OSDN Git Service

PR target/28014:
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.md
1 ;;- Machine description for Renesas / SuperH SH.
2 ;;  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3 ;;  2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4 ;;  Contributed by Steve Chamberlain (sac@cygnus.com).
5 ;;  Improved by Jim Wilson (wilson@cygnus.com).
6
7 ;; This file is part of GCC.
8
9 ;; GCC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GCC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 ;; Boston, MA 02110-1301, USA.
23
24
25 ;; ??? Should prepend a * to all pattern names which are not used.
26 ;; This will make the compiler smaller, and rebuilds after changes faster.
27
28 ;; ??? Should be enhanced to include support for many more GNU superoptimizer
29 ;; sequences.  Especially the sequences for arithmetic right shifts.
30
31 ;; ??? Should check all DImode patterns for consistency and usefulness.
32
33 ;; ??? The MAC.W and MAC.L instructions are not supported.  There is no
34 ;; way to generate them.
35
36 ;; ??? The cmp/str instruction is not supported.  Perhaps it can be used
37 ;; for a str* inline function.
38
39 ;; BSR is not generated by the compiler proper, but when relaxing, it
40 ;; generates .uses pseudo-ops that allow linker relaxation to create
41 ;; BSR.  This is actually implemented in bfd/{coff,elf32}-sh.c
42
43 ;; Special constraints for SH machine description:
44 ;;
45 ;;    t -- T
46 ;;    x -- mac
47 ;;    l -- pr
48 ;;    z -- r0
49 ;;
50 ;; Special formats used for outputting SH instructions:
51 ;;
52 ;;   %.  --  print a .s if insn needs delay slot
53 ;;   %@  --  print rte/rts if is/isn't an interrupt function
54 ;;   %#  --  output a nop if there is nothing to put in the delay slot
55 ;;   %O  --  print a constant without the #
56 ;;   %R  --  print the lsw reg of a double
57 ;;   %S  --  print the msw reg of a double
58 ;;   %T  --  print next word of a double REG or MEM
59 ;;
60 ;; Special predicates:
61 ;;
62 ;;  arith_operand          -- operand is valid source for arithmetic op
63 ;;  arith_reg_operand      -- operand is valid register for arithmetic op
64 ;;  general_movdst_operand -- operand is valid move destination
65 ;;  general_movsrc_operand -- operand is valid move source
66 ;;  logical_operand        -- operand is valid source for logical op
67
68 ;; -------------------------------------------------------------------------
69 ;; Constants
70 ;; -------------------------------------------------------------------------
71
72 (define_constants [
73   (AP_REG       145)
74   (PR_REG       146)
75   (T_REG        147)
76   (GBR_REG      144)
77   (MACH_REG     148)
78   (MACL_REG     149)
79   (FPUL_REG     150)
80   (RAP_REG      152)
81
82   (FPSCR_REG    151)
83
84   (PIC_REG      12)
85   (FP_REG       14)
86   (SP_REG       15)
87
88   (PR_MEDIA_REG 18)
89   (T_MEDIA_REG  19)
90
91   (R0_REG       0)
92   (R1_REG       1)
93   (R2_REG       2)
94   (R3_REG       3)
95   (R4_REG       4)
96   (R5_REG       5)
97   (R6_REG       6)
98   (R7_REG       7)
99   (R8_REG       8)
100   (R9_REG       9)
101   (R10_REG      10)
102   (R20_REG      20)
103   (R21_REG      21)
104   (R22_REG      22)
105   (R23_REG      23)
106
107   (DR0_REG      64)
108   (DR2_REG      66)
109   (DR4_REG      68)
110   (FR23_REG     87)
111
112   (TR0_REG      128)
113   (TR1_REG      129)
114   (TR2_REG      130)
115
116   (XD0_REG      136)
117
118   ;; These are used with unspec.
119   (UNSPEC_COMPACT_ARGS  0)
120   (UNSPEC_MOVA          1)
121   (UNSPEC_CASESI        2)
122   (UNSPEC_DATALABEL     3)
123   (UNSPEC_BBR           4)
124   (UNSPEC_SFUNC         5)
125   (UNSPEC_PIC           6)
126   (UNSPEC_GOT           7)
127   (UNSPEC_GOTOFF        8)
128   (UNSPEC_PLT           9)
129   (UNSPEC_CALLER        10)
130   (UNSPEC_GOTPLT        11)
131   (UNSPEC_ICACHE        12)
132   (UNSPEC_INIT_TRAMP    13)
133   (UNSPEC_FCOSA         14)
134   (UNSPEC_FSRRA         15)
135   (UNSPEC_FSINA         16)
136   (UNSPEC_NSB           17)
137   (UNSPEC_ALLOCO        18)
138   (UNSPEC_EH_RETURN     19)
139   (UNSPEC_TLSGD         20)
140   (UNSPEC_TLSLDM        21)
141   (UNSPEC_TLSIE         22)
142   (UNSPEC_DTPOFF        23)
143   (UNSPEC_GOTTPOFF      24)
144   (UNSPEC_TPOFF         25)
145   (UNSPEC_RA            26)
146   (UNSPEC_DIV_INV_M0    30)
147   (UNSPEC_DIV_INV_M1    31)
148   (UNSPEC_DIV_INV_M2    32)
149   (UNSPEC_DIV_INV_M3    33)
150   (UNSPEC_DIV_INV20     34)
151   (UNSPEC_ASHIFTRT      35)
152   (UNSPEC_THUNK         36)
153   (UNSPEC_SP_SET        40)
154   (UNSPEC_SP_TEST       41)
155
156   ;; These are used with unspec_volatile.
157   (UNSPECV_BLOCKAGE     0)
158   (UNSPECV_ALIGN        1)
159   (UNSPECV_CONST2       2)
160   (UNSPECV_CONST4       4)
161   (UNSPECV_CONST8       6)
162   (UNSPECV_WINDOW_END   10)
163   (UNSPECV_CONST_END    11)
164 ])
165
166 ;; -------------------------------------------------------------------------
167 ;; Attributes
168 ;; -------------------------------------------------------------------------
169
170 ;; Target CPU.
171
172 (define_attr "cpu"
173  "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
174   (const (symbol_ref "sh_cpu_attr")))
175
176 (define_attr "endian" "big,little"
177  (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
178                       (const_string "little") (const_string "big"))))
179
180 ;; Indicate if the default fpu mode is single precision.
181 (define_attr "fpu_single" "yes,no"
182   (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
183                          (const_string "yes") (const_string "no"))))
184
185 (define_attr "fmovd" "yes,no"
186   (const (if_then_else (symbol_ref "TARGET_FMOVD")
187                        (const_string "yes") (const_string "no"))))
188 ;; pipeline model
189 (define_attr "pipe_model" "sh1,sh4,sh5media"
190   (const
191    (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
192           (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
193          (const_string "sh1"))))
194
195 ;; cbranch      conditional branch instructions
196 ;; jump         unconditional jumps
197 ;; arith        ordinary arithmetic
198 ;; arith3       a compound insn that behaves similarly to a sequence of
199 ;;              three insns of type arith
200 ;; arith3b      like above, but might end with a redirected branch
201 ;; load         from memory
202 ;; load_si      Likewise, SImode variant for general register.
203 ;; fload        Likewise, but load to fp register.
204 ;; store        to memory
205 ;; move         general purpose register to register
206 ;; mt_group     other sh4 mt instructions
207 ;; fmove        register to register, floating point
208 ;; smpy         word precision integer multiply
209 ;; dmpy         longword or doublelongword precision integer multiply
210 ;; return       rts
211 ;; pload        load of pr reg, which can't be put into delay slot of rts
212 ;; prset        copy register to pr reg, ditto
213 ;; pstore       store of pr reg, which can't be put into delay slot of jsr
214 ;; prget        copy pr to register, ditto
215 ;; pcload       pc relative load of constant value
216 ;; pcfload      Likewise, but load to fp register.
217 ;; pcload_si    Likewise, SImode variant for general register.
218 ;; rte          return from exception
219 ;; sfunc        special function call with known used registers
220 ;; call         function call
221 ;; fp           floating point
222 ;; fdiv         floating point divide (or square root)
223 ;; gp_fpul      move from general purpose register to fpul
224 ;; fpul_gp      move from fpul to general purpose register
225 ;; mac_gp       move from mac[lh] to general purpose register
226 ;; dfp_arith, dfp_cmp,dfp_conv
227 ;; ftrc_s       fix_truncsfsi2_i4
228 ;; dfdiv        double precision floating point divide (or square root)
229 ;; cwb          ic_invalidate_line_i
230 ;; movua        SH4a unaligned load
231 ;; fsrra        square root reciprocal approximate
232 ;; fsca         sine and cosine approximate
233 ;; tls_load     load TLS related address
234 ;; arith_media  SHmedia arithmetic, logical, and shift instructions
235 ;; cbranch_media SHmedia conditional branch instructions
236 ;; cmp_media    SHmedia compare instructions
237 ;; dfdiv_media  SHmedia double precision divide and square root
238 ;; dfmul_media  SHmedia double precision multiply instruction
239 ;; dfparith_media SHmedia double precision floating point arithmetic
240 ;; dfpconv_media SHmedia double precision floating point conversions
241 ;; dmpy_media   SHmedia longword multiply
242 ;; fcmp_media   SHmedia floating point compare instructions
243 ;; fdiv_media   SHmedia single precision divide and square root
244 ;; fload_media  SHmedia floating point register load instructions
245 ;; fmove_media  SHmedia floating point register moves (inc. fabs and fneg)
246 ;; fparith_media SHmedia single precision floating point arithmetic
247 ;; fpconv_media SHmedia single precision floating point conversions
248 ;; fstore_media SHmedia floating point register store instructions
249 ;; gettr_media  SHmedia gettr instruction
250 ;; invalidate_line_media SHmedia invalidate_line sequence
251 ;; jump_media   SHmedia unconditional branch instructions
252 ;; load_media   SHmedia general register load instructions
253 ;; pt_media     SHmedia pt instruction (expanded by assembler)
254 ;; ptabs_media  SHmedia ptabs instruction
255 ;; store_media  SHmedia general register store instructions
256 ;; mcmp_media   SHmedia multimedia compare, absolute, saturating ops
257 ;; mac_media    SHmedia mac-style fixed point operations
258 ;; d2mpy_media  SHmedia: two 32 bit integer multiplies
259 ;; atrans_media SHmedia approximate transcendental functions
260 ;; ustore_media SHmedia unaligned stores
261 ;; nil          no-op move, will be deleted.
262
263 (define_attr "type"
264  "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fdiv,ftrc_s,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other"
265   (const_string "other"))
266
267 ;; We define a new attribute namely "insn_class".We use
268 ;; this for the DFA based pipeline description.
269 ;;
270 ;; mt_group      SH4 "mt" group instructions.
271 ;;
272 ;; ex_group      SH4 "ex" group instructions.
273 ;;
274 ;; ls_group      SH4 "ls" group instructions.
275 ;;
276
277 (define_attr "insn_class"
278   "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
279   (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
280          (eq_attr "type" "arith,dyn_shift") (const_string "ex_group")
281          (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,gp_fpul,fpul_gp") (const_string "ls_group")
282          (eq_attr "type" "cbranch,jump") (const_string "br_group")
283          (eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
284            (const_string "fe_group")
285          (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb") (const_string "co_group")]
286         (const_string "none")))
287 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
288 ;; so these do not belong in an insn group, although they are modeled
289 ;; with their own define_insn_reservations.
290
291 ;; Indicate what precision must be selected in fpscr for this insn, if any.
292
293 (define_attr "fp_mode" "single,double,none" (const_string "none"))
294
295 ;; Indicate if the fpu mode is set by this instruction
296 ;; "unknown" must have the value as "none" in fp_mode, and means
297 ;; that the instruction/abi has left the processor in an unknown
298 ;; state.
299 ;; "none" means that nothing has changed and no mode is set.
300 ;; This attribute is only used for the Renesas ABI.
301 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
302
303 ; If a conditional branch destination is within -252..258 bytes away
304 ; from the instruction it can be 2 bytes long.  Something in the
305 ; range -4090..4100 bytes can be 6 bytes long.  All other conditional
306 ; branches are initially assumed to be 16 bytes long.
307 ; In machine_dependent_reorg, we split all branches that are longer than
308 ; 2 bytes.
309
310 ;; The maximum range used for SImode constant pool entries is 1018.  A final
311 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
312 ;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
313 ;; instruction around the pool table, 2 bytes of alignment before the table,
314 ;; and 30 bytes of alignment after the table.  That gives a maximum total
315 ;; pool size of 1058 bytes.
316 ;; Worst case code/pool content size ratio is 1:2 (using asms).
317 ;; Thus, in the worst case, there is one instruction in front of a maximum
318 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
319 ;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
320 ;; If we have a forward branch, the initial table will be put after the
321 ;; unconditional branch.
322 ;;
323 ;; ??? We could do much better by keeping track of the actual pcloads within
324 ;; the branch range and in the pcload range in front of the branch range.
325
326 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
327 ;; inside an le.
328 (define_attr "short_cbranch_p" "no,yes"
329   (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
330          (const_string "no")
331          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
332          (const_string "yes")
333          (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
334          (const_string "no")
335          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
336          (const_string "yes")
337          ] (const_string "no")))
338
339 (define_attr "med_branch_p" "no,yes"
340   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
341               (const_int 1988))
342          (const_string "yes")
343          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
344          (const_string "no")
345          (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
346               (const_int 8186))
347          (const_string "yes")
348          ] (const_string "no")))
349
350 (define_attr "med_cbranch_p" "no,yes"
351   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
352               (const_int 1986))
353          (const_string "yes")
354          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
355          (const_string "no")
356          (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
357                (const_int 8184))
358          (const_string "yes")
359          ] (const_string "no")))
360
361 (define_attr "braf_branch_p" "no,yes"
362   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
363          (const_string "no")
364          (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
365               (const_int 20660))
366          (const_string "yes")
367          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
368          (const_string "no")
369          (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
370               (const_int 65530))
371          (const_string "yes")
372          ] (const_string "no")))
373
374 (define_attr "braf_cbranch_p" "no,yes"
375   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
376          (const_string "no")
377          (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
378               (const_int 20658))
379          (const_string "yes")
380          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
381          (const_string "no")
382          (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
383               (const_int 65528))
384          (const_string "yes")
385          ] (const_string "no")))
386
387 ; An unconditional jump in the range -4092..4098 can be 2 bytes long.
388 ; For wider ranges, we need a combination of a code and a data part.
389 ; If we can get a scratch register for a long range jump, the code
390 ; part can be 4 bytes long; otherwise, it must be 8 bytes long.
391 ; If the jump is in the range -32764..32770, the data part can be 2 bytes
392 ; long; otherwise, it must be 6 bytes long.
393
394 ; All other instructions are two bytes long by default.
395
396 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
397 ;; but getattrtab doesn't understand this.
398 (define_attr "length" ""
399   (cond [(eq_attr "type" "cbranch")
400          (cond [(eq_attr "short_cbranch_p" "yes")
401                 (const_int 2)
402                 (eq_attr "med_cbranch_p" "yes")
403                 (const_int 6)
404                 (eq_attr "braf_cbranch_p" "yes")
405                 (const_int 12)
406 ;; ??? using pc is not computed transitively.
407                 (ne (match_dup 0) (match_dup 0))
408                 (const_int 14)
409                 (ne (symbol_ref ("flag_pic")) (const_int 0))
410                 (const_int 24)
411                 ] (const_int 16))
412          (eq_attr "type" "jump")
413          (cond [(eq_attr "med_branch_p" "yes")
414                 (const_int 2)
415                 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
416                          (symbol_ref "INSN"))
417                      (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
418                          (symbol_ref "code_for_indirect_jump_scratch")))
419                 (cond [(eq_attr "braf_branch_p" "yes")
420                        (const_int 6)
421                        (eq (symbol_ref "flag_pic") (const_int 0))
422                        (const_int 10)
423                        (ne (symbol_ref "TARGET_SH2") (const_int 0))
424                        (const_int 10)] (const_int 18))
425                 (eq_attr "braf_branch_p" "yes")
426                 (const_int 10)
427 ;; ??? using pc is not computed transitively.
428                 (ne (match_dup 0) (match_dup 0))
429                 (const_int 12)
430                 (ne (symbol_ref ("flag_pic")) (const_int 0))
431                 (const_int 22)
432                 ] (const_int 14))
433          (eq_attr "type" "pt_media")
434          (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
435                        (const_int 20) (const_int 12))
436          (and (eq_attr "type" "jump_media")
437               (ne (symbol_ref "TARGET_SH5_CUT2_WORKAROUND") (const_int 0)))
438          (const_int 8)
439          ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
440                          (const_int 4)
441                          (const_int 2))))
442
443 ;; DFA descriptions for the pipelines
444
445 (include "sh1.md")
446 (include "shmedia.md")
447 (include "sh4.md")
448
449 (include "predicates.md")
450
451 ;; Definitions for filling delay slots
452
453 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
454
455 ;; ??? This should be (nil) instead of (const_int 0)
456 (define_attr "hit_stack" "yes,no"
457         (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
458                    (const_int 0))
459                (const_string "no")]
460               (const_string "yes")))
461
462 (define_attr "interrupt_function" "no,yes"
463   (const (symbol_ref "current_function_interrupt")))
464
465 (define_attr "in_delay_slot" "yes,no"
466   (cond [(eq_attr "type" "cbranch") (const_string "no")
467          (eq_attr "type" "pcload,pcload_si") (const_string "no")
468          (eq_attr "needs_delay_slot" "yes") (const_string "no")
469          (eq_attr "length" "2") (const_string "yes")
470          ] (const_string "no")))
471
472 (define_attr "cond_delay_slot" "yes,no"
473   (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
474          ] (const_string "no")))
475
476 (define_attr "is_sfunc" ""
477   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
478
479 (define_attr "is_mac_media" ""
480   (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
481
482 (define_attr "branch_zero" "yes,no"
483   (cond [(eq_attr "type" "!cbranch") (const_string "no")
484          (ne (symbol_ref "(next_active_insn (insn)\
485                            == (prev_active_insn\
486                                (XEXP (SET_SRC (PATTERN (insn)), 1))))\
487                           && get_attr_length (next_active_insn (insn)) == 2")
488              (const_int 0))
489          (const_string "yes")]
490         (const_string "no")))
491
492 ;; SH4 Double-precision computation with double-precision result -
493 ;; the two halves are ready at different times.
494 (define_attr "dfp_comp" "yes,no"
495   (cond [(eq_attr "type" "dfp_arith,dfp_conv,dfdiv") (const_string "yes")]
496         (const_string "no")))
497
498 ;; Insns for which the latency of a preceding fp insn is decreased by one.
499 (define_attr "late_fp_use" "yes,no" (const_string "no"))
500 ;; And feeding insns for which this relevant.
501 (define_attr "any_fp_comp" "yes,no"
502   (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
503          (const_string "yes")]
504         (const_string "no")))
505
506 (define_attr "any_int_load" "yes,no"
507   (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
508          (const_string "yes")]
509         (const_string "no")))
510
511 (define_attr "highpart" "user, ignore, extend, depend, must_split"
512   (const_string "user"))
513
514 (define_delay
515   (eq_attr "needs_delay_slot" "yes")
516   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
517
518 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
519 ;; and thus we can't put a pop instruction in its delay slot.
520 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
521 ;; instruction can go in the delay slot.
522
523 ;; Since a normal return (rts) implicitly uses the PR register,
524 ;; we can't allow PR register loads in an rts delay slot.
525
526 (define_delay
527   (eq_attr "type" "return")
528   [(and (eq_attr "in_delay_slot" "yes")
529         (ior (and (eq_attr "interrupt_function" "no")
530                   (eq_attr "type" "!pload,prset"))
531              (and (eq_attr "interrupt_function" "yes")
532                   (ior
533                    (ne (symbol_ref "TARGET_SH3") (const_int 0))
534                    (eq_attr "hit_stack" "no"))))) (nil) (nil)])
535
536 ;; Since a call implicitly uses the PR register, we can't allow
537 ;; a PR register store in a jsr delay slot.
538
539 (define_delay
540   (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
541   [(and (eq_attr "in_delay_slot" "yes")
542         (eq_attr "type" "!pstore,prget")) (nil) (nil)])
543
544 ;; Say that we have annulled true branches, since this gives smaller and
545 ;; faster code when branches are predicted as not taken.
546
547 ;; ??? The non-annulled condition should really be "in_delay_slot",
548 ;; but insns that can be filled in non-annulled get priority over insns
549 ;; that can only be filled in anulled.
550
551 (define_delay
552   (and (eq_attr "type" "cbranch")
553        (ne (symbol_ref "TARGET_SH2") (const_int 0)))
554   ;; SH2e has a hardware bug that pretty much prohibits the use of
555   ;; annuled delay slots.
556   [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
557                                           (not (eq_attr "cpu" "sh2e"))) (nil)])
558 \f
559 ;; -------------------------------------------------------------------------
560 ;; SImode signed integer comparisons
561 ;; -------------------------------------------------------------------------
562
563 (define_insn ""
564   [(set (reg:SI T_REG)
565         (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
566                        (match_operand:SI 1 "arith_operand" "K08,r"))
567                (const_int 0)))]
568   "TARGET_SH1"
569   "tst  %1,%0"
570   [(set_attr "type" "mt_group")])
571
572 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
573 ;; That would still allow reload to create cmpi instructions, but would
574 ;; perhaps allow forcing the constant into a register when that is better.
575 ;; Probably should use r0 for mem/imm compares, but force constant into a
576 ;; register for pseudo/imm compares.
577
578 (define_insn "cmpeqsi_t"
579   [(set (reg:SI T_REG)
580         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
581                (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
582   "TARGET_SH1"
583   "@
584         tst     %0,%0
585         cmp/eq  %1,%0
586         cmp/eq  %1,%0"
587    [(set_attr "type" "mt_group")])
588
589 (define_insn "cmpgtsi_t"
590   [(set (reg:SI T_REG)
591         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
592                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
593   "TARGET_SH1"
594   "@
595         cmp/gt  %1,%0
596         cmp/pl  %0"
597    [(set_attr "type" "mt_group")])
598
599 (define_insn "cmpgesi_t"
600   [(set (reg:SI T_REG)
601         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
602                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
603   "TARGET_SH1"
604   "@
605         cmp/ge  %1,%0
606         cmp/pz  %0"
607    [(set_attr "type" "mt_group")])
608
609 ;; -------------------------------------------------------------------------
610 ;; SImode unsigned integer comparisons
611 ;; -------------------------------------------------------------------------
612
613 (define_insn "cmpgeusi_t"
614   [(set (reg:SI T_REG)
615         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
616                 (match_operand:SI 1 "arith_reg_operand" "r")))]
617   "TARGET_SH1"
618   "cmp/hs       %1,%0"
619    [(set_attr "type" "mt_group")])
620
621 (define_insn "cmpgtusi_t"
622   [(set (reg:SI T_REG)
623         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
624                 (match_operand:SI 1 "arith_reg_operand" "r")))]
625   "TARGET_SH1"
626   "cmp/hi       %1,%0"
627    [(set_attr "type" "mt_group")])
628
629 ;; We save the compare operands in the cmpxx patterns and use them when
630 ;; we generate the branch.
631
632 (define_expand "cmpsi"
633   [(set (reg:SI T_REG)
634         (compare (match_operand:SI 0 "cmpsi_operand" "")
635                  (match_operand:SI 1 "arith_operand" "")))]
636   "TARGET_SH1 || TARGET_SHMEDIA"
637   "
638 {
639   if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG
640       && GET_CODE (operands[1]) != CONST_INT)
641     operands[0] = copy_to_mode_reg (SImode, operands[0]);
642   sh_compare_op0 = operands[0];
643   sh_compare_op1 = operands[1];
644   DONE;
645 }")
646 \f
647 ;; -------------------------------------------------------------------------
648 ;; DImode signed integer comparisons
649 ;; -------------------------------------------------------------------------
650
651 ;; ??? Could get better scheduling by splitting the initial test from the
652 ;; rest of the insn after reload.  However, the gain would hardly justify
653 ;; the sh.md size increase necessary to do that.
654
655 (define_insn ""
656   [(set (reg:SI T_REG)
657         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
658                        (match_operand:DI 1 "arith_operand" "r"))
659                (const_int 0)))]
660   "TARGET_SH1"
661   "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
662                                  insn, operands);"
663   [(set_attr "length" "6")
664    (set_attr "type" "arith3b")])
665
666 (define_insn "cmpeqdi_t"
667   [(set (reg:SI T_REG)
668         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
669                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
670   "TARGET_SH1"
671   "@
672         tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
673         cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
674   [(set_attr "length" "6")
675    (set_attr "type" "arith3b")])
676
677 (define_split
678   [(set (reg:SI T_REG)
679         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
680                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
681 ;; If we applied this split when not optimizing, it would only be
682 ;; applied during the machine-dependent reorg, when no new basic blocks
683 ;; may be created.
684   "TARGET_SH1 && reload_completed && optimize"
685   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
686    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
687                            (label_ref (match_dup 6))
688                            (pc)))
689    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
690    (match_dup 6)]
691   "
692 {
693   operands[2]
694     = gen_rtx_REG (SImode,
695                    true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
696   operands[3]
697     = (operands[1] == const0_rtx
698        ? const0_rtx
699        : gen_rtx_REG (SImode,
700                       true_regnum (operands[1])
701                       + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
702   operands[4] = gen_lowpart (SImode, operands[0]);
703   operands[5] = gen_lowpart (SImode, operands[1]);
704   operands[6] = gen_label_rtx ();
705 }")
706
707 (define_insn "cmpgtdi_t"
708   [(set (reg:SI T_REG)
709         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
710                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
711   "TARGET_SH2"
712   "@
713         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
714         tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
715   [(set_attr "length" "8")
716    (set_attr "type" "arith3")])
717
718 (define_insn "cmpgedi_t"
719   [(set (reg:SI T_REG)
720         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
721                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
722   "TARGET_SH2"
723   "@
724         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
725         cmp/pz\\t%S0"
726   [(set_attr "length" "8,2")
727    (set_attr "type" "arith3,mt_group")])
728 \f
729 ;; -------------------------------------------------------------------------
730 ;; DImode unsigned integer comparisons
731 ;; -------------------------------------------------------------------------
732
733 (define_insn "cmpgeudi_t"
734   [(set (reg:SI T_REG)
735         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
736                 (match_operand:DI 1 "arith_reg_operand" "r")))]
737   "TARGET_SH2"
738   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
739   [(set_attr "length" "8")
740    (set_attr "type" "arith3")])
741
742 (define_insn "cmpgtudi_t"
743   [(set (reg:SI T_REG)
744         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
745                 (match_operand:DI 1 "arith_reg_operand" "r")))]
746   "TARGET_SH2"
747   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
748   [(set_attr "length" "8")
749    (set_attr "type" "arith3")])
750
751 (define_insn "cmpeqsi_media"
752   [(set (match_operand:DI 0 "register_operand" "=r")
753         (eq:DI (match_operand:SI 1 "logical_operand" "%r")
754                (match_operand:SI 2 "cmp_operand" "Nr")))]
755   "TARGET_SHMEDIA"
756   "cmpeq        %1, %N2, %0"
757   [(set_attr "type" "cmp_media")])
758
759 (define_insn "cmpeqdi_media"
760   [(set (match_operand:DI 0 "register_operand" "=r")
761         (eq:DI (match_operand:DI 1 "register_operand" "%r")
762                (match_operand:DI 2 "cmp_operand" "Nr")))]
763   "TARGET_SHMEDIA"
764   "cmpeq        %1, %N2, %0"
765   [(set_attr "type" "cmp_media")])
766
767 (define_insn "cmpgtsi_media"
768   [(set (match_operand:DI 0 "register_operand" "=r")
769         (gt:DI (match_operand:SI 1 "cmp_operand" "Nr")
770                (match_operand:SI 2 "cmp_operand" "rN")))]
771   "TARGET_SHMEDIA"
772   "cmpgt        %N1, %N2, %0"
773   [(set_attr "type" "cmp_media")])
774
775 (define_insn "cmpgtdi_media"
776   [(set (match_operand:DI 0 "register_operand" "=r")
777         (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
778                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
779   "TARGET_SHMEDIA"
780   "cmpgt        %N1, %N2, %0"
781   [(set_attr "type" "cmp_media")])
782
783 (define_insn "cmpgtusi_media"
784   [(set (match_operand:DI 0 "register_operand" "=r")
785         (gtu:DI (match_operand:SI 1 "cmp_operand" "Nr")
786                 (match_operand:SI 2 "cmp_operand" "rN")))]
787   "TARGET_SHMEDIA"
788   "cmpgtu       %N1, %N2, %0"
789   [(set_attr "type" "cmp_media")])
790
791 (define_insn "cmpgtudi_media"
792   [(set (match_operand:DI 0 "register_operand" "=r")
793         (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
794                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
795   "TARGET_SHMEDIA"
796   "cmpgtu       %N1, %N2, %0"
797   [(set_attr "type" "cmp_media")])
798
799 (define_insn "cmpsieqsi_media"
800   [(set (match_operand:SI 0 "register_operand" "=r")
801         (eq:SI (match_operand:SI 1 "logical_operand" "%r")
802                (match_operand:SI 2 "cmp_operand" "Nr")))]
803   "TARGET_SHMEDIA"
804   "cmpeq        %1, %N2, %0"
805   [(set_attr "type" "cmp_media")])
806
807 (define_insn "cmpsieqdi_media"
808   [(set (match_operand:SI 0 "register_operand" "=r")
809         (eq:SI (match_operand:DI 1 "register_operand" "%r")
810                (match_operand:DI 2 "cmp_operand" "Nr")))]
811   "TARGET_SHMEDIA"
812   "cmpeq        %1, %N2, %0"
813   [(set_attr "type" "cmp_media")])
814
815 (define_insn "cmpsigtsi_media"
816   [(set (match_operand:SI 0 "register_operand" "=r")
817         (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
818                (match_operand:SI 2 "cmp_operand" "rN")))]
819   "TARGET_SHMEDIA"
820   "cmpgt        %N1, %N2, %0"
821   [(set_attr "type" "cmp_media")])
822
823 (define_insn "cmpsigtdi_media"
824   [(set (match_operand:SI 0 "register_operand" "=r")
825         (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
826                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
827   "TARGET_SHMEDIA"
828   "cmpgt        %N1, %N2, %0"
829   [(set_attr "type" "cmp_media")])
830
831 (define_insn "cmpsigtusi_media"
832   [(set (match_operand:SI 0 "register_operand" "=r")
833         (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
834                 (match_operand:SI 2 "cmp_operand" "rN")))]
835   "TARGET_SHMEDIA"
836   "cmpgtu       %N1, %N2, %0"
837   [(set_attr "type" "cmp_media")])
838
839 (define_insn "cmpsigtudi_media"
840   [(set (match_operand:SI 0 "register_operand" "=r")
841         (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
842                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
843   "TARGET_SHMEDIA"
844   "cmpgtu       %N1, %N2, %0"
845   [(set_attr "type" "cmp_media")])
846
847 ; These two patterns are for combine.
848 (define_insn "*cmpne0si_media"
849   [(set (match_operand:DI 0 "register_operand" "=r")
850         (ne:DI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
851   "TARGET_SHMEDIA"
852   "cmpgtu       %1,r63,%0"
853   [(set_attr "type" "cmp_media")])
854
855 (define_insn "*cmpne0sisi_media"
856   [(set (match_operand:SI 0 "register_operand" "=r")
857         (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
858   "TARGET_SHMEDIA"
859   "cmpgtu       %1,r63,%0"
860   [(set_attr "type" "cmp_media")])
861
862 ;; We save the compare operands in the cmpxx patterns and use them when
863 ;; we generate the branch.
864
865 (define_expand "cmpdi"
866   [(set (reg:SI T_REG)
867         (compare (match_operand:DI 0 "arith_operand" "")
868                  (match_operand:DI 1 "arith_operand" "")))]
869   "TARGET_SH2 || TARGET_SHMEDIA"
870   "
871 {
872   sh_compare_op0 = operands[0];
873   sh_compare_op1 = operands[1];
874   DONE;
875 }")
876 ;; -------------------------------------------------------------------------
877 ;; Conditional move instructions
878 ;; -------------------------------------------------------------------------
879
880 ;; The insn names may seem reversed, but note that cmveq performs the move
881 ;; if op1 == 0, and cmvne does it if op1 != 0.
882
883 (define_insn "movdicc_false"
884   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
885         (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
886                              (const_int 0))
887          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
888          (match_operand:DI 3 "arith_reg_operand" "0")))]
889   "TARGET_SHMEDIA"
890   "cmveq        %1, %N2, %0"
891   [(set_attr "type" "arith_media")])
892
893 (define_insn "movdicc_true"
894   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
895         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
896                              (const_int 0))
897          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
898          (match_operand:DI 3 "arith_reg_operand" "0")))]
899   "TARGET_SHMEDIA"
900   "cmvne        %1, %N2, %0"
901   [(set_attr "type" "arith_media")])
902
903 (define_peephole2
904   [(set (match_operand:DI 0 "arith_reg_dest" "")
905         (if_then_else:DI (match_operator 3 "equality_comparison_operator"
906                            [(match_operand:DI 1 "arith_reg_operand" "")
907                             (const_int 0)])
908          (match_operand:DI 2 "arith_reg_dest" "")
909          (match_dup 0)))
910    (set (match_dup 2) (match_dup 0))]
911   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
912   [(set (match_dup 2)
913         (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
914   "
915 {
916   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
917                                 VOIDmode, operands[1], CONST0_RTX (DImode));
918 }")
919
920 (define_peephole2
921   [(set (match_operand:DI 0 "general_movdst_operand" "")
922         (match_operand:DI 1 "arith_reg_or_0_operand" ""))
923    (set (match_operand:DI 2 "arith_reg_dest" "")
924         (if_then_else:DI (match_operator 4 "equality_comparison_operator"
925                            [(match_operand:DI 3 "arith_reg_operand" "")
926                             (const_int 0)])
927          (match_dup 0)
928          (match_dup 2)))]
929   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
930   [(set (match_dup 2)
931         (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
932   "")
933
934 (define_expand "movdicc"
935   [(set (match_operand:DI 0 "register_operand" "")
936         (if_then_else:DI (match_operand 1 "comparison_operator" "")
937                          (match_operand:DI 2 "register_operand" "")
938                          (match_operand:DI 3 "register_operand" "")))]
939   "TARGET_SHMEDIA"
940   "
941 {
942   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
943       && GET_MODE (sh_compare_op0) == DImode
944       && sh_compare_op1 == const0_rtx)
945     operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
946                                   sh_compare_op0, sh_compare_op1);
947   else
948     {
949       rtx tmp;
950
951       if (no_new_pseudos)
952         FAIL;
953
954       tmp = gen_reg_rtx (DImode);
955
956       switch (GET_CODE (operands[1]))
957         {
958         case EQ:
959           emit_insn (gen_seq (tmp));
960           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
961           break;
962
963         case NE:
964           emit_insn (gen_seq (tmp));
965           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
966           break;
967
968         case GT:
969           emit_insn (gen_sgt (tmp));
970           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
971           break;
972
973         case LT:
974           emit_insn (gen_slt (tmp));
975           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
976           break;
977
978         case GE:
979           emit_insn (gen_slt (tmp));
980           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
981           break;
982
983         case LE:
984           emit_insn (gen_sgt (tmp));
985           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
986           break;
987
988         case GTU:
989           emit_insn (gen_sgtu (tmp));
990           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
991           break;
992
993         case LTU:
994           emit_insn (gen_sltu (tmp));
995           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
996           break;
997
998         case GEU:
999           emit_insn (gen_sltu (tmp));
1000           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1001           break;
1002
1003         case LEU:
1004           emit_insn (gen_sgtu (tmp));
1005           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1006           break;
1007
1008         case UNORDERED:
1009           emit_insn (gen_sunordered (tmp));
1010           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1011           break;
1012
1013         case ORDERED:
1014           emit_insn (gen_sunordered (tmp));
1015           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1016           break;
1017
1018         case UNEQ:
1019         case UNGE:
1020         case UNGT:
1021         case UNLE:
1022         case UNLT:
1023         case LTGT:
1024           FAIL;
1025
1026         default:
1027           gcc_unreachable ();
1028         }
1029     }
1030 }")
1031
1032 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1033 ;; SImode to DImode.
1034 (define_insn "movsicc_false"
1035   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1036         (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1037                           (const_int 0))
1038          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1039          (match_operand:SI 3 "arith_reg_operand" "0")))]
1040   "TARGET_SHMEDIA"
1041   "cmveq        %1, %N2, %0"
1042   [(set_attr "type" "arith_media")])
1043
1044 (define_insn "movsicc_true"
1045   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1046         (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1047                           (const_int 0))
1048          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1049          (match_operand:SI 3 "arith_reg_operand" "0")))]
1050   "TARGET_SHMEDIA"
1051   "cmvne        %1, %N2, %0"
1052   [(set_attr "type" "arith_media")])
1053
1054 (define_peephole2
1055   [(set (match_operand:SI 0 "arith_reg_dest" "")
1056         (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1057                            [(match_operand:SI 1 "arith_reg_operand" "")
1058                             (const_int 0)])
1059          (match_operand:SI 2 "arith_reg_dest" "")
1060          (match_dup 0)))
1061    (set (match_dup 2) (match_dup 0))]
1062   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1063   [(set (match_dup 2)
1064         (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1065   "
1066 {
1067   operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1068                                 VOIDmode, operands[1], CONST0_RTX (SImode));
1069 }")
1070
1071 (define_peephole2
1072   [(set (match_operand:SI 0 "general_movdst_operand" "")
1073         (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1074    (set (match_operand:SI 2 "arith_reg_dest" "")
1075         (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1076                            [(match_operand:SI 3 "arith_reg_operand" "")
1077                             (const_int 0)])
1078          (match_dup 0)
1079          (match_dup 2)))]
1080   "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1081    && (GET_CODE (operands[1]) != REG || GENERAL_REGISTER_P (REGNO (operands[1])))"
1082   [(set (match_dup 2)
1083         (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1084   "
1085 {
1086   replace_rtx (operands[4], operands[0], operands[1]);
1087 }")
1088
1089 (define_peephole2
1090   [(set (match_operand 0 "any_register_operand" "")
1091         (match_operand 1 "any_register_operand" ""))
1092    (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1093    (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1094   "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1095     <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1096    && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1097    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1098    && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1099    && ! reg_overlap_mentioned_p (operands[0], operands[3])
1100    && ! reg_overlap_mentioned_p (operands[2], operands[0])
1101    && ! reg_overlap_mentioned_p (operands[0], operands[1])
1102    && (REGNO_REG_CLASS (REGNO (operands[0]))
1103        == REGNO_REG_CLASS (REGNO (operands[2])))
1104    && (REGNO_REG_CLASS (REGNO (operands[1]))
1105        == REGNO_REG_CLASS (REGNO (operands[0])))"
1106   [(set (match_dup 0) (match_dup 3))
1107    (set (match_dup 4) (match_dup 5))]
1108   "
1109 {
1110   rtx set1, set2;
1111   rtx replacements[4];
1112
1113   /* We want to replace occurrences of operands[0] with operands[1] and
1114      operands[2] with operands[0] in operands[4]/operands[5].
1115      Doing just two replace_rtx calls naively would result in the second
1116      replacement undoing all that the first did if operands[1] and operands[2]
1117      are identical, so we must do this simultaneously.  */
1118   replacements[0] = operands[0];
1119   replacements[1] = operands[1];
1120   replacements[2] = operands[2];
1121   replacements[3] = operands[0];
1122   if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1123       || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1124       || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1125     FAIL;
1126
1127   operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1128   replace_n_hard_rtx (operands[4], replacements, 2, 1);
1129   operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1130   /* The operands array is aliased to recog_data.operand, which gets
1131      clobbered by extract_insn, so finish with it now.  */
1132   set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1133   set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1134   /* ??? The last insn might be a jump insn, but the generic peephole2 code
1135      always uses emit_insn.  */
1136   /* Check that we don't violate matching constraints or earlyclobbers.  */
1137   extract_insn (emit_insn (set1));
1138   if (! constrain_operands (1))
1139     goto failure;
1140   extract_insn (emit (set2));
1141   if (! constrain_operands (1))
1142     {
1143       rtx tmp;
1144     failure:
1145       tmp = replacements[0];
1146       replacements[0] = replacements[1];
1147       replacements[1] = tmp;
1148       tmp = replacements[2];
1149       replacements[2] = replacements[3];
1150       replacements[3] = tmp;
1151       replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1152       replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1153       replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1154       FAIL;
1155     }
1156   DONE;
1157 }")
1158
1159 ;; The register allocator is rather clumsy in handling multi-way conditional
1160 ;; moves, so allow the combiner to make them, and we split them up after
1161 ;; reload.  */
1162 (define_insn_and_split "*movsicc_umin"
1163   [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1164         (umin:SI (if_then_else:SI
1165                    (eq (match_operand:SI 1 "arith_reg_operand" "r")
1166                        (const_int 0))
1167                    (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1168                    (match_operand:SI 3 "register_operand" "0"))
1169                  (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1170    (clobber (match_scratch:SI 5 "=&r"))]
1171   "TARGET_SHMEDIA && no_new_pseudos"
1172   "#"
1173   "TARGET_SHMEDIA && reload_completed"
1174   [(pc)]
1175   "
1176 {
1177   emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1178                                 operands[3]));
1179   emit_insn (gen_cmpsigtusi_media (operands[5], operands[4], operands[0]));
1180   emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1181                                 operands[0]));
1182   DONE;
1183 }")
1184
1185 (define_insn "*movsicc_t_false"
1186   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1187         (if_then_else (eq (reg:SI T_REG) (const_int 0))
1188                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1189                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1190   "TARGET_PRETEND_CMOVE
1191    && (arith_reg_operand (operands[1], SImode)
1192        || (immediate_operand (operands[1], SImode)
1193            && CONST_OK_FOR_I08 (INTVAL (operands[1]))))"
1194   "bt 0f\;mov %1,%0\\n0:"
1195   [(set_attr "type" "mt_group,arith") ;; poor approximation
1196    (set_attr "length" "4")])
1197
1198 (define_insn "*movsicc_t_true"
1199   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1200         (if_then_else (ne (reg:SI T_REG) (const_int 0))
1201                       (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1202                       (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1203   "TARGET_PRETEND_CMOVE
1204    && (arith_reg_operand (operands[1], SImode)
1205        || (immediate_operand (operands[1], SImode)
1206            && CONST_OK_FOR_I08 (INTVAL (operands[1]))))"
1207   "bf 0f\;mov %1,%0\\n0:"
1208   [(set_attr "type" "mt_group,arith") ;; poor approximation
1209    (set_attr "length" "4")])
1210
1211 (define_expand "movsicc"
1212   [(set (match_operand:SI 0 "arith_reg_dest" "")
1213         (if_then_else:SI (match_operand 1 "comparison_operator" "")
1214                          (match_operand:SI 2 "arith_reg_or_0_operand" "")
1215                          (match_operand:SI 3 "arith_reg_operand" "")))]
1216   "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1217   "
1218 {
1219   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1220       && GET_MODE (sh_compare_op0) == SImode
1221       && (TARGET_SHMEDIA
1222           || (REG_P (sh_compare_op0) && REGNO (sh_compare_op0) == T_REG))
1223       && sh_compare_op1 == const0_rtx)
1224     operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
1225                                   sh_compare_op0, sh_compare_op1);
1226   else if (TARGET_PRETEND_CMOVE)
1227     {
1228       enum rtx_code code = GET_CODE (operands[1]);
1229       enum rtx_code new_code = code;
1230       rtx tmp;
1231
1232       if (! currently_expanding_to_rtl)
1233         FAIL;
1234       switch (code)
1235         {
1236         case LT: case LE: case LEU: case LTU:
1237           if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) != MODE_INT)
1238             break;
1239         case NE:
1240           new_code = reverse_condition (code);
1241           break;
1242         case EQ: case GT: case GE: case GEU: case GTU:
1243           break;
1244         default:
1245           FAIL;
1246         }
1247       tmp = prepare_scc_operands (new_code);
1248       operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1249                                     tmp, const0_rtx);
1250     }
1251   else
1252     {
1253       rtx tmp;
1254
1255       if (no_new_pseudos)
1256         FAIL;
1257
1258       tmp = gen_reg_rtx (SImode);
1259
1260       switch (GET_CODE (operands[1]))
1261         {
1262         case EQ:
1263           emit_insn (gen_seq (tmp));
1264           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1265           break;
1266
1267         case NE:
1268           emit_insn (gen_seq (tmp));
1269           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1270           break;
1271
1272         case GT:
1273           emit_insn (gen_sgt (tmp));
1274           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1275           break;
1276
1277         case LT:
1278           emit_insn (gen_slt (tmp));
1279           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1280           break;
1281
1282         case GE:
1283           emit_insn (gen_slt (tmp));
1284           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1285           break;
1286
1287         case LE:
1288           emit_insn (gen_sgt (tmp));
1289           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1290           break;
1291
1292         case GTU:
1293           emit_insn (gen_sgtu (tmp));
1294           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1295           break;
1296
1297         case LTU:
1298           emit_insn (gen_sltu (tmp));
1299           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1300           break;
1301
1302         case GEU:
1303           emit_insn (gen_sltu (tmp));
1304           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1305           break;
1306
1307         case LEU:
1308           emit_insn (gen_sgtu (tmp));
1309           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1310           break;
1311
1312         case UNORDERED:
1313           emit_insn (gen_sunordered (tmp));
1314           operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
1315           break;
1316
1317         case ORDERED:
1318           emit_insn (gen_sunordered (tmp));
1319           operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
1320           break;
1321
1322         case UNEQ:
1323         case UNGE:
1324         case UNGT:
1325         case UNLE:
1326         case UNLT:
1327         case LTGT:
1328           FAIL;
1329
1330         default:
1331           abort ();
1332         }
1333     }
1334 }")
1335
1336 (define_expand "movqicc"
1337   [(set (match_operand:QI 0 "register_operand" "")
1338         (if_then_else:QI (match_operand 1 "comparison_operator" "")
1339                          (match_operand:QI 2 "register_operand" "")
1340                          (match_operand:QI 3 "register_operand" "")))]
1341   "TARGET_SHMEDIA"
1342   "
1343 {
1344   operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1345   operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1346   operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1347   emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1348   DONE;
1349 }")
1350 \f
1351 ;; -------------------------------------------------------------------------
1352 ;; Addition instructions
1353 ;; -------------------------------------------------------------------------
1354
1355 (define_expand "adddi3"
1356   [(set (match_operand:DI 0 "arith_reg_operand" "")
1357         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1358                  (match_operand:DI 2 "arith_operand" "")))]
1359   ""
1360   "
1361 {
1362   if (TARGET_SH1)
1363     {
1364       if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
1365         FAIL;
1366       operands[2] = force_reg (DImode, operands[2]);
1367       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1368       DONE;
1369     }
1370 }")
1371
1372 (define_insn "*adddi3_media"
1373   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1374         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1375                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1376   "TARGET_SHMEDIA"
1377   "@
1378         add     %1, %2, %0
1379         addi    %1, %2, %0"
1380   [(set_attr "type" "arith_media")])
1381
1382 (define_insn "*adddisi3_media"
1383   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1384         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1385                  (match_operand:DI 2 "arith_operand" "r,I10")))]
1386   "TARGET_SHMEDIA"
1387   "@
1388         add.l   %1, %2, %0
1389         addi.l  %1, %2, %0"
1390   [(set_attr "type" "arith_media")
1391    (set_attr "highpart" "ignore")])
1392
1393 (define_insn "adddi3z_media"
1394   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1395         (zero_extend:DI
1396          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1397                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1398   "TARGET_SHMEDIA"
1399   "addz.l       %1, %N2, %0"
1400   [(set_attr "type" "arith_media")
1401    (set_attr "highpart" "ignore")])
1402
1403 (define_insn "adddi3_compact"
1404   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1405         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1406                  (match_operand:DI 2 "arith_reg_operand" "r")))
1407    (clobber (reg:SI T_REG))]
1408   "TARGET_SH1"
1409   "#"
1410   [(set_attr "length" "6")])
1411
1412 (define_split
1413   [(set (match_operand:DI 0 "arith_reg_dest" "")
1414         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1415                  (match_operand:DI 2 "arith_reg_operand" "")))
1416    (clobber (reg:SI T_REG))]
1417   "TARGET_SH1 && reload_completed"
1418   [(const_int 0)]
1419   "
1420 {
1421   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1422   high0 = gen_rtx_REG (SImode,
1423                        true_regnum (operands[0])
1424                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1425   high2 = gen_rtx_REG (SImode,
1426                        true_regnum (operands[2])
1427                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1428   emit_insn (gen_clrt ());
1429   emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1430   emit_insn (gen_addc1 (high0, high0, high2));
1431   DONE;
1432 }")
1433
1434 (define_insn "addc"
1435   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1436         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1437                           (match_operand:SI 2 "arith_reg_operand" "r"))
1438                  (reg:SI T_REG)))
1439    (set (reg:SI T_REG)
1440         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1441   "TARGET_SH1"
1442   "addc %2,%0"
1443   [(set_attr "type" "arith")])
1444
1445 (define_insn "addc1"
1446   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1447         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1448                           (match_operand:SI 2 "arith_reg_operand" "r"))
1449                  (reg:SI T_REG)))
1450    (clobber (reg:SI T_REG))]
1451   "TARGET_SH1"
1452   "addc %2,%0"
1453   [(set_attr "type" "arith")])
1454
1455 (define_expand "addsi3"
1456   [(set (match_operand:SI 0 "arith_reg_operand" "")
1457         (plus:SI (match_operand:SI 1 "arith_operand" "")
1458                  (match_operand:SI 2 "arith_operand" "")))]
1459   ""
1460   "
1461 {
1462   if (TARGET_SHMEDIA)
1463     operands[1] = force_reg (SImode, operands[1]);
1464 }")
1465
1466 (define_insn "addsi3_media"
1467   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1468         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1469                  (match_operand:SI 2 "arith_operand" "r,I10")))]
1470   "TARGET_SHMEDIA"
1471   "@
1472         add.l   %1, %2, %0
1473         addi.l  %1, %2, %0"
1474   [(set_attr "type" "arith_media")
1475    (set_attr "highpart" "ignore")])
1476
1477 (define_insn "addsidi3_media"
1478   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1479         (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1480                                   "%r,r")
1481                                  (match_operand:SI 2 "arith_operand"
1482                                   "r,I10"))))]
1483   "TARGET_SHMEDIA"
1484   "@
1485         add.l   %1, %2, %0
1486         addi.l  %1, %2, %0"
1487   [(set_attr "type" "arith_media")
1488    (set_attr "highpart" "ignore")])
1489
1490 (define_insn "*addsi3_compact"
1491   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1492         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1493                  (match_operand:SI 2 "arith_operand" "rI08")))]
1494   "TARGET_SH1"
1495   "add  %2,%0"
1496   [(set_attr "type" "arith")])
1497
1498 ;; -------------------------------------------------------------------------
1499 ;; Subtraction instructions
1500 ;; -------------------------------------------------------------------------
1501
1502 (define_expand "subdi3"
1503   [(set (match_operand:DI 0 "arith_reg_operand" "")
1504         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1505                   (match_operand:DI 2 "arith_reg_operand" "")))]
1506   ""
1507   "
1508 {
1509   if (TARGET_SH1)
1510     {
1511       operands[1] = force_reg (DImode, operands[1]);
1512       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1513       DONE;
1514     }
1515 }")
1516
1517 (define_insn "*subdi3_media"
1518   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1519         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1520                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1521   "TARGET_SHMEDIA"
1522   "sub  %N1, %2, %0"
1523   [(set_attr "type" "arith_media")])
1524   
1525 (define_insn "subdisi3_media"
1526   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1527         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1528                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1529   "TARGET_SHMEDIA"
1530   "sub.l        %N1, %2, %0"
1531   [(set_attr "type" "arith_media")
1532    (set_attr "highpart" "ignore")])
1533
1534 (define_insn "subdi3_compact"
1535   [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1536         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1537                  (match_operand:DI 2 "arith_reg_operand" "r")))
1538    (clobber (reg:SI T_REG))]
1539   "TARGET_SH1"
1540   "#"
1541   [(set_attr "length" "6")])
1542
1543 (define_split
1544   [(set (match_operand:DI 0 "arith_reg_dest" "")
1545         (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1546                   (match_operand:DI 2 "arith_reg_operand" "")))
1547    (clobber (reg:SI T_REG))]
1548   "TARGET_SH1 && reload_completed"
1549   [(const_int 0)]
1550   "
1551 {
1552   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1553   high0 = gen_rtx_REG (SImode,
1554                        true_regnum (operands[0])
1555                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1556   high2 = gen_rtx_REG (SImode,
1557                        true_regnum (operands[2])
1558                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1559   emit_insn (gen_clrt ());
1560   emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1561   emit_insn (gen_subc1 (high0, high0, high2));
1562   DONE;
1563 }")
1564
1565 (define_insn "subc"
1566   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1567         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1568                             (match_operand:SI 2 "arith_reg_operand" "r"))
1569                   (reg:SI T_REG)))
1570    (set (reg:SI T_REG)
1571         (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1572                           (reg:SI T_REG))
1573                 (match_dup 1)))]
1574   "TARGET_SH1"
1575   "subc %2,%0"
1576   [(set_attr "type" "arith")])
1577
1578 (define_insn "subc1"
1579   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1580         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1581                             (match_operand:SI 2 "arith_reg_operand" "r"))
1582                   (reg:SI T_REG)))
1583    (clobber (reg:SI T_REG))]
1584   "TARGET_SH1"
1585   "subc %2,%0"
1586   [(set_attr "type" "arith")])
1587
1588 ;; life_analysis thinks rn is live before subc rn,rn, so make a special
1589 ;; pattern for this case.  This helps multimedia applications that compute
1590 ;; the sum of absolute differences.
1591 (define_insn "mov_neg_si_t"
1592   [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))]
1593   "TARGET_SH1"
1594   "subc %0,%0"
1595   [(set_attr "type" "arith")])
1596
1597 (define_insn "*subsi3_internal"
1598   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1599         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1600                   (match_operand:SI 2 "arith_reg_operand" "r")))]
1601   "TARGET_SH1"
1602   "sub  %2,%0"
1603   [(set_attr "type" "arith")])
1604
1605 (define_insn_and_split "*subsi3_media"
1606   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1607         (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
1608                   (match_operand:SI 2 "extend_reg_operand" "r")))]
1609   "TARGET_SHMEDIA
1610    && (operands[1] != constm1_rtx
1611        || (GET_CODE (operands[2]) != TRUNCATE
1612            && GET_CODE (operands[2]) != SUBREG))"
1613   "sub.l        %N1, %2, %0"
1614   "operands[1] == constm1_rtx"
1615   [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
1616   ""
1617   [(set_attr "type" "arith_media")
1618    (set_attr "highpart" "ignore")])
1619
1620 (define_split
1621   [(set (match_operand:SI 0 "arith_reg_dest" "")
1622         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1623                                                        "general_extend_operand"
1624                                                        "") 0)) 0)))]
1625   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
1626   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1627    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1628   "")
1629
1630 (define_split
1631   [(set (match_operand:SI 0 "arith_reg_dest" "")
1632         (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1633                                                        "general_extend_operand"
1634                                                        "") 0)) 3)))]
1635   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
1636   [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1637    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1638   "")
1639 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1640 ;; will sometimes save one instruction.  Otherwise we might get
1641 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1642 ;; are the same.
1643
1644 (define_expand "subsi3"
1645   [(set (match_operand:SI 0 "arith_reg_operand" "")
1646         (minus:SI (match_operand:SI 1 "arith_operand" "")
1647                   (match_operand:SI 2 "arith_reg_operand" "")))]
1648   ""
1649   "
1650 {
1651   if (TARGET_SH1 && GET_CODE (operands[1]) == CONST_INT)
1652     {
1653       emit_insn (gen_negsi2 (operands[0], operands[2]));
1654       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1655       DONE;
1656     }
1657   if (TARGET_SHMEDIA)
1658     {
1659       if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode))
1660         FAIL;
1661       if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
1662         operands[1] = force_reg (SImode, operands[1]);
1663     }
1664 }")
1665 \f
1666 ;; -------------------------------------------------------------------------
1667 ;; Division instructions
1668 ;; -------------------------------------------------------------------------
1669
1670 ;; We take advantage of the library routines which don't clobber as many
1671 ;; registers as a normal function call would.
1672
1673 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1674 ;; also has an effect on the register that holds the address of the sfunc.
1675 ;; To make this work, we have an extra dummy insn that shows the use
1676 ;; of this register for reorg.
1677
1678 (define_insn "use_sfunc_addr"
1679   [(set (reg:SI PR_REG)
1680         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1681   "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1682   ""
1683   [(set_attr "length" "0")])
1684
1685 (define_insn "udivsi3_sh2a"
1686   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1687         (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1688                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1689   "TARGET_SH2A"
1690   "divu %2,%1"
1691   [(set_attr "type" "arith")
1692    (set_attr "in_delay_slot" "no")])
1693
1694 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1695 ;; hard register 0.  If we used hard register 0, then the next instruction
1696 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1697 ;; gets allocated to a stack slot that needs its address reloaded, then
1698 ;; there is nothing to prevent reload from using r0 to reload the address.
1699 ;; This reload would clobber the value in r0 we are trying to store.
1700 ;; If we let reload allocate r0, then this problem can never happen.
1701
1702 (define_insn "udivsi3_i1"
1703   [(set (match_operand:SI 0 "register_operand" "=z")
1704         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1705    (clobber (reg:SI T_REG))
1706    (clobber (reg:SI PR_REG))
1707    (clobber (reg:SI R4_REG))
1708    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1709   "TARGET_SH1 && ! TARGET_SH4"
1710   "jsr  @%1%#"
1711   [(set_attr "type" "sfunc")
1712    (set_attr "needs_delay_slot" "yes")])
1713
1714 ; Since shmedia-nofpu code could be linked against shcompact code, and
1715 ; the udivsi3 libcall has the same name, we must consider all registers
1716 ; clobbered that are in the union of the registers clobbered by the
1717 ; shmedia and the shcompact implementation.  Note, if the shcompact
1718 ; implementation actually used shcompact code, we'd need to clobber
1719 ; also r23 and fr23.
1720 (define_insn "udivsi3_i1_media"
1721   [(set (match_operand:SI 0 "register_operand" "=z")
1722         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1723    (clobber (reg:SI T_MEDIA_REG))
1724    (clobber (reg:SI PR_MEDIA_REG))
1725    (clobber (reg:SI R20_REG))
1726    (clobber (reg:SI R21_REG))
1727    (clobber (reg:SI R22_REG))
1728    (clobber (reg:DI TR0_REG))
1729    (clobber (reg:DI TR1_REG))
1730    (clobber (reg:DI TR2_REG))
1731    (use (match_operand 1 "target_operand" "b"))]
1732   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1733   "blink        %1, r18"
1734   [(set_attr "type" "sfunc")
1735    (set_attr "needs_delay_slot" "yes")])
1736
1737 (define_expand "udivsi3_i4_media"
1738   [(set (match_dup 3)
1739         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1740    (set (match_dup 4)
1741         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1742    (set (match_dup 5) (float:DF (match_dup 3)))
1743    (set (match_dup 6) (float:DF (match_dup 4)))
1744    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1745    (set (match_dup 8) (fix:DI (match_dup 7)))
1746    (set (match_operand:SI 0 "register_operand" "")
1747         (truncate:SI (match_dup 8)))]
1748   "TARGET_SHMEDIA_FPU"
1749   "
1750 {
1751   operands[3] = gen_reg_rtx (DImode);
1752   operands[4] = gen_reg_rtx (DImode);
1753   operands[5] = gen_reg_rtx (DFmode);
1754   operands[6] = gen_reg_rtx (DFmode);
1755   operands[7] = gen_reg_rtx (DFmode);
1756   operands[8] = gen_reg_rtx (DImode);
1757 }")
1758
1759 (define_insn "udivsi3_i4"
1760   [(set (match_operand:SI 0 "register_operand" "=y")
1761         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1762    (clobber (reg:SI T_REG))
1763    (clobber (reg:SI PR_REG))
1764    (clobber (reg:DF DR0_REG))
1765    (clobber (reg:DF DR2_REG))
1766    (clobber (reg:DF DR4_REG))
1767    (clobber (reg:SI R0_REG))
1768    (clobber (reg:SI R1_REG))
1769    (clobber (reg:SI R4_REG))
1770    (clobber (reg:SI R5_REG))
1771    (use (reg:PSI FPSCR_REG))
1772    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1773   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1774   "jsr  @%1%#"
1775   [(set_attr "type" "sfunc")
1776    (set_attr "fp_mode" "double")
1777    (set_attr "needs_delay_slot" "yes")])
1778
1779 (define_insn "udivsi3_i4_single"
1780   [(set (match_operand:SI 0 "register_operand" "=y")
1781         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1782    (clobber (reg:SI T_REG))
1783    (clobber (reg:SI PR_REG))
1784    (clobber (reg:DF DR0_REG))
1785    (clobber (reg:DF DR2_REG))
1786    (clobber (reg:DF DR4_REG))
1787    (clobber (reg:SI R0_REG))
1788    (clobber (reg:SI R1_REG))
1789    (clobber (reg:SI R4_REG))
1790    (clobber (reg:SI R5_REG))
1791    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1792   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1793   "jsr  @%1%#"
1794   [(set_attr "type" "sfunc")
1795    (set_attr "needs_delay_slot" "yes")])
1796
1797 (define_insn "udivsi3_i4_int"
1798   [(set (match_operand:SI 0 "register_operand" "=z")
1799         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1800    (clobber (reg:SI T_REG))
1801    (clobber (reg:SI R1_REG))
1802    (clobber (reg:SI PR_REG))
1803    (clobber (reg:SI MACH_REG))
1804    (clobber (reg:SI MACL_REG))
1805    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1806   "TARGET_SH1"
1807   "jsr  @%1%#"
1808   [(set_attr "type" "sfunc")
1809    (set_attr "needs_delay_slot" "yes")])
1810
1811
1812 (define_expand "udivsi3"
1813   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1814    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1815    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1816    (parallel [(set (match_operand:SI 0 "register_operand" "")
1817                    (udiv:SI (reg:SI R4_REG)
1818                             (reg:SI R5_REG)))
1819               (clobber (reg:SI T_REG))
1820               (clobber (reg:SI PR_REG))
1821               (clobber (reg:SI R4_REG))
1822               (use (match_dup 3))])]
1823   ""
1824   "
1825 {
1826   rtx first, last;
1827
1828   operands[3] = gen_reg_rtx (Pmode);
1829   /* Emit the move of the address to a pseudo outside of the libcall.  */
1830   if (TARGET_DIVIDE_CALL_TABLE)
1831     {
1832       /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
1833          that causes problems when the divide code is supposed to come from a
1834          separate library.  Division by zero is undefined, so dividing 1 can be
1835          implemented by comparing with the divisor.  */
1836       if (operands[1] == const1_rtx && currently_expanding_to_rtl)
1837         {
1838           emit_insn (gen_cmpsi (operands[1], operands[2]));
1839           emit_insn (gen_sgeu (operands[0]));
1840           DONE;
1841         }
1842       else if (operands[2] == const0_rtx)
1843         {
1844           emit_move_insn (operands[0], operands[2]);
1845           DONE;
1846         }
1847       function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
1848       last = gen_udivsi3_i4_int (operands[0], operands[3]);
1849     }
1850   else if (TARGET_DIVIDE_CALL_FP)
1851     {
1852       function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC);
1853       if (TARGET_FPU_SINGLE)
1854         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1855       else
1856         last = gen_udivsi3_i4 (operands[0], operands[3]);
1857     }
1858   else if (TARGET_SHMEDIA_FPU)
1859     {
1860       operands[1] = force_reg (SImode, operands[1]);
1861       operands[2] = force_reg (SImode, operands[2]);
1862       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1863       DONE;
1864     }
1865   else if (TARGET_SH2A)
1866     {
1867       operands[1] = force_reg (SImode, operands[1]);
1868       operands[2] = force_reg (SImode, operands[2]);
1869       emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1870       DONE;
1871     }
1872   else if (TARGET_SH5)
1873     {
1874       function_symbol (operands[3],
1875                        TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\",
1876                        SFUNC_STATIC);
1877
1878       if (TARGET_SHMEDIA)
1879         last = gen_udivsi3_i1_media (operands[0], operands[3]);
1880       else if (TARGET_FPU_ANY)
1881         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1882       else
1883         last = gen_udivsi3_i1 (operands[0], operands[3]);
1884     }
1885   else
1886     {
1887       function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
1888       last = gen_udivsi3_i1 (operands[0], operands[3]);
1889     }
1890   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1891   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1892   last = emit_insn (last);
1893   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1894      invariant code motion can move it.  */
1895   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1896   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1897   DONE;
1898 }")
1899
1900 (define_insn "divsi3_sh2a"
1901   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1902         (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1903                 (match_operand:SI 2 "arith_reg_operand" "z")))]
1904   "TARGET_SH2A"
1905   "divs %2,%1"
1906   [(set_attr "type" "arith")
1907    (set_attr "in_delay_slot" "no")])
1908
1909 (define_insn "divsi3_i1"
1910   [(set (match_operand:SI 0 "register_operand" "=z")
1911         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1912    (clobber (reg:SI T_REG))
1913    (clobber (reg:SI PR_REG))
1914    (clobber (reg:SI R1_REG))
1915    (clobber (reg:SI R2_REG))
1916    (clobber (reg:SI R3_REG))
1917    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1918   "TARGET_SH1 && ! TARGET_SH4"
1919   "jsr  @%1%#"
1920   [(set_attr "type" "sfunc")
1921    (set_attr "needs_delay_slot" "yes")])
1922
1923 (define_insn "divsi3_i1_media"
1924   [(set (match_operand:SI 0 "register_operand" "=z")
1925         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1926    (clobber (reg:SI T_MEDIA_REG))
1927    (clobber (reg:SI PR_MEDIA_REG))
1928    (clobber (reg:SI R1_REG))
1929    (clobber (reg:SI R20_REG))
1930    (clobber (reg:SI R21_REG))
1931    (clobber (reg:SI TR0_REG))
1932    (use (match_operand 1 "target_operand" "b"))]
1933   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1934   "blink        %1, r18"
1935   [(set_attr "type" "sfunc")])
1936
1937 (define_insn "divsi3_media_2"
1938   [(set (match_operand:SI 0 "register_operand" "=z")
1939         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1940    (clobber (reg:SI T_MEDIA_REG))
1941    (clobber (reg:SI PR_MEDIA_REG))
1942    (clobber (reg:SI R1_REG))
1943    (clobber (reg:SI R21_REG))
1944    (clobber (reg:SI TR0_REG))
1945    (use (reg:SI R20_REG))
1946    (use (match_operand 1 "target_operand" "b"))]
1947   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1948   "blink        %1, r18"
1949   [(set_attr "type" "sfunc")])
1950
1951 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
1952 ;; hard reg clobbers and data dependencies that we need when we want
1953 ;; to rematerialize the division into a call.
1954 (define_insn_and_split "divsi_inv_call"
1955   [(set (match_operand:SI 0 "register_operand" "=r")
1956         (div:SI (match_operand:SI 1 "register_operand" "r")
1957                 (match_operand:SI 2 "register_operand" "r")))
1958    (clobber (reg:SI R4_REG))
1959    (clobber (reg:SI R5_REG))
1960    (clobber (reg:SI T_MEDIA_REG))
1961    (clobber (reg:SI PR_MEDIA_REG))
1962    (clobber (reg:SI R1_REG))
1963    (clobber (reg:SI R21_REG))
1964    (clobber (reg:SI TR0_REG))
1965    (clobber (reg:SI R20_REG))
1966    (use (match_operand:SI 3 "register_operand" "r"))]
1967   "TARGET_SHMEDIA"
1968   "#"
1969   "&& (high_life_started || reload_completed)"
1970   [(set (match_dup 0) (match_dup 3))]
1971   ""
1972   [(set_attr "highpart" "must_split")])
1973
1974 ;; This is the combiner pattern for -mdiv=inv:call .
1975 (define_insn_and_split "*divsi_inv_call_combine"
1976   [(set (match_operand:SI 0 "register_operand" "=z")
1977         (div:SI (match_operand:SI 1 "register_operand" "r")
1978                 (match_operand:SI 2 "register_operand" "r")))
1979    (clobber (reg:SI R4_REG))
1980    (clobber (reg:SI R5_REG))
1981    (clobber (reg:SI T_MEDIA_REG))
1982    (clobber (reg:SI PR_MEDIA_REG))
1983    (clobber (reg:SI R1_REG))
1984    (clobber (reg:SI R21_REG))
1985    (clobber (reg:SI TR0_REG))
1986    (clobber (reg:SI R20_REG))
1987    (use (unspec:SI [(match_dup 1)
1988                     (match_operand:SI 3 "" "")
1989                     (unspec:SI [(match_operand:SI 4 "" "")
1990                                 (match_dup 3)
1991                                 (match_operand:DI 5 "" "")]
1992                      UNSPEC_DIV_INV_M2)
1993                     (match_operand:DI 6 "" "")
1994                     (const_int 0)
1995                     (const_int 0)]
1996          UNSPEC_DIV_INV_M3))]
1997   "TARGET_SHMEDIA"
1998   "#"
1999   "&& (high_life_started || reload_completed)"
2000   [(pc)]
2001   "
2002 {
2003   const char *name = sh_divsi3_libfunc;
2004   enum sh_function_kind kind = SFUNC_GOT;
2005   rtx sym;
2006
2007   emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2008   emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2009   while (TARGET_DIVIDE_INV_CALL2)
2010     {
2011       rtx x = operands[3];
2012
2013       if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2014         break;
2015       x = XVECEXP (x, 0, 0);
2016       name = \"__sdivsi3_2\";
2017       kind = SFUNC_STATIC;
2018       emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2019       break;
2020     }
2021   sym = function_symbol (NULL, name, kind);
2022   emit_insn (gen_divsi3_media_2 (operands[0], sym));
2023   DONE;
2024 }"
2025   [(set_attr "highpart" "must_split")])
2026
2027 (define_expand "divsi3_i4_media"
2028   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2029    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2030    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2031    (set (match_operand:SI 0 "register_operand" "=r")
2032         (fix:SI (match_dup 5)))]
2033   "TARGET_SHMEDIA_FPU"
2034   "
2035 {
2036   operands[3] = gen_reg_rtx (DFmode);
2037   operands[4] = gen_reg_rtx (DFmode);
2038   operands[5] = gen_reg_rtx (DFmode);
2039 }")
2040
2041 (define_insn "divsi3_i4"
2042   [(set (match_operand:SI 0 "register_operand" "=y")
2043         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2044    (clobber (reg:SI PR_REG))
2045    (clobber (reg:DF DR0_REG))
2046    (clobber (reg:DF DR2_REG))
2047    (use (reg:PSI FPSCR_REG))
2048    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2049   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2050   "jsr  @%1%#"
2051   [(set_attr "type" "sfunc")
2052    (set_attr "fp_mode" "double")
2053    (set_attr "needs_delay_slot" "yes")])
2054
2055 (define_insn "divsi3_i4_single"
2056   [(set (match_operand:SI 0 "register_operand" "=y")
2057         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2058    (clobber (reg:SI PR_REG))
2059    (clobber (reg:DF DR0_REG))
2060    (clobber (reg:DF DR2_REG))
2061    (clobber (reg:SI R2_REG))
2062    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2063   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2064   "jsr  @%1%#"
2065   [(set_attr "type" "sfunc")
2066    (set_attr "needs_delay_slot" "yes")])
2067
2068 (define_insn "divsi3_i4_int"
2069   [(set (match_operand:SI 0 "register_operand" "=z")
2070         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2071    (clobber (reg:SI T_REG))
2072    (clobber (reg:SI PR_REG))
2073    (clobber (reg:SI R1_REG))
2074    (clobber (reg:SI MACH_REG))
2075    (clobber (reg:SI MACL_REG))
2076    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2077   "TARGET_SH1"
2078   "jsr  @%1%#"
2079   [(set_attr "type" "sfunc")
2080    (set_attr "needs_delay_slot" "yes")])
2081
2082 (define_expand "divsi3"
2083   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2084    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2085    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2086    (parallel [(set (match_operand:SI 0 "register_operand" "")
2087                    (div:SI (reg:SI R4_REG)
2088                            (reg:SI R5_REG)))
2089               (clobber (reg:SI T_REG))
2090               (clobber (reg:SI PR_REG))
2091               (clobber (reg:SI R1_REG))
2092               (clobber (reg:SI R2_REG))
2093               (clobber (reg:SI R3_REG))
2094               (use (match_dup 3))])]
2095   ""
2096   "
2097 {
2098   rtx first, last;
2099
2100   operands[3] = gen_reg_rtx (Pmode);
2101   /* Emit the move of the address to a pseudo outside of the libcall.  */
2102   if (TARGET_DIVIDE_CALL_TABLE)
2103     {
2104       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2105       last = gen_divsi3_i4_int (operands[0], operands[3]);
2106     }
2107   else if (TARGET_DIVIDE_CALL_FP)
2108     {
2109       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2110       if (TARGET_FPU_SINGLE)
2111         last = gen_divsi3_i4_single (operands[0], operands[3]);
2112       else
2113         last = gen_divsi3_i4 (operands[0], operands[3]);
2114     }
2115   else if (TARGET_SH2A)
2116     {
2117       operands[1] = force_reg (SImode, operands[1]);
2118       operands[2] = force_reg (SImode, operands[2]);
2119       emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2120       DONE;
2121     }
2122   else if (TARGET_DIVIDE_INV)
2123     {
2124       rtx dividend = operands[1];
2125       rtx divisor = operands[2];
2126       rtx tab_base;
2127       rtx nsb_res = gen_reg_rtx (DImode);
2128       rtx norm64 = gen_reg_rtx (DImode);
2129       rtx tab_ix = gen_reg_rtx (DImode);
2130       rtx norm32 = gen_reg_rtx (SImode);
2131       rtx i92 = force_reg (DImode, GEN_INT (92));
2132       rtx scratch0a = gen_reg_rtx (DImode);
2133       rtx scratch0b = gen_reg_rtx (DImode);
2134       rtx inv0 = gen_reg_rtx (SImode);
2135       rtx scratch1a = gen_reg_rtx (DImode);
2136       rtx scratch1b = gen_reg_rtx (DImode);
2137       rtx shift = gen_reg_rtx (DImode);
2138       rtx i2p27, i43;
2139       rtx inv1 = gen_reg_rtx (SImode);
2140       rtx scratch2a = gen_reg_rtx (DImode);
2141       rtx scratch2b = gen_reg_rtx (SImode);
2142       rtx inv2 = gen_reg_rtx (SImode);
2143       rtx scratch3a = gen_reg_rtx (DImode);
2144       rtx scratch3b = gen_reg_rtx (DImode);
2145       rtx scratch3c = gen_reg_rtx (DImode);
2146       rtx scratch3d = gen_reg_rtx (SImode);
2147       rtx scratch3e = gen_reg_rtx (DImode);
2148       rtx result = gen_reg_rtx (SImode);
2149
2150       if (! arith_reg_or_0_operand (dividend, SImode))
2151         dividend = force_reg (SImode, dividend);
2152       if (! arith_reg_operand (divisor, SImode))
2153         divisor = force_reg (SImode, divisor);
2154       if (flag_pic && Pmode != DImode)
2155         {
2156           tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2157           tab_base = gen_datalabel_ref (tab_base);
2158           tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2159         }
2160       else
2161         {
2162           tab_base = gen_rtx_SYMBOL_REF (DImode, \"__div_table\");
2163           tab_base = gen_datalabel_ref (tab_base);
2164           tab_base = force_reg (DImode, tab_base);
2165         }
2166       if (TARGET_DIVIDE_INV20U)
2167         i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2168       else
2169         i2p27 = GEN_INT (0);
2170       if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2171         i43 = force_reg (DImode, GEN_INT (43));
2172       else
2173         i43 = GEN_INT (0);
2174       emit_insn (gen_nsbdi (nsb_res,
2175                             simplify_gen_subreg (DImode, divisor, SImode, 0)));
2176       emit_insn (gen_ashldi3_media (norm64,
2177                                     gen_rtx_SUBREG (DImode, divisor, 0),
2178                                     nsb_res));
2179       emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2180       emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2181       emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2182                                    inv0, scratch0a, scratch0b,
2183                                    scratch1a, scratch1b));
2184       emit_insn (gen_subdi3 (shift, i92, nsb_res));
2185       emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2186                                    scratch2a));
2187       emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2188                                    i2p27, i43,
2189                                    scratch3a, scratch3b, scratch3c,
2190                                    scratch2a, scratch2b, scratch3d, scratch3e));
2191       if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2192         emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2193       else if (TARGET_DIVIDE_INV_FP)
2194         emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2195                                      gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2196                                      gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2197                                      gen_reg_rtx (DFmode)));
2198       else
2199         emit_move_insn (operands[0], result);
2200       DONE;
2201     }
2202   else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2203     {
2204       operands[1] = force_reg (SImode, operands[1]);
2205       operands[2] = force_reg (SImode, operands[2]);
2206       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2207       DONE;
2208     }
2209   else if (TARGET_SH5)
2210     {
2211       if (TARGET_DIVIDE_CALL2)
2212         {
2213           rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2214           tab_base = gen_datalabel_ref (tab_base);
2215           emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2216         }
2217       if (TARGET_FPU_ANY && TARGET_SH1)
2218         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2219       else if (TARGET_DIVIDE_CALL2)
2220         function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC);
2221       else
2222         function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2223
2224       if (TARGET_SHMEDIA)
2225         last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2226                 (operands[0], operands[3]));
2227       else if (TARGET_FPU_ANY)
2228         last = gen_divsi3_i4_single (operands[0], operands[3]);
2229       else
2230         last = gen_divsi3_i1 (operands[0], operands[3]);
2231     }
2232   else
2233     {
2234       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2235       last = gen_divsi3_i1 (operands[0], operands[3]);
2236     }
2237   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2238   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2239   last = emit_insn (last);
2240   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2241      invariant code motion can move it.  */
2242   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2243   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2244   DONE;
2245 }")
2246
2247 ;; operands: inv0, tab_base, tab_ix, norm32
2248 ;; scratch equiv in sdivsi3_2: r19, r21
2249 (define_expand "divsi_inv_m0"
2250   [(set (match_operand:SI 0 "register_operand" "=r")
2251         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2252                     (match_operand:DI 2 "register_operand" "r")
2253                     (match_operand:SI 3 "register_operand" "r")]
2254          UNSPEC_DIV_INV_M0))
2255    (clobber (match_operand:DI 4 "register_operand" "=r"))
2256    (clobber (match_operand:DI 5 "register_operand" "=r"))]
2257   "TARGET_SHMEDIA"
2258   "
2259 {
2260 /*
2261 tab_base: r20
2262 tab_ix: r21
2263 norm32: r25
2264  ldx.ub r20, r21, r19 // u0.8
2265  shlli r21, 1, r21
2266  muls.l r25, r19, r19 // s2.38
2267  ldx.w r20, r21, r21  // s2.14
2268  shari r19, 24, r19   // truncate to s2.14
2269  sub r21, r19, r19    // some 11 bit inverse in s1.14
2270 */
2271
2272   rtx inv0 = operands[0];
2273   rtx tab_base = operands[1];
2274   rtx tab_ix = operands[2];
2275   rtx norm32 = operands[3];
2276   rtx scratch0 = operands[4];
2277   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2278   rtx scratch1 = operands[5];
2279   rtx mem;
2280
2281   mem = gen_const_mem (QImode, gen_rtx_PLUS (DImode, tab_base, tab_ix));
2282   emit_insn (gen_zero_extendqidi2 (scratch0, mem));
2283   emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2284   emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2285   mem = gen_const_mem (HImode, gen_rtx_PLUS (DImode, tab_base, scratch1));
2286   emit_insn (gen_extendhidi2 (scratch1, mem));
2287   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2288   emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2289   DONE;
2290 }")
2291
2292 ;; operands: inv1, tab_base, tab_ix, norm32
2293 (define_insn_and_split "divsi_inv_m1"
2294   [(set (match_operand:SI 0 "register_operand" "=r")
2295         (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2296                     (match_operand:DI 2 "register_operand" "r")
2297                     (match_operand:SI 3 "register_operand" "r")]
2298          UNSPEC_DIV_INV_M1))
2299    (clobber (match_operand:SI 4 "register_operand" "=r"))
2300    (clobber (match_operand:DI 5 "register_operand" "=r"))
2301    (clobber (match_operand:DI 6 "register_operand" "=r"))
2302    (clobber (match_operand:DI 7 "register_operand" "=r"))
2303    (clobber (match_operand:DI 8 "register_operand" "=r"))]
2304   "TARGET_SHMEDIA"
2305   "#"
2306   "&& no_new_pseudos"
2307   [(pc)]
2308   "
2309 {
2310 /* inv0: r19
2311  muls.l r19, r19, r18 // u0.28
2312  muls.l r25, r18, r18 // s2.58
2313  shlli r19, 45, r0    // multiply by two and convert to s2.58
2314  sub r0, r18, r18
2315  shari r18, 28, r18   // some 18 bit inverse in s1.30
2316 */
2317
2318   rtx inv1 = operands[0];
2319   rtx tab_base = operands[1];
2320   rtx tab_ix = operands[2];
2321   rtx norm32 = operands[3];
2322   rtx inv0 = operands[4];
2323   rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2324   rtx scratch0a = operands[5];
2325   rtx scratch0b = operands[6];
2326   rtx scratch0 = operands[7];
2327   rtx scratch1 = operands[8];
2328   rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2329
2330   emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2331                                scratch0a, scratch0b));
2332   emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2333   emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2334   emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2335   emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2336   emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2337   DONE;
2338 }")
2339
2340 ;; operands: inv2, norm32, inv1, i92
2341 (define_insn_and_split "divsi_inv_m2"
2342   [(set (match_operand:SI 0 "register_operand" "=r")
2343         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2344                     (match_operand:SI 2 "register_operand" "r")
2345                     (match_operand:DI 3 "register_operand" "r")]
2346          UNSPEC_DIV_INV_M2))
2347    (clobber (match_operand:DI 4 "register_operand" "=r"))]
2348   "TARGET_SHMEDIA"
2349   "#"
2350   "&& no_new_pseudos"
2351   [(pc)]
2352   "
2353 {
2354 /*
2355  muls.l r18, r25, r0  // s2.60
2356  shari r0, 16, r0     // s-16.44
2357   sub
2358  muls.l r0, r18, r19  // s-16.74
2359  shari r19, 30, r19   // s-16.44
2360 */
2361   rtx inv2 = operands[0];
2362   rtx norm32 = operands[1];
2363   rtx inv1 = operands[2];
2364   rtx i92 = operands[3];
2365   rtx scratch0 = operands[4];
2366   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2367
2368   emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2369   emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2370   emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2371   emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2372   emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2373   DONE;
2374 }")
2375
2376 (define_insn_and_split "divsi_inv_m3"
2377   [(set (match_operand:SI 0 "register_operand" "=r")
2378         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2379                     (match_operand:SI 2 "register_operand" "r")
2380                     (match_operand:SI 3 "register_operand" "r")
2381                     (match_operand:DI 4 "register_operand" "r")
2382                     (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2383                     (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2384          UNSPEC_DIV_INV_M3))
2385    (clobber (match_operand:DI 7 "register_operand" "=r"))
2386    (clobber (match_operand:DI 8 "register_operand" "=r"))
2387    (clobber (match_operand:DI 9 "register_operand" "=r"))
2388    (clobber (match_operand:DI 10 "register_operand" "=r"))
2389    (clobber (match_operand:SI 11 "register_operand" "=r"))
2390    (clobber (match_operand:SI 12 "register_operand" "=r"))
2391    (clobber (match_operand:DI 13 "register_operand" "=r"))]
2392   "TARGET_SHMEDIA"
2393   "#"
2394   "&& no_new_pseudos"
2395   [(pc)]
2396   "
2397 {
2398 /*
2399   r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
2400   r0: scratch0  r19: scratch1 r21: scratch2
2401
2402   muls.l r18, r4, r25 // s32.30
2403  muls.l r19, r4, r19  // s15.30
2404  shari r25, 63, r21
2405   shari r19, 14, r19  // s18.-14
2406  sub r25, r19, r0
2407  shard r0, r1, r0
2408  sub r0, r21, r0
2409 */
2410
2411   rtx result = operands[0];
2412   rtx dividend = operands[1];
2413   rtx inv1 = operands[2];
2414   rtx inv2 = operands[3];
2415   rtx shift = operands[4];
2416   rtx scratch0 = operands[7];
2417   rtx scratch1 = operands[8];
2418   rtx scratch2 = operands[9];
2419
2420   emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2421   emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2422   emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2423   emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2424   emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2425   emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2426   emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2427   DONE;
2428 }")
2429
2430 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2431 ;; inv1: tab_base, tab_ix, norm32
2432 ;; inv2: norm32, inv1, i92
2433 (define_insn_and_split "divsi_inv_m1_3"
2434   [(set (match_operand:SI 0 "register_operand" "=r")
2435         (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2436                     (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2437                                 (match_operand:DI 3 "register_operand" "r")
2438                                 (match_operand:SI 4 "register_operand" "r")]
2439                      UNSPEC_DIV_INV_M1)
2440                     (unspec:SI [(match_dup 4)
2441                                 (unspec:SI [(match_dup 2)
2442                                             (match_dup 3)
2443                                             (match_dup 4)] UNSPEC_DIV_INV_M1)
2444                                 (match_operand:SI 5 "" "")]
2445                      UNSPEC_DIV_INV_M2)
2446                     (match_operand:DI 6 "register_operand" "r")
2447                     (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2448                     (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2449          UNSPEC_DIV_INV_M3))
2450    (clobber (match_operand:DI 9 "register_operand" "=r"))
2451    (clobber (match_operand:DI 10 "register_operand" "=r"))
2452    (clobber (match_operand:DI 11 "register_operand" "=r"))
2453    (clobber (match_operand:DI 12 "register_operand" "=r"))
2454    (clobber (match_operand:SI 13 "register_operand" "=r"))
2455    (clobber (match_operand:SI 14 "register_operand" "=r"))
2456    (clobber (match_operand:DI 15 "register_operand" "=r"))]
2457   "TARGET_SHMEDIA
2458    && (TARGET_DIVIDE_INV_MINLAT
2459        || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2460   "#"
2461   "&& no_new_pseudos"
2462   [(pc)]
2463   "
2464 {
2465   rtx result = operands[0];
2466   rtx dividend = operands[1];
2467   rtx tab_base = operands[2];
2468   rtx tab_ix = operands[3];
2469   rtx norm32 = operands[4];
2470   /* rtx i92 = operands[5]; */
2471   rtx shift = operands[6];
2472   rtx i2p27 = operands[7];
2473   rtx i43 = operands[8];
2474   rtx scratch0 = operands[9];
2475   rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2476   rtx scratch1 = operands[10];
2477   rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2478   rtx scratch2 = operands[11];
2479   rtx scratch3 = operands[12];
2480   rtx scratch4 = operands[13];
2481   rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2482   rtx scratch5 = operands[14];
2483   rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2484   rtx scratch6 = operands[15];
2485
2486   emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2487                                scratch0, scratch1));
2488   /* inv0 == scratch4 */
2489   if (! TARGET_DIVIDE_INV20U)
2490     {
2491       emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2492       i2p27 = scratch0;
2493       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2494     }
2495   else
2496     {
2497       emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2498       emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2499     }
2500   emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2501   emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2502   emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2503   /* inv1 == scratch4 */
2504
2505   if (TARGET_DIVIDE_INV_MINLAT)
2506     {
2507       emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2508       emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2509       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2510       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2511       emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2512       emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2513       emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2514       emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2515       emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2516       emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2517       emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2518     }
2519   else
2520     {
2521       rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2522       /* Use separate scratch regs for nsb and sign to allow scheduling.  */
2523       emit_insn (gen_nsbdi (scratch6,
2524                             simplify_gen_subreg (DImode, dividend, SImode, 0)));
2525       emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2526       emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2527       emit_insn (gen_divsi_inv20 (scratch2,
2528                                   norm32, scratch4, dividend,
2529                                   scratch6, scratch3, i43,
2530                                   /* scratch0 may be shared with i2p27.  */
2531                                   scratch0, scratch1, scratch5,
2532                                   label, label, i2p27));
2533     }
2534   emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2535   emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2536   DONE;
2537 }")
2538
2539 (define_insn "divsi_inv20"
2540   [(set (match_operand:DI 0 "register_operand" "=&r")
2541         (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2542                     (match_operand:SI 2 "register_operand" "r")
2543                     (match_operand:SI 3 "register_operand" "r")
2544                     (match_operand:DI 4 "register_operand" "r")
2545                     (match_operand:DI 5 "register_operand" "r")
2546                     (match_operand:DI 6 "register_operand" "r")
2547                     (match_operand:DI 12 "register_operand" "r")
2548                     (match_operand 10 "target_operand" "b")
2549                     (match_operand 11 "immediate_operand" "i")]
2550          UNSPEC_DIV_INV20))
2551    (clobber (match_operand:DI 7 "register_operand" "=&r"))
2552    (clobber (match_operand:DI 8 "register_operand" "=&r"))
2553    (clobber (match_operand:SI 9 "register_operand" "=r"))]
2554   "TARGET_SHMEDIA
2555    && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2556   "*
2557 {
2558 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2559              %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2560              %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2561              %10 label (tr), %11 label (imm)
2562
2563  muls.l inv1, norm32, scratch0  // s2.60
2564   muls.l inv1, dividend, result // s32.30
2565   xor i2p27, result_sign, round_scratch
2566  bge/u dividend_nsb, i43, tr.. (label)
2567  shari scratch0, 16, scratch0   // s-16.44
2568  muls.l sratch0_si, inv1, scratch0 // s-16.74
2569   sub result, round_scratch, result
2570   shari dividend, 14, scratch1   // s19.-14
2571  shari scratch0, 30, scratch0   // s-16.44
2572  muls.l scratch0, scratch1, round_scratch // s15.30
2573 label:
2574  sub result, round_scratch, result */
2575
2576   int likely = TARGET_DIVIDE_INV20L;
2577
2578   if (! likely) output_asm_insn (\"muls.l\t%2, %1 , %8\", operands);
2579   output_asm_insn (\"muls.l\t%2, %3, %0\;xor\t%12, %5, %7\", operands);
2580   output_asm_insn (likely
2581                    ? \"bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8\"
2582                    : \"bge/u\t%4, %6, %10\", operands);
2583   output_asm_insn (\"shari\t%8, 16, %8\;muls.l\t%8, %2, %8\", operands);
2584   if (! likely) output_asm_insn (\"sub\t%0, %7, %0\", operands);
2585   output_asm_insn (\"shari\t%3, 14, %9\;shari\t%8, 30, %8\", operands);
2586   return (likely
2587           ? \"muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0\"
2588           : \"muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0\");
2589 }")
2590
2591 (define_insn_and_split "divsi_inv_fp"
2592   [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
2593         (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
2594                 (match_operand:SI 2 "register_operand" "rf")))
2595    (use (match_operand:SI 3 "general_movsrc_operand" "r"))
2596    (clobber (match_operand:SI 4 "register_operand" "=r"))
2597    (clobber (match_operand:SI 5 "register_operand" "=r"))
2598    (clobber (match_operand:DF 6 "register_operand" "=r"))
2599    (clobber (match_operand:DF 7 "register_operand" "=r"))
2600    (clobber (match_operand:DF 8 "register_operand" "=r"))]
2601   "TARGET_SHMEDIA_FPU"
2602   "#"
2603   "&& (high_life_started || reload_completed)"
2604   [(set (match_dup 0) (match_dup 3))]
2605   ""
2606   [(set_attr "highpart" "must_split")])
2607
2608 ;; If a matching group of divide-by-inverse instructions is in the same
2609 ;; basic block after gcse & loop optimizations, we want to transform them
2610 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
2611 (define_insn_and_split "*divsi_inv_fp_combine"
2612   [(set (match_operand:SI 0 "register_operand" "=f")
2613         (div:SI (match_operand:SI 1 "register_operand" "f")
2614                 (match_operand:SI 2 "register_operand" "f")))
2615    (use (unspec:SI [(match_dup 1)
2616                     (match_operand:SI 3 "" "")
2617                     (unspec:SI [(match_operand:SI 4 "" "")
2618                                 (match_dup 3)
2619                                 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
2620                     (match_operand:DI 6 "" "")
2621                     (const_int 0)
2622                     (const_int 0)] UNSPEC_DIV_INV_M3))
2623    (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
2624    (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
2625    (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
2626    (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
2627    (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
2628   "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && no_new_pseudos"
2629   "#"
2630   "&& 1"
2631   [(set (match_dup 9) (float:DF (match_dup 1)))
2632    (set (match_dup 10) (float:DF (match_dup 2)))
2633    (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
2634    (set (match_dup 8)
2635         (fix:SI (match_dup 11)))
2636    (set (match_dup 0) (match_dup 8))]
2637   "
2638 {
2639   if (! fp_arith_reg_operand (operands[1], SImode))
2640     {
2641       emit_move_insn (operands[7], operands[1]);
2642       operands[1] = operands[7];
2643     }
2644   if (! fp_arith_reg_operand (operands[2], SImode))
2645     {
2646       emit_move_insn (operands[8], operands[2]);
2647       operands[2] = operands[8];
2648     }
2649 }"
2650   [(set_attr "highpart" "must_split")])
2651 \f
2652 ;; -------------------------------------------------------------------------
2653 ;; Multiplication instructions
2654 ;; -------------------------------------------------------------------------
2655
2656 (define_insn "umulhisi3_i"
2657   [(set (reg:SI MACL_REG)
2658         (mult:SI (zero_extend:SI
2659                   (match_operand:HI 0 "arith_reg_operand" "r"))
2660                  (zero_extend:SI
2661                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
2662   "TARGET_SH1"
2663   "mulu.w       %1,%0"
2664   [(set_attr "type" "smpy")])
2665
2666 (define_insn "mulhisi3_i"
2667   [(set (reg:SI MACL_REG)
2668         (mult:SI (sign_extend:SI
2669                   (match_operand:HI 0 "arith_reg_operand" "r"))
2670                  (sign_extend:SI
2671                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
2672   "TARGET_SH1"
2673   "muls.w       %1,%0"
2674   [(set_attr "type" "smpy")])
2675
2676 (define_expand "mulhisi3"
2677   [(set (reg:SI MACL_REG)
2678         (mult:SI (sign_extend:SI
2679                   (match_operand:HI 1 "arith_reg_operand" ""))
2680                  (sign_extend:SI
2681                   (match_operand:HI 2 "arith_reg_operand" ""))))
2682    (set (match_operand:SI 0 "arith_reg_operand" "")
2683         (reg:SI MACL_REG))]
2684   "TARGET_SH1"
2685   "
2686 {
2687   rtx first, last;
2688
2689   first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
2690   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
2691   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2692      invariant code motion can move it.  */
2693   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2694   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2695   /* expand_binop can't find a suitable code in umul_widen_optab to
2696      make a REG_EQUAL note from, so make one here.
2697      See also smulsi3_highpart.
2698      ??? Alternatively, we could put this at the calling site of expand_binop,
2699      i.e. expand_expr.  */
2700   REG_NOTES (last)
2701     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
2702                          REG_NOTES (last));
2703   DONE;
2704 }")
2705
2706 (define_expand "umulhisi3"
2707   [(set (reg:SI MACL_REG)
2708         (mult:SI (zero_extend:SI
2709                   (match_operand:HI 1 "arith_reg_operand" ""))
2710                  (zero_extend:SI
2711                   (match_operand:HI 2 "arith_reg_operand" ""))))
2712    (set (match_operand:SI 0 "arith_reg_operand" "")
2713         (reg:SI MACL_REG))]
2714   "TARGET_SH1"
2715   "
2716 {
2717   rtx first, last;
2718
2719   first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
2720   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
2721   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2722      invariant code motion can move it.  */
2723   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2724   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2725   /* expand_binop can't find a suitable code in umul_widen_optab to
2726      make a REG_EQUAL note from, so make one here.
2727      See also smulsi3_highpart.
2728      ??? Alternatively, we could put this at the calling site of expand_binop,
2729      i.e. expand_expr.  */
2730   REG_NOTES (last)
2731     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
2732                          REG_NOTES (last));
2733   DONE;
2734 }")
2735
2736 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
2737 ;; a call to a routine which clobbers known registers.
2738
2739 (define_insn ""
2740   [(set (match_operand:SI 1 "register_operand" "=z")
2741         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2742    (clobber (reg:SI MACL_REG))
2743    (clobber (reg:SI T_REG))
2744    (clobber (reg:SI PR_REG))
2745    (clobber (reg:SI R3_REG))
2746    (clobber (reg:SI R2_REG))
2747    (clobber (reg:SI R1_REG))
2748    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
2749   "TARGET_SH1"
2750   "jsr  @%0%#"
2751   [(set_attr "type" "sfunc")
2752    (set_attr "needs_delay_slot" "yes")])
2753
2754 (define_expand "mulsi3_call"
2755   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2756    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2757    (parallel[(set (match_operand:SI 0 "register_operand" "")
2758                   (mult:SI (reg:SI R4_REG)
2759                            (reg:SI R5_REG)))
2760              (clobber (reg:SI MACL_REG))
2761              (clobber (reg:SI T_REG))
2762              (clobber (reg:SI PR_REG))
2763              (clobber (reg:SI R3_REG))
2764              (clobber (reg:SI R2_REG))
2765              (clobber (reg:SI R1_REG))
2766              (use (match_operand:SI 3 "register_operand" ""))])]
2767   "TARGET_SH1"
2768   "")
2769
2770 (define_insn "mul_r"
2771   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2772         (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
2773                  (match_operand:SI 2 "arith_reg_operand" "z")))]
2774   "TARGET_SH2A"
2775   "mulr %2,%0"
2776   [(set_attr "type" "dmpy")])
2777
2778 (define_insn "mul_l"
2779   [(set (reg:SI MACL_REG)
2780         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
2781                  (match_operand:SI 1 "arith_reg_operand" "r")))]
2782   "TARGET_SH2"
2783   "mul.l        %1,%0"
2784   [(set_attr "type" "dmpy")])
2785
2786 (define_expand "mulsi3"
2787   [(set (reg:SI MACL_REG)
2788         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
2789                   (match_operand:SI 2 "arith_reg_operand" "")))
2790    (set (match_operand:SI 0 "arith_reg_operand" "")
2791         (reg:SI MACL_REG))]
2792   "TARGET_SH1"
2793   "
2794 {
2795   rtx first, last;
2796
2797   if (!TARGET_SH2)
2798     {
2799       /* The address must be set outside the libcall,
2800          since it goes into a pseudo.  */
2801       rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC);
2802       rtx addr = force_reg (SImode, sym);
2803       rtx insns = gen_mulsi3_call (operands[0], operands[1],
2804                                    operands[2], addr);
2805       first = insns;
2806       last = emit_insn (insns);
2807     }
2808   else
2809     {
2810       rtx macl = gen_rtx_REG (SImode, MACL_REG);
2811
2812       first = emit_insn (gen_mul_l (operands[1], operands[2]));
2813       /* consec_sets_giv can only recognize the first insn that sets a
2814          giv as the giv insn.  So we must tag this also with a REG_EQUAL
2815          note.  */
2816       last = emit_insn (gen_movsi_i ((operands[0]), macl));
2817     }
2818   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
2819      invariant code motion can move it.  */
2820   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
2821   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2822   DONE;
2823 }")
2824
2825 (define_insn "mulsidi3_i"
2826   [(set (reg:SI MACH_REG)
2827         (truncate:SI
2828          (lshiftrt:DI
2829           (mult:DI
2830            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2831            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2832           (const_int 32))))
2833    (set (reg:SI MACL_REG)
2834         (mult:SI (match_dup 0)
2835                  (match_dup 1)))]
2836   "TARGET_SH2"
2837   "dmuls.l      %1,%0"
2838   [(set_attr "type" "dmpy")])
2839
2840 (define_expand "mulsidi3"
2841   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2842         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2843                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2844   "TARGET_SH2 || TARGET_SHMEDIA"
2845   "
2846 {
2847   if (TARGET_SH2)
2848     {
2849        emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
2850                                         operands[2]));
2851        DONE;
2852     }
2853 }")
2854
2855 (define_insn "mulsidi3_media"
2856   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2857         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2858                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2859   "TARGET_SHMEDIA"
2860   "muls.l       %1, %2, %0"
2861   [(set_attr "type" "dmpy_media")
2862    (set_attr "highpart" "ignore")])
2863
2864 (define_insn "mulsidi3_compact"
2865   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2866         (mult:DI
2867          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2868          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2869    (clobber (reg:SI MACH_REG))
2870    (clobber (reg:SI MACL_REG))]
2871   "TARGET_SH2"
2872   "#")
2873
2874 (define_split
2875   [(set (match_operand:DI 0 "arith_reg_dest" "")
2876         (mult:DI
2877          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2878          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2879    (clobber (reg:SI MACH_REG))
2880    (clobber (reg:SI MACL_REG))]
2881   "TARGET_SH2"
2882   [(const_int 0)]
2883   "
2884 {
2885   rtx low_dst = gen_lowpart (SImode, operands[0]);
2886   rtx high_dst = gen_highpart (SImode, operands[0]);
2887
2888   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
2889
2890   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2891   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2892   /* We need something to tag the possible REG_EQUAL notes on to.  */
2893   emit_move_insn (operands[0], operands[0]);
2894   DONE;
2895 }")
2896
2897 (define_insn "umulsidi3_i"
2898   [(set (reg:SI MACH_REG)
2899         (truncate:SI
2900          (lshiftrt:DI
2901           (mult:DI
2902            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2903            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2904           (const_int 32))))
2905    (set (reg:SI MACL_REG)
2906         (mult:SI (match_dup 0)
2907                  (match_dup 1)))]
2908   "TARGET_SH2"
2909   "dmulu.l      %1,%0"
2910   [(set_attr "type" "dmpy")])
2911
2912 (define_expand "umulsidi3"
2913   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2914         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2915                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2916   "TARGET_SH2 || TARGET_SHMEDIA"
2917   "
2918 {
2919   if (TARGET_SH2)
2920     {
2921        emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
2922                                          operands[2]));
2923        DONE;
2924     }
2925 }")
2926
2927 (define_insn "umulsidi3_media"
2928   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2929         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2930                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2931   "TARGET_SHMEDIA"
2932   "mulu.l       %1, %2, %0"
2933   [(set_attr "type" "dmpy_media")
2934    (set_attr "highpart" "ignore")])
2935
2936 (define_insn "umulsidi3_compact"
2937   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2938         (mult:DI
2939          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2940          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2941    (clobber (reg:SI MACH_REG))
2942    (clobber (reg:SI MACL_REG))]
2943   "TARGET_SH2"
2944   "#")
2945
2946 (define_split
2947   [(set (match_operand:DI 0 "arith_reg_dest" "")
2948         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2949                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2950    (clobber (reg:SI MACH_REG))
2951    (clobber (reg:SI MACL_REG))]
2952   "TARGET_SH2"
2953   [(const_int 0)]
2954   "
2955 {
2956   rtx low_dst = gen_lowpart (SImode, operands[0]);
2957   rtx high_dst = gen_highpart (SImode, operands[0]);
2958
2959   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
2960
2961   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2962   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2963   /* We need something to tag the possible REG_EQUAL notes on to.  */
2964   emit_move_insn (operands[0], operands[0]);
2965   DONE;
2966 }")
2967
2968 (define_insn "smulsi3_highpart_i"
2969   [(set (reg:SI MACH_REG)
2970         (truncate:SI
2971          (lshiftrt:DI
2972           (mult:DI
2973            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2974            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2975           (const_int 32))))
2976    (clobber (reg:SI MACL_REG))]
2977   "TARGET_SH2"
2978   "dmuls.l      %1,%0"
2979   [(set_attr "type" "dmpy")])
2980
2981 (define_expand "smulsi3_highpart"
2982   [(parallel
2983     [(set (reg:SI MACH_REG)
2984           (truncate:SI
2985            (lshiftrt:DI
2986             (mult:DI
2987              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2988              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
2989             (const_int 32))))
2990     (clobber (reg:SI MACL_REG))])
2991    (set (match_operand:SI 0 "arith_reg_operand" "")
2992         (reg:SI MACH_REG))]
2993   "TARGET_SH2"
2994   "
2995 {
2996   rtx first, last;
2997
2998   first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
2999   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
3000   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
3001      invariant code motion can move it.  */
3002   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
3003   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
3004   /* expand_binop can't find a suitable code in mul_highpart_optab to
3005      make a REG_EQUAL note from, so make one here.
3006      See also {,u}mulhisi.
3007      ??? Alternatively, we could put this at the calling site of expand_binop,
3008      i.e. expand_mult_highpart.  */
3009   REG_NOTES (last)
3010     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
3011                          REG_NOTES (last));
3012   DONE;
3013 }")
3014
3015 (define_insn "umulsi3_highpart_i"
3016   [(set (reg:SI MACH_REG)
3017         (truncate:SI
3018          (lshiftrt:DI
3019           (mult:DI
3020            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3021            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3022           (const_int 32))))
3023    (clobber (reg:SI MACL_REG))]
3024   "TARGET_SH2"
3025   "dmulu.l      %1,%0"
3026   [(set_attr "type" "dmpy")])
3027
3028 (define_expand "umulsi3_highpart"
3029   [(parallel
3030     [(set (reg:SI MACH_REG)
3031           (truncate:SI
3032            (lshiftrt:DI
3033             (mult:DI
3034              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3035              (zero_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 first, last;
3044
3045   first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3046   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
3047   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
3048      invariant code motion can move it.  */
3049   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
3050   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
3051   DONE;
3052 }")
3053
3054 (define_insn_and_split "muldi3"
3055   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3056         (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3057                  (match_operand:DI 2 "arith_reg_operand" "r")))
3058    (clobber (match_scratch:DI 3 "=&r"))
3059    (clobber (match_scratch:DI 4 "=r"))]
3060   "TARGET_SHMEDIA"
3061   "#"
3062   "reload_completed"
3063   [(const_int 0)]
3064   "
3065 {
3066   rtx op3_v2si, op2_v2si;
3067
3068   op3_v2si = operands[3];
3069   if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3070     {
3071       op3_v2si = XEXP (op3_v2si, 0);
3072       op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3073     }
3074   op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3075   op2_v2si = operands[2];
3076   if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3077     {
3078       op2_v2si = XEXP (op2_v2si, 0);
3079       op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3080     }
3081   op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3082   emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3083   emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3084   emit_insn (gen_umulsidi3_media (operands[4],
3085                                  sh_gen_truncate (SImode, operands[1], 0),
3086                                  sh_gen_truncate (SImode, operands[2], 0)));
3087   emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3088   emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3089   emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3090   emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3091   DONE;
3092 }")
3093
3094 \f
3095 ;; -------------------------------------------------------------------------
3096 ;; Logical operations
3097 ;; -------------------------------------------------------------------------
3098
3099 (define_insn "*andsi3_compact"
3100   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3101         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3102                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3103   "TARGET_SH1"
3104   "and  %2,%0"
3105   [(set_attr "type" "arith")])
3106
3107 (define_insn "*andsi3_media"
3108   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3109         (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3110                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3111   "TARGET_SHMEDIA"
3112   "@
3113         and     %1, %2, %0
3114         andi    %1, %2, %0"
3115   [(set_attr "type" "arith_media")])
3116
3117 ;; If the constant is 255, then emit an extu.b instruction instead of an
3118 ;; and, since that will give better code.
3119
3120 (define_expand "andsi3"
3121   [(set (match_operand:SI 0 "arith_reg_operand" "")
3122         (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3123                 (match_operand:SI 2 "logical_operand" "")))]
3124   ""
3125   "
3126 {
3127   if (TARGET_SH1
3128       && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)
3129     {
3130       emit_insn (gen_zero_extendqisi2 (operands[0],
3131                                        gen_lowpart (QImode, operands[1])));
3132       DONE;
3133     }
3134 }")
3135
3136 (define_insn_and_split "anddi3"
3137   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3138         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3139                 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3140   "TARGET_SHMEDIA"
3141   "@
3142         and     %1, %2, %0
3143         andi    %1, %2, %0
3144         #"
3145   "reload_completed
3146    && ! logical_operand (operands[2], DImode)"
3147   [(const_int 0)]
3148   "
3149 {
3150   if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3151     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3152   else
3153     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3154   DONE;
3155 }"
3156   [(set_attr "type" "arith_media")])
3157
3158 (define_insn "andcsi3"
3159   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3160         (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3161                 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3162   "TARGET_SHMEDIA"
3163   "andc %1,%2,%0"
3164   [(set_attr "type" "arith_media")])
3165
3166 (define_insn "andcdi3"
3167   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3168         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3169                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3170   "TARGET_SHMEDIA"
3171   "andc %1,%2,%0"
3172   [(set_attr "type" "arith_media")])
3173
3174 (define_expand "iorsi3"
3175   [(set (match_operand:SI 0 "arith_reg_operand" "")
3176         (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3177                 (match_operand:SI 2 "logical_operand" "")))]
3178   ""
3179   "")
3180
3181 (define_insn "*iorsi3_compact"
3182   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3183         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3184                 (match_operand:SI 2 "logical_operand" "r,K08")))]
3185   "TARGET_SH1"
3186   "or   %2,%0"
3187   [(set_attr "type" "arith")])
3188
3189 (define_insn "*iorsi3_media"
3190   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3191         (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3192                 (match_operand:SI 2 "logical_operand" "r,I10")))]
3193   "TARGET_SHMEDIA"
3194   "@
3195         or      %1, %2, %0
3196         ori     %1, %2, %0"
3197   [(set_attr "type" "arith_media")])
3198
3199 (define_insn "iordi3"
3200   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3201         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3202                 (match_operand:DI 2 "logical_operand" "r,I10")))]
3203   "TARGET_SHMEDIA"
3204   "@
3205         or      %1, %2, %0
3206         ori     %1, %2, %0"
3207   [(set_attr "type" "arith_media")])
3208
3209 (define_insn_and_split "*logical_sidi3"
3210   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3211         (sign_extend:DI (match_operator:SI 3 "logical_operator"
3212                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3213                            (match_operand:SI 2 "logical_operand" "r,I10")])))]
3214   "TARGET_SHMEDIA"
3215   "#"
3216   "&& reload_completed"
3217   [(set (match_dup 0) (match_dup 3))]
3218   "
3219 {
3220   operands[3]
3221     = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3222                       simplify_gen_subreg (DImode, operands[1], SImode, 0),
3223                       simplify_gen_subreg (DImode, operands[2], SImode, 0));
3224 }")
3225
3226 (define_insn_and_split "*logical_sidisi3"
3227   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3228         (truncate:SI (sign_extend:DI
3229                         (match_operator:SI 3 "logical_operator"
3230                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3231                            (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3232   "TARGET_SHMEDIA"
3233   "#"
3234   "&& 1"
3235   [(set (match_dup 0) (match_dup 3))])
3236
3237 (define_insn_and_split "*logical_sidi3_2"
3238   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3239         (sign_extend:DI (truncate:SI (sign_extend:DI
3240                         (match_operator:SI 3 "logical_operator"
3241                           [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3242                            (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3243   "TARGET_SHMEDIA"
3244   "#"
3245   "&& 1"
3246   [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3247
3248 (define_expand "xorsi3"
3249   [(set (match_operand:SI 0 "arith_reg_operand" "")
3250         (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3251                 (match_operand:SI 2 "xor_operand" "")))]
3252   ""
3253   "")
3254
3255 (define_insn "*xorsi3_compact"
3256   [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3257         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3258                 (match_operand:SI 2 "logical_operand" "K08,r")))]
3259   "TARGET_SH1"
3260   "xor  %2,%0"
3261   [(set_attr "type" "arith")])
3262
3263 (define_insn "*xorsi3_media"
3264   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3265         (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3266                 (match_operand:SI 2 "xor_operand" "r,I06")))]
3267   "TARGET_SHMEDIA"
3268   "@
3269         xor     %1, %2, %0
3270         xori    %1, %2, %0"
3271   [(set_attr "type" "arith_media")])
3272
3273 (define_insn "xordi3"
3274   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3275         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3276                 (match_operand:DI 2 "xor_operand" "r,I06")))]
3277   "TARGET_SHMEDIA"
3278   "@
3279         xor     %1, %2, %0
3280         xori    %1, %2, %0"
3281   [(set_attr "type" "arith_media")])
3282
3283 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3284 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3285 (define_split
3286   [(set (match_operand:DI 0 "arith_reg_dest" "")
3287         (sign_extend:DI (match_operator 4 "binary_logical_operator"
3288                           [(match_operand 1 "any_register_operand" "")
3289                            (match_operand 2 "any_register_operand" "")])))]
3290   "TARGET_SHMEDIA"
3291   [(set (match_dup 5) (match_dup 4))
3292    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3293 "
3294 {
3295   enum machine_mode inmode = GET_MODE (operands[1]);
3296   int offset = 0;
3297
3298   if (GET_CODE (operands[0]) == SUBREG)
3299     {
3300       offset = SUBREG_BYTE (operands[0]);
3301       operands[0] = SUBREG_REG (operands[0]);
3302     }
3303   gcc_assert (GET_CODE (operands[0]) == REG);
3304   if (! TARGET_LITTLE_ENDIAN)
3305     offset += 8 - GET_MODE_SIZE (inmode);
3306   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3307 }")
3308 \f
3309 ;; -------------------------------------------------------------------------
3310 ;; Shifts and rotates
3311 ;; -------------------------------------------------------------------------
3312
3313 (define_expand "rotldi3"
3314   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3315         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3316                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3317   "TARGET_SHMEDIA"
3318   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3319
3320 (define_insn "rotldi3_mextr"
3321   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3322         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3323                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
3324   "TARGET_SHMEDIA"
3325   "*
3326 {
3327   static char templ[16];
3328
3329   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
3330            8 - (int) (INTVAL (operands[2]) >> 3));
3331   return templ;
3332 }"
3333   [(set_attr "type" "arith_media")])
3334
3335 (define_expand "rotrdi3"
3336   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3337         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3338                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3339   "TARGET_SHMEDIA"
3340   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3341
3342 (define_insn "rotrdi3_mextr"
3343   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3344         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3345                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
3346   "TARGET_SHMEDIA"
3347   "*
3348 {
3349   static char templ[16];
3350
3351   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
3352   return templ;
3353 }"
3354   [(set_attr "type" "arith_media")])
3355
3356 (define_split
3357   [(set (match_operand:DI 0 "arith_reg_dest" "")
3358         (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3359                                          "ua_address_operand" "")))
3360                 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3361                            (const_int 8))))
3362    (clobber (match_operand:DI 3 "register_operand" ""))]
3363   "TARGET_SHMEDIA"
3364   [(match_dup 4) (match_dup 5)]
3365   "
3366 {
3367   operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3368                  (operands[3], operands[1]));
3369   operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3370                               GEN_INT (56), GEN_INT (8));
3371 }")
3372
3373 (define_insn "rotlsi3_1"
3374   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3375         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3376                    (const_int 1)))
3377    (set (reg:SI T_REG)
3378         (lshiftrt:SI (match_dup 1) (const_int 31)))]
3379   "TARGET_SH1"
3380   "rotl %0"
3381   [(set_attr "type" "arith")])
3382
3383 (define_insn "rotlsi3_31"
3384   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3385         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3386                    (const_int 31)))
3387    (clobber (reg:SI T_REG))]
3388   "TARGET_SH1"
3389   "rotr %0"
3390   [(set_attr "type" "arith")])
3391
3392 (define_insn "rotlsi3_16"
3393   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3394         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3395                    (const_int 16)))]
3396   "TARGET_SH1"
3397   "swap.w       %1,%0"
3398   [(set_attr "type" "arith")])
3399
3400 (define_expand "rotlsi3"
3401   [(set (match_operand:SI 0 "arith_reg_dest" "")
3402         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
3403                    (match_operand:SI 2 "immediate_operand" "")))]
3404   "TARGET_SH1"
3405   "
3406 {
3407   static const char rot_tab[] = {
3408     000, 000, 000, 000, 000, 000, 010, 001,
3409     001, 001, 011, 013, 003, 003, 003, 003,
3410     003, 003, 003, 003, 003, 013, 012, 002,
3411     002, 002, 010, 000, 000, 000, 000, 000,
3412   };
3413
3414   int count, choice;
3415
3416   if (GET_CODE (operands[2]) != CONST_INT)
3417     FAIL;
3418   count = INTVAL (operands[2]);
3419   choice = rot_tab[count];
3420   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3421     FAIL;
3422   choice &= 7;
3423   switch (choice)
3424     {
3425     case 0:
3426       emit_move_insn (operands[0], operands[1]);
3427       count -= (count & 16) * 2;
3428       break;
3429     case 3:
3430      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3431      count -= 16;
3432      break;
3433     case 1:
3434     case 2:
3435       {
3436         rtx parts[2];
3437         parts[0] = gen_reg_rtx (SImode);
3438         parts[1] = gen_reg_rtx (SImode);
3439         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3440         emit_move_insn (parts[choice-1], operands[1]);
3441         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3442         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3443         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3444         count = (count & ~16) - 8;
3445       }
3446     }
3447
3448   for (; count > 0; count--)
3449     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3450   for (; count < 0; count++)
3451     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3452
3453   DONE;
3454 }")
3455
3456 (define_insn "*rotlhi3_8"
3457   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3458         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3459                    (const_int 8)))]
3460   "TARGET_SH1"
3461   "swap.b       %1,%0"
3462   [(set_attr "type" "arith")])
3463
3464 (define_expand "rotlhi3"
3465   [(set (match_operand:HI 0 "arith_reg_operand" "")
3466         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
3467                    (match_operand:HI 2 "immediate_operand" "")))]
3468   "TARGET_SH1"
3469   "
3470 {
3471   if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
3472     FAIL;
3473 }")
3474
3475 ;;
3476 ;; shift left
3477
3478 (define_insn "ashlsi3_sh2a"
3479   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3480         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3481                    (match_operand:SI 2 "arith_reg_operand" "r")))]
3482   "TARGET_SH2A"
3483   "shad %2,%0"
3484   [(set_attr "type" "arith")
3485    (set_attr "length" "4")])
3486
3487 ;; This pattern is used by init_expmed for computing the costs of shift
3488 ;; insns.
3489
3490 (define_insn_and_split "ashlsi3_std"
3491   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
3492         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
3493                    (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
3494    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
3495   "TARGET_SH3
3496    || (TARGET_SH1 && GET_CODE (operands[2]) == CONST_INT
3497        && CONST_OK_FOR_P27 (INTVAL (operands[2])))"
3498   "@
3499    shld %2,%0
3500    add  %0,%0
3501    shll%O2      %0
3502    #"
3503   "TARGET_SH3
3504    && reload_completed
3505    && GET_CODE (operands[2]) == CONST_INT
3506    && ! CONST_OK_FOR_P27 (INTVAL (operands[2]))"
3507   [(set (match_dup 3) (match_dup 2))
3508    (parallel
3509     [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
3510      (clobber (match_dup 4))])]
3511   "operands[4] = gen_rtx_SCRATCH (SImode);"
3512   [(set_attr "length" "*,*,*,4")
3513    (set_attr "type" "dyn_shift,arith,arith,arith")])
3514
3515 (define_insn "ashlhi3_k"
3516   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
3517         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
3518                    (match_operand:HI 2 "const_int_operand" "M,P27")))]
3519   "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))"
3520   "@
3521         add     %0,%0
3522         shll%O2 %0"
3523   [(set_attr "type" "arith")])
3524
3525 (define_insn "ashlsi3_n"
3526   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3527         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3528                    (match_operand:SI 2 "const_int_operand" "n")))
3529    (clobber (reg:SI T_REG))]
3530   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3531   "#"
3532   [(set (attr "length")
3533         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3534                (const_string "2")
3535                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3536                (const_string "4")
3537                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3538                (const_string "6")]
3539               (const_string "8")))
3540    (set_attr "type" "arith")])
3541
3542 (define_split
3543   [(set (match_operand:SI 0 "arith_reg_dest" "")
3544         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3545                    (match_operand:SI 2 "const_int_operand" "")))
3546    (clobber (reg:SI T_REG))]
3547   "TARGET_SH1 && reload_completed"
3548   [(use (reg:SI R0_REG))]
3549   "
3550 {
3551   gen_shifty_op (ASHIFT, operands);
3552   DONE;
3553 }")
3554
3555 (define_insn "ashlsi3_media"
3556   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3557         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3558                    (match_operand:SI 2 "shift_count_operand" "r,n")))]
3559   "TARGET_SHMEDIA"
3560   "@
3561         shlld.l %1, %2, %0
3562         shlli.l %1, %2, %0"
3563   [(set_attr "type" "arith_media")
3564    (set_attr "highpart" "ignore")])
3565
3566 (define_expand "ashlsi3"
3567   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3568                    (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3569                               (match_operand:SI 2 "nonmemory_operand" "")))
3570               (clobber (reg:SI T_REG))])]
3571   ""
3572   "
3573 {
3574   if (TARGET_SHMEDIA)
3575     {
3576       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
3577       DONE;
3578     }
3579   if (GET_CODE (operands[2]) == CONST_INT
3580       && sh_dynamicalize_shift_p (operands[2]))
3581     operands[2] = force_reg (SImode, operands[2]);
3582   if (TARGET_SH3)
3583     {
3584       emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
3585       DONE;
3586     }
3587   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3588     FAIL;
3589 }")
3590
3591 (define_insn "*ashlhi3_n"
3592   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3593         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
3594                    (match_operand:HI 2 "const_int_operand" "n")))
3595    (clobber (reg:SI T_REG))]
3596   "TARGET_SH1"
3597   "#"
3598   [(set (attr "length")
3599         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3600                (const_string "2")
3601                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3602                (const_string "4")]
3603               (const_string "6")))
3604    (set_attr "type" "arith")])
3605
3606 (define_expand "ashlhi3"
3607   [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
3608                    (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3609                               (match_operand:SI 2 "nonmemory_operand" "")))
3610               (clobber (reg:SI T_REG))])]
3611   "TARGET_SH1"
3612   "
3613 {
3614   if (GET_CODE (operands[2]) != CONST_INT)
3615     FAIL;
3616   /* It may be possible to call gen_ashlhi3 directly with more generic
3617      operands.  Make sure operands[1] is a HImode register here.  */
3618   if (!arith_reg_operand (operands[1], HImode))
3619     operands[1] = copy_to_mode_reg (HImode, operands[1]);
3620 }")
3621
3622 (define_split
3623   [(set (match_operand:HI 0 "arith_reg_dest" "")
3624         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3625                    (match_operand:HI 2 "const_int_operand" "")))
3626    (clobber (reg:SI T_REG))]
3627   "TARGET_SH1 && reload_completed"
3628   [(use (reg:SI R0_REG))]
3629   "
3630 {
3631   gen_shifty_hi_op (ASHIFT, operands);
3632   DONE;
3633 }")
3634
3635 ;
3636 ; arithmetic shift right
3637 ;
3638
3639 (define_insn "ashrsi3_sh2a"
3640   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3641         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3642                    (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3643   "TARGET_SH2A"
3644   "shad %2,%0"
3645   [(set_attr "type" "dyn_shift")
3646    (set_attr "length" "4")])
3647
3648 (define_insn "ashrsi3_k"
3649   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3650         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3651                      (match_operand:SI 2 "const_int_operand" "M")))
3652    (clobber (reg:SI T_REG))]
3653   "TARGET_SH1 && INTVAL (operands[2]) == 1"
3654   "shar %0"
3655   [(set_attr "type" "arith")])
3656
3657 ;; We can't do HImode right shifts correctly unless we start out with an
3658 ;; explicit zero / sign extension; doing that would result in worse overall
3659 ;; code, so just let the machine independent code widen the mode.
3660 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
3661
3662
3663 ;; ??? This should be a define expand.
3664
3665 (define_insn "ashrsi2_16"
3666   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3667         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3668                      (const_int 16)))]
3669   "TARGET_SH1"
3670   "#"
3671   [(set_attr "length" "4")])
3672
3673 (define_split
3674   [(set (match_operand:SI 0 "arith_reg_dest" "")
3675         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3676                      (const_int 16)))]
3677   "TARGET_SH1"
3678   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
3679    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3680   "operands[2] = gen_lowpart (HImode, operands[0]);")
3681
3682 ;; ??? This should be a define expand.
3683
3684 (define_insn "ashrsi2_31"
3685   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3686         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3687                      (const_int 31)))
3688    (clobber (reg:SI T_REG))]
3689   "TARGET_SH1"
3690   "#"
3691   [(set_attr "length" "4")])
3692
3693 (define_split
3694   [(set (match_operand:SI 0 "arith_reg_dest" "")
3695         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3696                      (const_int 31)))
3697    (clobber (reg:SI T_REG))]
3698   "TARGET_SH1"
3699   [(const_int 0)]
3700   "
3701 {
3702   emit_insn (gen_ashlsi_c (operands[0], operands[1]));
3703   emit_insn (gen_mov_neg_si_t (operands[0]));
3704   DONE;
3705 }")
3706
3707 (define_peephole2
3708   [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
3709    (set (reg:SI T_REG)
3710         (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
3711   "TARGET_SH1
3712    && peep2_reg_dead_p (2, operands[0])
3713    && peep2_reg_dead_p (2, operands[1])"
3714   [(const_int 0)]
3715   "
3716 {
3717   emit_insn (gen_ashlsi_c (operands[1], operands[1]));
3718   DONE;
3719 }")
3720
3721 (define_insn "ashlsi_c"
3722   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3723         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
3724    (set (reg:SI T_REG)
3725         (lt:SI (match_dup 1) (const_int 0)))]
3726   "TARGET_SH1"
3727   "shll %0"
3728   [(set_attr "type" "arith")])
3729
3730 (define_insn "*ashlsi_c_void"
3731   [(set (reg:SI T_REG)
3732         (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
3733    (clobber (match_scratch:SI 1 "=0"))]
3734   "TARGET_SH1 && cse_not_expected"
3735   "shll %0"
3736   [(set_attr "type" "arith")])
3737
3738 (define_insn "ashrsi3_d"
3739   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3740         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3741                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3742   "TARGET_SH3"
3743   "shad %2,%0"
3744   [(set_attr "type" "dyn_shift")])
3745
3746 (define_insn "ashrsi3_n"
3747   [(set (reg:SI R4_REG)
3748         (ashiftrt:SI (reg:SI R4_REG)
3749                      (match_operand:SI 0 "const_int_operand" "i")))
3750    (clobber (reg:SI T_REG))
3751    (clobber (reg:SI PR_REG))
3752    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3753   "TARGET_SH1"
3754   "jsr  @%1%#"
3755   [(set_attr "type" "sfunc")
3756    (set_attr "needs_delay_slot" "yes")])
3757
3758 (define_insn "ashrsi3_media"
3759   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3760         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3761                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
3762   "TARGET_SHMEDIA"
3763   "@
3764         shard.l %1, %2, %0
3765         shari.l %1, %2, %0"
3766   [(set_attr "type" "arith_media")
3767    (set_attr "highpart" "ignore")])
3768
3769 (define_expand "ashrsi3"
3770   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3771                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3772                                 (match_operand:SI 2 "nonmemory_operand" "")))
3773               (clobber (reg:SI T_REG))])]
3774   ""
3775   "
3776 {
3777   if (TARGET_SHMEDIA)
3778     {
3779       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
3780       DONE;
3781     }
3782   if (expand_ashiftrt (operands))
3783     DONE;
3784   else
3785     FAIL;
3786 }")
3787
3788 ;; logical shift right
3789
3790 (define_insn "lshrsi3_sh2a"
3791   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3792         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3793                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3794   "TARGET_SH2A"
3795   "shld %2,%0"
3796   [(set_attr "type" "dyn_shift")
3797    (set_attr "length" "4")])
3798
3799 (define_insn "lshrsi3_d"
3800   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3801         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3802                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3803   "TARGET_SH3"
3804   "shld %2,%0"
3805   [(set_attr "type" "dyn_shift")])
3806
3807 ;;  Only the single bit shift clobbers the T bit.
3808
3809 (define_insn "lshrsi3_m"
3810   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3811         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3812                      (match_operand:SI 2 "const_int_operand" "M")))
3813    (clobber (reg:SI T_REG))]
3814   "TARGET_SH1 && CONST_OK_FOR_M (INTVAL (operands[2]))"
3815   "shlr %0"
3816   [(set_attr "type" "arith")])
3817
3818 (define_insn "lshrsi3_k"
3819   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3820         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3821                      (match_operand:SI 2 "const_int_operand" "P27")))]
3822   "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))
3823    && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
3824   "shlr%O2      %0"
3825   [(set_attr "type" "arith")])
3826
3827 (define_insn "lshrsi3_n"
3828   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3829         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3830                      (match_operand:SI 2 "const_int_operand" "n")))
3831    (clobber (reg:SI T_REG))]
3832   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3833   "#"
3834   [(set (attr "length")
3835         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3836                (const_string "2")
3837                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3838                (const_string "4")
3839                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3840                (const_string "6")]
3841               (const_string "8")))
3842    (set_attr "type" "arith")])
3843
3844 (define_split
3845   [(set (match_operand:SI 0 "arith_reg_dest" "")
3846         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3847                      (match_operand:SI 2 "const_int_operand" "")))
3848    (clobber (reg:SI T_REG))]
3849   "TARGET_SH1 && reload_completed"
3850   [(use (reg:SI R0_REG))]
3851   "
3852 {
3853   gen_shifty_op (LSHIFTRT, operands);
3854   DONE;
3855 }")
3856
3857 (define_insn "lshrsi3_media"
3858   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3859         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3860                      (match_operand:SI 2 "shift_count_operand" "r,n")))]
3861   "TARGET_SHMEDIA"
3862   "@
3863         shlrd.l %1, %2, %0
3864         shlri.l %1, %2, %0"
3865   [(set_attr "type" "arith_media")
3866    (set_attr "highpart" "ignore")])
3867
3868 (define_expand "lshrsi3"
3869   [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
3870                    (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3871                                 (match_operand:SI 2 "nonmemory_operand" "")))
3872               (clobber (reg:SI T_REG))])]
3873   ""
3874   "
3875 {
3876   if (TARGET_SHMEDIA)
3877     {
3878       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
3879       DONE;
3880     }
3881   if (GET_CODE (operands[2]) == CONST_INT
3882       && sh_dynamicalize_shift_p (operands[2]))
3883     operands[2] = force_reg (SImode, operands[2]);
3884   if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
3885     {
3886       rtx count = copy_to_mode_reg (SImode, operands[2]);
3887       emit_insn (gen_negsi2 (count, count));
3888       emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
3889       DONE;
3890     }
3891   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3892     FAIL;
3893 }")
3894
3895 ;; ??? This should be a define expand.
3896
3897 (define_insn "ashldi3_k"
3898   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3899         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
3900                    (const_int 1)))
3901    (clobber (reg:SI T_REG))]
3902   "TARGET_SH1"
3903   "shll %R0\;rotcl      %S0"
3904   [(set_attr "length" "4")
3905    (set_attr "type" "arith")])
3906
3907 (define_insn "ashldi3_media"
3908   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3909         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3910                    (match_operand:DI 2 "shift_count_operand" "r,n")))]
3911   "TARGET_SHMEDIA"
3912   "@
3913         shlld   %1, %2, %0
3914         shlli   %1, %2, %0"
3915   [(set_attr "type" "arith_media")])
3916
3917 (define_insn "*ashldisi3_media"
3918   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3919         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3920                    (match_operand:DI 2 "const_int_operand" "n")))]
3921   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3922   "shlli.l      %1, %2, %0"
3923   [(set_attr "type" "arith_media")
3924    (set_attr "highpart" "ignore")])
3925
3926 (define_expand "ashldi3"
3927   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3928                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
3929                               (match_operand:DI 2 "immediate_operand" "")))
3930               (clobber (reg:SI T_REG))])]
3931   ""
3932   "
3933 {
3934   if (TARGET_SHMEDIA)
3935     {
3936       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
3937       DONE;
3938     }
3939   if (GET_CODE (operands[2]) != CONST_INT
3940       || INTVAL (operands[2]) != 1)
3941     FAIL;
3942 }")
3943
3944 ;; ??? This should be a define expand.
3945
3946 (define_insn "lshrdi3_k"
3947   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3948         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
3949                      (const_int 1)))
3950    (clobber (reg:SI T_REG))]
3951   "TARGET_SH1"
3952   "shlr %S0\;rotcr      %R0"
3953   [(set_attr "length" "4")
3954    (set_attr "type" "arith")])
3955
3956 (define_insn "lshrdi3_media"
3957   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
3958         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3959                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
3960   "TARGET_SHMEDIA
3961    && (arith_reg_dest (operands[0], DImode)
3962        || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 32))"
3963   "@
3964         shlrd   %1, %2, %0
3965         shlri   %1, %2, %0"
3966   [(set_attr "type" "arith_media")])
3967
3968 (define_insn "*lshrdisi3_media"
3969   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3970         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
3971                      (match_operand:DI 2 "const_int_operand" "n")))]
3972   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3973   "shlri.l      %1, %2, %0"
3974   [(set_attr "type" "arith_media")
3975    (set_attr "highpart" "ignore")])
3976
3977 (define_expand "lshrdi3"
3978   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3979                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
3980                                (match_operand:DI 2 "immediate_operand" "")))
3981              (clobber (reg:SI T_REG))])]
3982   ""
3983   "
3984 {
3985   if (TARGET_SHMEDIA)
3986     {
3987       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
3988       DONE;
3989     }
3990   if (GET_CODE (operands[2]) != CONST_INT
3991       || INTVAL (operands[2]) != 1)
3992     FAIL;
3993 }")
3994
3995 ;; ??? This should be a define expand.
3996
3997 (define_insn "ashrdi3_k"
3998   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3999         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4000                      (const_int 1)))
4001    (clobber (reg:SI T_REG))]
4002   "TARGET_SH1"
4003   "shar %S0\;rotcr      %R0"
4004   [(set_attr "length" "4")
4005    (set_attr "type" "arith")])
4006
4007 (define_insn "ashrdi3_media"
4008   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4009         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4010                      (match_operand:DI 2 "shift_count_operand" "r,n")))]
4011   "TARGET_SHMEDIA
4012    && (arith_reg_dest (operands[0], DImode)
4013        || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32))"
4014   "@
4015         shard   %1, %2, %0
4016         shari   %1, %2, %0"
4017   [(set_attr "type" "arith_media")])
4018
4019 (define_insn "*ashrdisi3_media"
4020   [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4021         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4022                      (match_operand:DI 2 "const_int_operand" "n")))]
4023   "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4024   "shari.l      %1, %2, %0"
4025   [(set_attr "type" "arith_media")
4026    (set_attr "highpart" "ignore")])
4027
4028 (define_insn "ashrdisi3_media_high"
4029   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4030         (truncate:SI
4031            (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4032                         (match_operand:DI 2 "const_int_operand" "n"))))]
4033   "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4034   "shari        %1, %2, %0"
4035   [(set_attr "type" "arith_media")])
4036
4037 (define_insn "ashrdisi3_media_opaque"
4038   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4039         (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4040                     (match_operand:DI 2 "const_int_operand" "n")]
4041          UNSPEC_ASHIFTRT))]
4042   "TARGET_SHMEDIA"
4043   "shari        %1, %2, %0"
4044   [(set_attr "type" "arith_media")])
4045
4046 (define_expand "ashrdi3"
4047   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4048                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4049                                 (match_operand:DI 2 "immediate_operand" "")))
4050               (clobber (reg:SI T_REG))])]
4051   ""
4052   "
4053 {
4054   if (TARGET_SHMEDIA)
4055     {
4056       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4057       DONE;
4058     }
4059   if (GET_CODE (operands[2]) != CONST_INT
4060       || INTVAL (operands[2]) != 1)
4061     FAIL;
4062 }")
4063
4064 ;; combined left/right shift
4065
4066 (define_split
4067   [(set (match_operand:SI 0 "register_operand" "")
4068         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4069                            (match_operand:SI 2 "const_int_operand" ""))
4070                 (match_operand:SI 3 "const_int_operand" "")))]
4071   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4072   [(use (reg:SI R0_REG))]
4073   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4074    DONE;")
4075
4076 (define_split
4077   [(set (match_operand:SI 0 "register_operand" "")
4078         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4079                            (match_operand:SI 2 "const_int_operand" ""))
4080                 (match_operand:SI 3 "const_int_operand" "")))
4081    (clobber (reg:SI T_REG))]
4082   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4083   [(use (reg:SI R0_REG))]
4084   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4085    DONE;")
4086
4087 (define_insn ""
4088   [(set (match_operand:SI 0 "register_operand" "=r")
4089         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4090                            (match_operand:SI 2 "const_int_operand" "n"))
4091                 (match_operand:SI 3 "const_int_operand" "n")))
4092    (clobber (reg:SI T_REG))]
4093   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4094  "#"
4095   [(set (attr "length")
4096         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4097                (const_string "4")
4098                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4099                (const_string "6")
4100                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4101                (const_string "8")
4102                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4103                (const_string "10")
4104                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4105                (const_string "12")
4106                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4107                (const_string "14")
4108                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4109                (const_string "16")]
4110               (const_string "18")))
4111    (set_attr "type" "arith")])
4112
4113 (define_insn ""
4114   [(set (match_operand:SI 0 "register_operand" "=z")
4115         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4116                            (match_operand:SI 2 "const_int_operand" "n"))
4117                 (match_operand:SI 3 "const_int_operand" "n")))
4118    (clobber (reg:SI T_REG))]
4119   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4120  "#"
4121   [(set (attr "length")
4122         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4123                (const_string "4")
4124                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4125                (const_string "6")
4126                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4127                (const_string "8")]
4128               (const_string "10")))
4129    (set_attr "type" "arith")])
4130
4131 ;; shift left / and combination with a scratch register: The combine pass
4132 ;; does not accept the individual instructions, even though they are
4133 ;; cheap.  But it needs a precise description so that it is usable after
4134 ;; reload.
4135 (define_insn "and_shl_scratch"
4136   [(set (match_operand:SI 0 "register_operand" "=r,&r")
4137         (lshiftrt:SI
4138          (ashift:SI
4139           (and:SI
4140            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
4141                         (match_operand:SI 2 "const_int_operand" "N,n"))
4142            (match_operand:SI 3 "" "0,r"))
4143           (match_operand:SI 4 "const_int_operand" "n,n"))
4144          (match_operand:SI 5 "const_int_operand" "n,n")))
4145    (clobber (reg:SI T_REG))]
4146   "TARGET_SH1"
4147   "#"
4148   [(set (attr "length")
4149         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
4150                (const_string "4")
4151                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
4152                (const_string "6")
4153                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
4154                (const_string "8")
4155                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
4156                (const_string "10")]
4157               (const_string "12")))
4158    (set_attr "type" "arith")])
4159
4160 (define_split
4161   [(set (match_operand:SI 0 "register_operand" "")
4162         (lshiftrt:SI
4163          (ashift:SI
4164           (and:SI
4165            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4166                         (match_operand:SI 2 "const_int_operand" ""))
4167            (match_operand:SI 3 "register_operand" ""))
4168           (match_operand:SI 4 "const_int_operand" ""))
4169          (match_operand:SI 5 "const_int_operand" "")))
4170    (clobber (reg:SI T_REG))]
4171   "TARGET_SH1"
4172   [(use (reg:SI R0_REG))]
4173   "
4174 {
4175   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
4176
4177   if (INTVAL (operands[2]))
4178     {
4179       gen_shifty_op (LSHIFTRT, operands);
4180     }
4181   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
4182   operands[2] = operands[4];
4183   gen_shifty_op (ASHIFT, operands);
4184   if (INTVAL (operands[5]))
4185     {
4186       operands[2] = operands[5];
4187       gen_shifty_op (LSHIFTRT, operands);
4188     }
4189   DONE;
4190 }")
4191
4192 ;; signed left/right shift combination.
4193 (define_split
4194   [(set (match_operand:SI 0 "register_operand" "")
4195         (sign_extract:SI
4196          (ashift:SI (match_operand:SI 1 "register_operand" "")
4197                     (match_operand:SI 2 "const_int_operand" ""))
4198          (match_operand:SI 3 "const_int_operand" "")
4199          (const_int 0)))
4200    (clobber (reg:SI T_REG))]
4201   "TARGET_SH1"
4202   [(use (reg:SI R0_REG))]
4203   "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
4204    DONE;")
4205
4206 (define_insn "shl_sext_ext"
4207   [(set (match_operand:SI 0 "register_operand" "=r")
4208         (sign_extract:SI
4209          (ashift:SI (match_operand:SI 1 "register_operand" "0")
4210                     (match_operand:SI 2 "const_int_operand" "n"))
4211          (match_operand:SI 3 "const_int_operand" "n")
4212          (const_int 0)))
4213    (clobber (reg:SI T_REG))]
4214   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
4215   "#"
4216   [(set (attr "length")
4217         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
4218                (const_string "2")
4219                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
4220                (const_string "4")
4221                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4222                (const_string "6")
4223                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4224                (const_string "8")
4225                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4226                (const_string "10")
4227                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4228                (const_string "12")
4229                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
4230                (const_string "14")
4231                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
4232                (const_string "16")]
4233               (const_string "18")))
4234     (set_attr "type" "arith")])
4235
4236 (define_insn "shl_sext_sub"
4237   [(set (match_operand:SI 0 "register_operand" "=z")
4238         (sign_extract:SI
4239          (ashift:SI (match_operand:SI 1 "register_operand" "0")
4240                     (match_operand:SI 2 "const_int_operand" "n"))
4241          (match_operand:SI 3 "const_int_operand" "n")
4242          (const_int 0)))
4243    (clobber (reg:SI T_REG))]
4244   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
4245   "#"
4246   [(set (attr "length")
4247         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4248                (const_string "6")
4249                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4250                (const_string "8")
4251                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4252                (const_string "10")
4253                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4254                (const_string "12")]
4255               (const_string "14")))
4256     (set_attr "type" "arith")])
4257
4258 ;; These patterns are found in expansions of DImode shifts by 16, and
4259 ;; allow the xtrct instruction to be generated from C source.
4260
4261 (define_insn "xtrct_left"
4262   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4263         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4264                            (const_int 16))
4265                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
4266                              (const_int 16))))]
4267   "TARGET_SH1"
4268   "xtrct        %1,%0"
4269   [(set_attr "type" "arith")])
4270
4271 (define_insn "xtrct_right"
4272   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4273         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4274                              (const_int 16))
4275                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
4276                            (const_int 16))))]
4277   "TARGET_SH1"
4278   "xtrct        %2,%0"
4279   [(set_attr "type" "arith")])
4280
4281 ;; -------------------------------------------------------------------------
4282 ;; Unary arithmetic
4283 ;; -------------------------------------------------------------------------
4284
4285 (define_insn "negc"
4286   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4287         (neg:SI (plus:SI (reg:SI T_REG)
4288                          (match_operand:SI 1 "arith_reg_operand" "r"))))
4289    (set (reg:SI T_REG)
4290         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4291                (const_int 0)))]
4292   "TARGET_SH1"
4293   "negc %1,%0"
4294   [(set_attr "type" "arith")])
4295
4296 (define_insn "*negdi_media"
4297   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4298         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4299   "TARGET_SHMEDIA"
4300   "sub  r63, %1, %0"
4301   [(set_attr "type" "arith_media")])
4302
4303 (define_expand "negdi2"
4304   [(set (match_operand:DI 0 "arith_reg_operand" "")
4305         (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
4306   ""
4307   "
4308 {
4309   if (TARGET_SH1)
4310     {
4311       int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
4312       int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4313
4314       rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
4315       rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4316
4317       rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
4318       rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
4319
4320       emit_insn (gen_clrt ());
4321       emit_insn (gen_negc (low_dst, low_src));
4322       emit_insn (gen_negc (high_dst, high_src));
4323       DONE;
4324     }
4325 }")
4326
4327 (define_insn "negsi2"
4328   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4329         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4330   "TARGET_SH1"
4331   "neg  %1,%0"
4332   [(set_attr "type" "arith")])
4333
4334 (define_insn "one_cmplsi2"
4335   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4336         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4337   "TARGET_SH1"
4338   "not  %1,%0"
4339   [(set_attr "type" "arith")])
4340
4341 (define_expand "one_cmpldi2"
4342   [(set (match_operand:DI 0 "arith_reg_dest" "")
4343         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
4344                 (const_int -1)))]
4345   "TARGET_SHMEDIA" "")
4346
4347 /* The SH4 202 can do zero-offset branches without pipeline stalls.
4348    This can be used as some kind of conditional execution, which is useful
4349    for abs.  */
4350 (define_split
4351   [(set (match_operand:SI 0 "arith_reg_dest" "")
4352         (plus:SI (xor:SI (neg:SI (reg:SI T_REG))
4353                          (match_operand:SI 1 "arith_reg_operand" ""))
4354                  (reg:SI T_REG)))]
4355   "TARGET_HARD_SH4"
4356   [(const_int 0)]
4357   "emit_insn (gen_movsi_i (operands[0], operands[1]));
4358    emit_insn (gen_cneg (operands[0], operands[0], operands[0]));
4359    DONE;")
4360
4361 (define_insn "cneg"
4362   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4363         (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
4364                       (match_operand:SI 1 "arith_reg_operand" "0")
4365                       (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4366   "TARGET_HARD_SH4"
4367   "bf 0f\;neg %2,%0\\n0:"
4368   [(set_attr "type" "arith") ;; poor approximation
4369    (set_attr "length" "4")])
4370
4371 \f
4372 ;; -------------------------------------------------------------------------
4373 ;; Zero extension instructions
4374 ;; -------------------------------------------------------------------------
4375
4376 (define_insn "zero_extendsidi2"
4377   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4378         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
4379   "TARGET_SHMEDIA"
4380   "addz.l       %1, r63, %0"
4381   [(set_attr "type" "arith_media")
4382    (set_attr "highpart" "extend")])
4383
4384 (define_insn "zero_extendhidi2"
4385   [(set (match_operand:DI 0 "register_operand" "=r,r")
4386         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4387   "TARGET_SHMEDIA"
4388   "@
4389         #
4390         ld%M1.uw        %m1, %0"
4391   [(set_attr "type" "*,load_media")
4392    (set (attr "highpart")
4393         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4394                (const_string "user")]
4395               (const_string "ignore")))])
4396
4397 (define_split
4398   [(set (match_operand:DI 0 "register_operand" "")
4399         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4400   "TARGET_SHMEDIA && reload_completed"
4401   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4402    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
4403   "
4404 {
4405   if (GET_CODE (operands[1]) == TRUNCATE)
4406     operands[1] = XEXP (operands[1], 0);
4407 }")
4408
4409 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
4410 ;; reload the entire truncate expression.
4411 (define_insn_and_split "*loaddi_trunc"
4412   [(set (match_operand 0 "any_register_operand" "=r")
4413         (truncate (match_operand:DI 1 "memory_operand" "m")))]
4414   "TARGET_SHMEDIA && reload_completed"
4415   "#"
4416   "TARGET_SHMEDIA && reload_completed"
4417   [(set (match_dup 0) (match_dup 1))]
4418   "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
4419
4420 (define_insn "zero_extendqidi2"
4421   [(set (match_operand:DI 0 "register_operand" "=r,r")
4422         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4423   "TARGET_SHMEDIA"
4424   "@
4425         andi    %1, 255, %0
4426         ld%M1.ub        %m1, %0"
4427   [(set_attr "type" "arith_media,load_media")
4428    (set (attr "highpart")
4429         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4430                (const_string "user")]
4431               (const_string "ignore")))])
4432
4433 (define_expand "zero_extendhisi2"
4434   [(set (match_operand:SI 0 "arith_reg_operand" "")
4435         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
4436   ""
4437   "
4438 {
4439   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
4440     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4441 }")
4442
4443 (define_insn "*zero_extendhisi2_compact"
4444   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4445         (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
4446   "TARGET_SH1"
4447   "extu.w       %1,%0"
4448   [(set_attr "type" "arith")])
4449
4450 (define_insn "*zero_extendhisi2_media"
4451   [(set (match_operand:SI 0 "register_operand" "=r,r")
4452         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4453   "TARGET_SHMEDIA"
4454   "@
4455         #
4456         ld%M1.uw        %m1, %0"
4457   [(set_attr "type" "arith_media,load_media")
4458    (set (attr "highpart")
4459         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4460                (const_string "user")]
4461               (const_string "ignore")))])
4462
4463 (define_split
4464   [(set (match_operand:SI 0 "register_operand" "")
4465         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4466   "TARGET_SHMEDIA && reload_completed"
4467   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4468    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4469   "
4470 {
4471   rtx op1 = operands[1];
4472
4473   if (GET_CODE (op1) == TRUNCATE)
4474     op1 = XEXP (op1, 0);
4475   operands[2]
4476     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4477                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4478 }")
4479
4480 (define_expand "zero_extendqisi2"
4481   [(set (match_operand:SI 0 "arith_reg_operand" "")
4482         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4483   ""
4484   "
4485 {
4486   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
4487     operands[1] = copy_to_mode_reg (QImode, operands[1]);
4488 }")
4489
4490 (define_insn "*zero_extendqisi2_compact"
4491   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4492         (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
4493   "TARGET_SH1"
4494   "extu.b       %1,%0"
4495   [(set_attr "type" "arith")])
4496
4497 (define_insn "*zero_extendqisi2_media"
4498   [(set (match_operand:SI 0 "register_operand" "=r,r")
4499         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4500   "TARGET_SHMEDIA"
4501   "@
4502         andi    %1, 255, %0
4503         ld%M1.ub        %m1, %0"
4504   [(set_attr "type" "arith_media,load_media")
4505    (set (attr "highpart")
4506         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4507                (const_string "user")]
4508               (const_string "ignore")))])
4509
4510 (define_insn "zero_extendqihi2"
4511   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4512         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4513   "TARGET_SH1"
4514   "extu.b       %1,%0"
4515   [(set_attr "type" "arith")])
4516
4517 ;; -------------------------------------------------------------------------
4518 ;; Sign extension instructions
4519 ;; -------------------------------------------------------------------------
4520
4521 ;; ??? This should be a define expand.
4522 ;; ??? Or perhaps it should be dropped?
4523
4524 ;; convert_move generates good code for SH[1-4].
4525 (define_insn "extendsidi2"
4526   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
4527         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
4528   "TARGET_SHMEDIA"
4529   "@
4530         add.l   %1, r63, %0
4531         ld%M1.l %m1, %0
4532         fmov.sl %1, %0"
4533   [(set_attr "type" "arith_media,load_media,fpconv_media")
4534    (set (attr "highpart")
4535         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4536                (const_string "user")]
4537               (const_string "extend")))])
4538
4539 (define_insn "extendhidi2"
4540   [(set (match_operand:DI 0 "register_operand" "=r,r")
4541         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4542   "TARGET_SHMEDIA"
4543   "@
4544         #
4545         ld%M1.w %m1, %0"
4546   [(set_attr "type" "*,load_media")
4547    (set (attr "highpart")
4548         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4549                (const_string "user")]
4550               (const_string "ignore")))])
4551
4552 (define_split
4553   [(set (match_operand:DI 0 "register_operand" "")
4554         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4555   "TARGET_SHMEDIA && reload_completed"
4556   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4557    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
4558   "
4559 {
4560   if (GET_CODE (operands[1]) == TRUNCATE)
4561     operands[1] = XEXP (operands[1], 0);
4562 }")
4563
4564 (define_insn "extendqidi2"
4565   [(set (match_operand:DI 0 "register_operand" "=r,r")
4566         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4567   "TARGET_SHMEDIA"
4568   "@
4569         #
4570         ld%M1.b %m1, %0"
4571   [(set_attr "type" "*,load_media")
4572    (set (attr "highpart")
4573         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4574                (const_string "user")]
4575               (const_string "ignore")))])
4576
4577 (define_split
4578   [(set (match_operand:DI 0 "register_operand" "")
4579         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
4580   "TARGET_SHMEDIA && reload_completed"
4581   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
4582    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
4583   "
4584 {
4585   if (GET_CODE (operands[1]) == TRUNCATE)
4586     operands[1] = XEXP (operands[1], 0);
4587 }")
4588
4589 (define_expand "extendhisi2"
4590   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4591         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4592   ""
4593   "")
4594
4595 (define_insn "*extendhisi2_compact"
4596   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4597         (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
4598   "TARGET_SH1"
4599   "@
4600         exts.w  %1,%0
4601         mov.w   %1,%0"
4602   [(set_attr "type" "arith,load")])
4603
4604 (define_insn "*extendhisi2_media"
4605   [(set (match_operand:SI 0 "register_operand" "=r,r")
4606         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4607   "TARGET_SHMEDIA"
4608   "@
4609         #
4610         ld%M1.w %m1, %0"
4611   [(set_attr "type" "arith_media,load_media")
4612    (set (attr "highpart")
4613         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4614                (const_string "user")]
4615               (const_string "ignore")))])
4616
4617 (define_split
4618   [(set (match_operand:SI 0 "register_operand" "")
4619         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4620   "TARGET_SHMEDIA && reload_completed"
4621   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4622    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4623   "
4624 {
4625   rtx op1 = operands[1];
4626   if (GET_CODE (op1) == TRUNCATE)
4627     op1 = XEXP (op1, 0);
4628   operands[2]
4629     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4630                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4631 }")
4632
4633 (define_expand "extendqisi2"
4634   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4635         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4636   ""
4637   "")
4638
4639 (define_insn "*extendqisi2_compact"
4640   [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4641         (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4642   "TARGET_SH1"
4643   "@
4644         exts.b  %1,%0
4645         mov.b   %1,%0"
4646   [(set_attr "type" "arith,load")])
4647
4648 (define_insn "*extendqisi2_media"
4649   [(set (match_operand:SI 0 "register_operand" "=r,r")
4650         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4651   "TARGET_SHMEDIA"
4652   "@
4653         #
4654         ld%M1.b %m1, %0"
4655   [(set_attr "type" "arith_media,load_media")
4656    (set (attr "highpart")
4657         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4658                (const_string "user")]
4659               (const_string "ignore")))])
4660
4661 (define_split
4662   [(set (match_operand:SI 0 "register_operand" "")
4663         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
4664   "TARGET_SHMEDIA && reload_completed"
4665   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4666    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4667    "
4668 {
4669   rtx op1 = operands[1];
4670   if (GET_CODE (op1) == TRUNCATE)
4671     op1 = XEXP (op1, 0);
4672   operands[2]
4673     = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4674                            subreg_lowpart_offset (SImode, GET_MODE (op1)));
4675 }")
4676
4677 (define_insn "extendqihi2"
4678   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4679         (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4680   "TARGET_SH1"
4681   "@
4682         exts.b  %1,%0
4683         mov.b   %1,%0"
4684   [(set_attr "type" "arith,load")])
4685
4686 /* It would seem useful to combine the truncXi patterns into the movXi
4687    patterns, but unary operators are ignored when matching constraints,
4688    so we need separate patterns.  */
4689 (define_insn "truncdisi2"
4690   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
4691         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
4692   "TARGET_SHMEDIA"
4693   "@
4694         add.l   %1, r63, %0
4695         st%M0.l %m0, %1
4696         fst%M0.s        %m0, %T1
4697         fmov.ls %1, %0
4698         fmov.sl %T1, %0
4699         fmov.s  %T1, %0"
4700   [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
4701    (set (attr "highpart")
4702         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4703                (const_string "user")]
4704               (const_string "extend")))])
4705
4706 (define_insn "truncdihi2"
4707   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
4708         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
4709   "TARGET_SHMEDIA"
4710   "@
4711         shlli\\t%1,48,%0\;shlri\\t%0,48,%0
4712         st%M0.w %m0, %1"
4713   [(set_attr "type"   "arith_media,store_media")
4714    (set_attr "length" "8,4")
4715    (set (attr "highpart")
4716         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4717                (const_string "user")]
4718               (const_string "extend")))])
4719
4720 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
4721 ; Because we use zero extension, we can't provide signed QImode compares
4722 ; using a simple compare or conditional banch insn.
4723 (define_insn "truncdiqi2"
4724   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
4725         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
4726   "TARGET_SHMEDIA"
4727   "@
4728         andi    %1, 255, %0
4729         st%M0.b %m0, %1"
4730   [(set_attr "type"   "arith_media,store")
4731    (set (attr "highpart")
4732         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4733                (const_string "user")]
4734               (const_string "extend")))])
4735 ;; -------------------------------------------------------------------------
4736 ;; Move instructions
4737 ;; -------------------------------------------------------------------------
4738
4739 ;; define push and pop so it is easy for sh.c
4740 ;; We can't use push and pop on SHcompact because the stack must always
4741 ;; be 8-byte aligned.
4742
4743 (define_expand "push"
4744   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
4745         (match_operand:SI 0 "register_operand" "r,l,x"))]
4746   "TARGET_SH1 && ! TARGET_SH5"
4747   "")
4748
4749 (define_expand "pop"
4750   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
4751         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
4752   "TARGET_SH1 && ! TARGET_SH5"
4753   "")
4754
4755 (define_expand "push_e"
4756   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
4757                    (match_operand:SF 0 "" ""))
4758               (use (reg:PSI FPSCR_REG))
4759               (clobber (scratch:SI))])]
4760   "TARGET_SH1 && ! TARGET_SH5"
4761   "")
4762
4763 (define_insn "push_fpul"
4764   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
4765   "TARGET_SH2E && ! TARGET_SH5"
4766   "sts.l        fpul,@-r15"
4767   [(set_attr "type" "store")
4768    (set_attr "late_fp_use" "yes")
4769    (set_attr "hit_stack" "yes")])
4770
4771 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
4772 ;; so use that.
4773 (define_expand "push_4"
4774   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
4775                    (match_operand:DF 0 "" ""))
4776               (use (reg:PSI FPSCR_REG))
4777               (clobber (scratch:SI))])]
4778   "TARGET_SH1 && ! TARGET_SH5"
4779   "")
4780
4781 (define_expand "pop_e"
4782   [(parallel [(set (match_operand:SF 0 "" "")
4783               (mem:SF (post_inc:SI (reg:SI SP_REG))))
4784               (use (reg:PSI FPSCR_REG))
4785               (clobber (scratch:SI))])]
4786   "TARGET_SH1 && ! TARGET_SH5"
4787   "")
4788
4789 (define_insn "pop_fpul"
4790   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
4791   "TARGET_SH2E && ! TARGET_SH5"
4792   "lds.l        @r15+,fpul"
4793   [(set_attr "type" "load")
4794    (set_attr "hit_stack" "yes")])
4795
4796 (define_expand "pop_4"
4797   [(parallel [(set (match_operand:DF 0 "" "")
4798                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
4799               (use (reg:PSI FPSCR_REG))
4800               (clobber (scratch:SI))])]
4801   "TARGET_SH1 && ! TARGET_SH5"
4802   "")
4803
4804 (define_expand "push_fpscr"
4805   [(const_int 0)]
4806   "TARGET_SH2E"
4807   "
4808 {
4809   rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
4810                                                  gen_rtx_PRE_DEC (Pmode,
4811                                                           stack_pointer_rtx)),
4812                                         get_fpscr_rtx ()));
4813   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4814   DONE;
4815 }")
4816
4817 (define_expand "pop_fpscr"
4818   [(const_int 0)]
4819   "TARGET_SH2E"
4820   "
4821 {
4822   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
4823                                         gen_frame_mem (PSImode,
4824                                                  gen_rtx_POST_INC (Pmode,
4825                                                           stack_pointer_rtx))));
4826   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
4827   DONE;
4828 }")
4829
4830 ;; These two patterns can happen as the result of optimization, when
4831 ;; comparisons get simplified to a move of zero or 1 into the T reg.
4832 ;; They don't disappear completely, because the T reg is a fixed hard reg.
4833
4834 (define_insn "clrt"
4835   [(set (reg:SI T_REG) (const_int 0))]
4836   "TARGET_SH1"
4837   "clrt")
4838
4839 (define_insn "sett"
4840   [(set (reg:SI T_REG) (const_int 1))]
4841   "TARGET_SH1"
4842   "sett")
4843
4844 ;; t/r must come after r/r, lest reload will try to reload stuff like
4845 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
4846 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
4847 (define_insn "movsi_i"
4848   [(set (match_operand:SI 0 "general_movdst_operand"
4849             "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
4850         (match_operand:SI 1 "general_movsrc_operand"
4851          "Q,rI08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
4852   "TARGET_SH1
4853    && ! TARGET_SH2E
4854    && ! TARGET_SH2A
4855    && (register_operand (operands[0], SImode)
4856        || register_operand (operands[1], SImode))"
4857   "@
4858         mov.l   %1,%0
4859         mov     %1,%0
4860         cmp/pl  %1
4861         mov.l   %1,%0
4862         sts     %1,%0
4863         sts     %1,%0
4864         movt    %0
4865         mov.l   %1,%0
4866         sts.l   %1,%0
4867         sts.l   %1,%0
4868         lds     %1,%0
4869         lds     %1,%0
4870         lds.l   %1,%0
4871         lds.l   %1,%0
4872         fake    %1,%0"
4873   [(set_attr "type" "pcload_si,move,mt_group,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,pcload_si")
4874    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
4875
4876 ;; t/r must come after r/r, lest reload will try to reload stuff like
4877 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
4878 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
4879 ;; will require a reload.
4880 ;; ??? We can't include f/f because we need the proper FPSCR setting when
4881 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
4882 (define_insn "movsi_ie"
4883   [(set (match_operand:SI 0 "general_movdst_operand"
4884             "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
4885         (match_operand:SI 1 "general_movsrc_operand"
4886          "Q,rI08,I20,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
4887   "(TARGET_SH2E || TARGET_SH2A)
4888    && (register_operand (operands[0], SImode)
4889        || register_operand (operands[1], SImode))"
4890   "@
4891         mov.l   %1,%0
4892         mov     %1,%0
4893         movi20  %1,%0
4894         cmp/pl  %1
4895         mov.l   %1,%0
4896         sts     %1,%0
4897         sts     %1,%0
4898         movt    %0
4899         mov.l   %1,%0
4900         sts.l   %1,%0
4901         sts.l   %1,%0
4902         lds     %1,%0
4903         lds     %1,%0
4904         lds.l   %1,%0
4905         lds.l   %1,%0
4906         lds.l   %1,%0
4907         sts.l   %1,%0
4908         fake    %1,%0
4909         lds     %1,%0
4910         sts     %1,%0
4911         fsts    fpul,%0
4912         flds    %1,fpul
4913         fmov    %1,%0
4914         ! move optimized away"
4915   [(set_attr "type" "pcload_si,move,move,*,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,load,store,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
4916    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
4917    (set_attr "length" "*,*,4,*,4,*,*,*,4,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
4918
4919 (define_insn "movsi_i_lowpart"
4920   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
4921         (match_operand:SI 1 "general_movsrc_operand" "Q,rI08,mr,x,l,t,r,i"))]
4922    "TARGET_SH1
4923     && (register_operand (operands[0], SImode)
4924         || register_operand (operands[1], SImode))"
4925   "@
4926         mov.l   %1,%0
4927         mov     %1,%0
4928         mov.l   %1,%0
4929         sts     %1,%0
4930         sts     %1,%0
4931         movt    %0
4932         mov.l   %1,%0
4933         fake    %1,%0"
4934   [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
4935
4936 (define_insn_and_split "load_ra"
4937   [(set (match_operand:SI 0 "general_movdst_operand" "")
4938         (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
4939   "TARGET_SH1"
4940   "#"
4941   "&& ! currently_expanding_to_rtl"
4942   [(set (match_dup 0) (match_dup 1))]
4943   "
4944 {
4945   if (TARGET_SHCOMPACT && current_function_has_nonlocal_label)
4946     operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
4947 }")
4948
4949 ;; The '?'s in the following constraints may not reflect the time taken
4950 ;; to perform the move. They are there to discourage the use of floating-
4951 ;; point registers for storing integer values.
4952 (define_insn "*movsi_media"
4953   [(set (match_operand:SI 0 "general_movdst_operand"
4954                 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
4955         (match_operand:SI 1 "general_movsrc_operand"
4956          "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
4957   "TARGET_SHMEDIA_FPU
4958    && (register_operand (operands[0], SImode)
4959        || sh_register_operand (operands[1], SImode)
4960        || GET_CODE (operands[1]) == TRUNCATE)"
4961   "@
4962         add.l   %1, r63, %0
4963         movi    %1, %0
4964         #
4965         ld%M1.l %m1, %0
4966         st%M0.l %m0, %N1
4967         fld%M1.s        %m1, %0
4968         fst%M0.s        %m0, %1
4969         fmov.ls %N1, %0
4970         fmov.sl %1, %0
4971         fmov.s  %1, %0
4972         ptabs   %1, %0
4973         gettr   %1, %0
4974         pt      %1, %0"
4975   [(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")
4976    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
4977    (set (attr "highpart")
4978         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4979                (const_string "user")]
4980               (const_string "ignore")))])
4981
4982 (define_insn "*movsi_media_nofpu"
4983   [(set (match_operand:SI 0 "general_movdst_operand"
4984                 "=r,r,r,r,m,*b,r,*b")
4985         (match_operand:SI 1 "general_movsrc_operand"
4986          "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
4987   "TARGET_SHMEDIA
4988    && (register_operand (operands[0], SImode)
4989        || sh_register_operand (operands[1], SImode)
4990        || GET_CODE (operands[1]) == TRUNCATE)"
4991   "@
4992         add.l   %1, r63, %0
4993         movi    %1, %0
4994         #
4995         ld%M1.l %m1, %0
4996         st%M0.l %m0, %N1
4997         ptabs   %1, %0
4998         gettr   %1, %0
4999         pt      %1, %0"
5000   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5001    (set_attr "length" "4,4,8,4,4,4,4,12")
5002    (set (attr "highpart")
5003         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5004                (const_string "user")]
5005               (const_string "ignore")))])
5006
5007 (define_expand "movsi_const"
5008   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5009         (const:SI (sign_extend:SI
5010                    (truncate:HI
5011                     (ashiftrt:SI
5012                      (match_operand:DI 1 "immediate_operand" "s")
5013                      (const_int 16))))))
5014    (set (match_dup 0)
5015         (ior:SI (ashift:SI (match_dup 0) (const_int 16))
5016                 (const:SI
5017                   (zero_extend:SI
5018                    (truncate:HI (match_dup 1))))))]
5019   "TARGET_SHMEDIA && reload_completed
5020    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5021   "
5022 {
5023   if (GET_CODE (operands[1]) == LABEL_REF
5024       && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
5025     LABEL_NUSES (XEXP (operands[1], 0)) += 2;
5026   else if (GOTOFF_P (operands[1]))
5027     {
5028       rtx unspec = XEXP (operands[1], 0);
5029
5030       if (! UNSPEC_GOTOFF_P (unspec))
5031         {
5032           unspec = XEXP (unspec, 0);
5033           if (! UNSPEC_GOTOFF_P (unspec))
5034             abort ();
5035         }
5036       if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
5037           && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
5038         LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
5039     }
5040 }")
5041
5042 (define_expand "movsi_const_16bit"
5043   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5044         (const:SI (sign_extend:SI
5045                    (truncate:HI
5046                     (match_operand:DI 1 "immediate_operand" "s")))))]
5047   "TARGET_SHMEDIA && flag_pic && reload_completed
5048    && GET_CODE (operands[1]) == SYMBOL_REF"
5049   "")
5050
5051 (define_split
5052   [(set (match_operand:SI 0 "arith_reg_dest" "")
5053         (match_operand:SI 1 "immediate_operand" ""))]
5054   "TARGET_SHMEDIA && reload_completed
5055    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5056   [(const_int 0)]
5057   "
5058 {
5059   rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
5060
5061   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
5062                                         REG_NOTES (insn));
5063
5064   DONE;
5065 }")
5066
5067 (define_split
5068   [(set (match_operand:SI 0 "register_operand" "")
5069         (match_operand:SI 1 "immediate_operand" ""))]
5070   "TARGET_SHMEDIA && reload_completed
5071    && ((GET_CODE (operands[1]) == CONST_INT
5072         && ! CONST_OK_FOR_I16 (INTVAL (operands[1])))
5073        || GET_CODE (operands[1]) == CONST_DOUBLE)"
5074   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5075
5076 (define_expand "movsi"
5077   [(set (match_operand:SI 0 "general_movdst_operand" "")
5078         (match_operand:SI 1 "general_movsrc_operand" ""))]
5079   ""
5080   "{ if (prepare_move_operands (operands, SImode)) DONE; }")
5081
5082 (define_expand "ic_invalidate_line"
5083   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
5084                                 (match_dup 1)] UNSPEC_ICACHE)
5085               (clobber (scratch:SI))])]
5086   "TARGET_HARD_SH4 || TARGET_SH5"
5087   "
5088 {
5089   if (TARGET_SHMEDIA)
5090     {
5091       emit_insn (gen_ic_invalidate_line_media (operands[0]));
5092       DONE;
5093     }
5094   else if (TARGET_SHCOMPACT)
5095     {
5096       operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC);
5097       operands[1] = force_reg (Pmode, operands[1]);
5098       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
5099       DONE;
5100     }
5101   else if (TARGET_SH4A_ARCH)
5102     {
5103       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
5104       DONE;
5105     }
5106   operands[0] = force_reg (Pmode, operands[0]);
5107   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
5108                                                                Pmode)));
5109 }")
5110
5111 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
5112 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
5113 ;; the requirement *1*00 for associative address writes.  The alignment of
5114 ;; %0 implies that its least significant bit is cleared,
5115 ;; thus we clear the V bit of a matching entry if there is one.
5116 (define_insn "ic_invalidate_line_i"
5117   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
5118                      (match_operand:SI 1 "register_operand" "r")]
5119                      UNSPEC_ICACHE)
5120    (clobber (match_scratch:SI 2 "=&r"))]
5121   "TARGET_HARD_SH4"
5122   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
5123   [(set_attr "length" "8")
5124    (set_attr "type" "cwb")])
5125
5126 (define_insn "ic_invalidate_line_sh4a"
5127   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
5128                     UNSPEC_ICACHE)]
5129   "TARGET_SH4A_ARCH"
5130   "ocbwb\\t@%0\;synco\;icbi\\t@%0"
5131   [(set_attr "length" "16")
5132    (set_attr "type" "cwb")])
5133
5134 ;; ??? could make arg 0 an offsettable memory operand to allow to save
5135 ;; an add in the code that calculates the address.
5136 (define_insn "ic_invalidate_line_media"
5137   [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
5138                     UNSPEC_ICACHE)]
5139   "TARGET_SHMEDIA"
5140   "ocbwb        %0,0\;synco\;icbi       %0, 0\;synci"
5141   [(set_attr "length" "16")
5142    (set_attr "type" "invalidate_line_media")])
5143
5144 (define_insn "ic_invalidate_line_compact"
5145   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5146                      (match_operand:SI 1 "register_operand" "r")]
5147                     UNSPEC_ICACHE)
5148    (clobber (reg:SI PR_REG))]
5149   "TARGET_SHCOMPACT"
5150   "jsr @%1%#"
5151   [(set_attr "type" "sfunc")
5152    (set_attr "needs_delay_slot" "yes")])
5153
5154 (define_expand "initialize_trampoline"
5155   [(match_operand:SI 0 "" "")
5156    (match_operand:SI 1 "" "")
5157    (match_operand:SI 2 "" "")]
5158   "TARGET_SHCOMPACT"
5159   "
5160 {
5161   rtx sfun, tramp;
5162
5163   tramp = force_reg (Pmode, operands[0]);
5164   sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\",
5165                                             SFUNC_STATIC));
5166   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
5167   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
5168
5169   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
5170   DONE;
5171 }")
5172
5173 (define_insn "initialize_trampoline_compact"
5174   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5175                      (match_operand:SI 1 "register_operand" "r")
5176                      (reg:SI R2_REG) (reg:SI R3_REG)]
5177                     UNSPEC_INIT_TRAMP)
5178
5179    (clobber (reg:SI PR_REG))]
5180   "TARGET_SHCOMPACT"
5181   "jsr @%1%#"
5182   [(set_attr "type" "sfunc")
5183    (set_attr "needs_delay_slot" "yes")])
5184
5185 (define_insn "movqi_i"
5186   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l")
5187         (match_operand:QI 1 "general_movsrc_operand"  "ri,m,r,t,l,r"))]
5188   "TARGET_SH1
5189    && (arith_reg_operand (operands[0], QImode)
5190        || arith_reg_operand (operands[1], QImode))"
5191   "@
5192         mov     %1,%0
5193         mov.b   %1,%0
5194         mov.b   %1,%0
5195         movt    %0
5196         sts     %1,%0
5197         lds     %1,%0"
5198  [(set_attr "type" "move,load,store,move,move,move")])
5199
5200 (define_insn "*movqi_media"
5201   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
5202         (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
5203   "TARGET_SHMEDIA
5204    && (arith_reg_operand (operands[0], QImode)
5205        || extend_reg_or_0_operand (operands[1], QImode))"
5206   "@
5207         add.l   %1, r63, %0
5208         movi    %1, %0
5209         ld%M1.ub        %m1, %0
5210         st%M0.b %m0, %N1"
5211   [(set_attr "type" "arith_media,arith_media,load_media,store_media")
5212    (set (attr "highpart")
5213         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5214                (const_string "user")]
5215               (const_string "ignore")))])
5216
5217 (define_expand "movqi"
5218   [(set (match_operand:QI 0 "general_operand" "")
5219         (match_operand:QI 1 "general_operand"  ""))]
5220   ""
5221   "{ if (prepare_move_operands (operands, QImode)) DONE; }")
5222
5223 (define_expand "reload_inqi"
5224   [(set (match_operand:SI 2 "" "=&r")
5225         (match_operand:QI 1 "inqhi_operand" ""))
5226    (set (match_operand:QI 0 "arith_reg_operand" "=r")
5227         (truncate:QI (match_dup 3)))]
5228   "TARGET_SHMEDIA"
5229   "
5230 {
5231   rtx inner = XEXP (operands[1], 0);
5232   int regno = REGNO (inner);
5233
5234   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5235   operands[1] = gen_rtx_REG (SImode, regno);
5236   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5237 }")
5238
5239 /* When storing r0, we have to avoid reg+reg addressing.  */
5240 (define_insn "movhi_i"
5241   [(set (match_operand:HI 0 "general_movdst_operand"   "=r,r,r,r,m,r,l,r")
5242         (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
5243   "TARGET_SH1
5244    && (arith_reg_operand (operands[0], HImode)
5245        || arith_reg_operand (operands[1], HImode))
5246    && (GET_CODE (operands[0]) != MEM
5247        || GET_CODE (XEXP (operands[0], 0)) != PLUS
5248        || GET_CODE (XEXP (XEXP (operands[0], 0), 1)) != REG
5249        || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
5250   "@
5251         mov.w   %1,%0
5252         mov     %1,%0
5253         mov.w   %1,%0
5254         movt    %0
5255         mov.w   %1,%0
5256         sts     %1,%0
5257         lds     %1,%0
5258         fake    %1,%0"
5259   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
5260
5261 (define_insn "*movhi_media"
5262   [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
5263         (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
5264   "TARGET_SHMEDIA
5265    && (arith_reg_operand (operands[0], HImode)
5266        || arith_reg_or_0_operand (operands[1], HImode))"
5267   "@
5268         add.l   %1, r63, %0
5269         movi    %1, %0
5270         #
5271         ld%M1.w %m1, %0
5272         st%M0.w %m0, %N1"
5273   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
5274    (set (attr "highpart")
5275         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5276                (const_string "user")]
5277               (const_string "ignore")))])
5278
5279 (define_split
5280   [(set (match_operand:HI 0 "register_operand" "")
5281         (match_operand:HI 1 "immediate_operand" ""))]
5282   "TARGET_SHMEDIA && reload_completed
5283    && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
5284   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5285
5286 (define_expand "movhi"
5287   [(set (match_operand:HI 0 "general_movdst_operand" "")
5288         (match_operand:HI 1 "general_movsrc_operand"  ""))]
5289   ""
5290   "{ if (prepare_move_operands (operands, HImode)) DONE; }")
5291
5292 (define_expand "reload_inhi"
5293   [(set (match_operand:SI 2 "" "=&r")
5294         (match_operand:HI 1 "inqhi_operand" ""))
5295    (set (match_operand:HI 0 "arith_reg_operand" "=r")
5296         (truncate:HI (match_dup 3)))]
5297   "TARGET_SHMEDIA"
5298   "
5299 {
5300   rtx inner = XEXP (operands[1], 0);
5301   int regno = REGNO (inner);
5302
5303   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5304   operands[1] = gen_rtx_REG (SImode, regno);
5305   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5306 }")
5307
5308 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
5309 ;; compiled with -m2 -ml -O3 -funroll-loops
5310 (define_insn "*movdi_i"
5311   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
5312         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
5313   "TARGET_SH1
5314    && (arith_reg_operand (operands[0], DImode)
5315        || arith_reg_operand (operands[1], DImode))"
5316   "* return output_movedouble (insn, operands, DImode);"
5317   [(set_attr "length" "4")
5318    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
5319
5320 ;; If the output is a register and the input is memory or a register, we have
5321 ;; to be careful and see which word needs to be loaded first.
5322
5323 (define_split
5324   [(set (match_operand:DI 0 "general_movdst_operand" "")
5325         (match_operand:DI 1 "general_movsrc_operand" ""))]
5326   "TARGET_SH1 && reload_completed"
5327   [(set (match_dup 2) (match_dup 3))
5328    (set (match_dup 4) (match_dup 5))]
5329   "
5330 {
5331   int regno;
5332
5333   if ((GET_CODE (operands[0]) == MEM
5334        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
5335       || (GET_CODE (operands[1]) == MEM
5336           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
5337     FAIL;
5338
5339   switch (GET_CODE (operands[0]))
5340     {
5341     case REG:
5342       regno = REGNO (operands[0]);
5343       break;
5344     case SUBREG:
5345       regno = subreg_regno (operands[0]);
5346       break;
5347     case MEM:
5348       regno = -1;
5349       break;
5350     default:
5351       gcc_unreachable ();
5352     }
5353
5354   if (regno == -1
5355       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
5356     {
5357       operands[2] = operand_subword (operands[0], 0, 0, DImode);
5358       operands[3] = operand_subword (operands[1], 0, 0, DImode);
5359       operands[4] = operand_subword (operands[0], 1, 0, DImode);
5360       operands[5] = operand_subword (operands[1], 1, 0, DImode);
5361     }
5362   else
5363     {
5364       operands[2] = operand_subword (operands[0], 1, 0, DImode);
5365       operands[3] = operand_subword (operands[1], 1, 0, DImode);
5366       operands[4] = operand_subword (operands[0], 0, 0, DImode);
5367       operands[5] = operand_subword (operands[1], 0, 0, DImode);
5368     }
5369
5370   if (operands[2] == 0 || operands[3] == 0
5371       || operands[4] == 0 || operands[5] == 0)
5372     FAIL;
5373 }")
5374
5375 ;; The '?'s in the following constraints may not reflect the time taken
5376 ;; to perform the move. They are there to discourage the use of floating-
5377 ;; point registers for storing integer values.
5378 (define_insn "*movdi_media"
5379   [(set (match_operand:DI 0 "general_movdst_operand"
5380                  "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
5381         (match_operand:DI 1 "general_movsrc_operand"
5382          "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5383   "TARGET_SHMEDIA_FPU
5384    && (register_operand (operands[0], DImode)
5385        || sh_register_operand (operands[1], DImode))"
5386   "@
5387         add     %1, r63, %0
5388         movi    %1, %0
5389         #
5390         ld%M1.q %m1, %0
5391         st%M0.q %m0, %N1
5392         fld%M1.d        %m1, %0
5393         fst%M0.d        %m0, %1
5394         fmov.qd %N1, %0
5395         fmov.dq %1, %0
5396         fmov.d  %1, %0
5397         ptabs   %1, %0
5398         gettr   %1, %0
5399         pt      %1, %0"
5400   [(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")
5401    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
5402
5403 (define_insn "*movdi_media_nofpu"
5404   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
5405         (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
5406   "TARGET_SHMEDIA
5407    && (register_operand (operands[0], DImode)
5408        || sh_register_operand (operands[1], DImode))"
5409   "@
5410         add     %1, r63, %0
5411         movi    %1, %0
5412         #
5413         ld%M1.q %m1, %0
5414         st%M0.q %m0, %N1
5415         ptabs   %1, %0
5416         gettr   %1, %0
5417         pt      %1, %0"
5418   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5419    (set_attr "length" "4,4,16,4,4,4,4,*")])
5420
5421 (define_insn "*movdi_media_I16"
5422   [(set (match_operand:DI 0 "ext_dest_operand" "=r")
5423         (match_operand:DI 1 "const_int_operand" "I16"))]
5424   "TARGET_SHMEDIA && reload_completed"
5425   "movi %1, %0"
5426   [(set_attr "type" "arith_media")
5427    (set_attr "length" "4")])
5428
5429 (define_split
5430   [(set (match_operand:DI 0 "arith_reg_dest" "")
5431         (match_operand:DI 1 "immediate_operand" ""))]
5432   "TARGET_SHMEDIA && reload_completed
5433    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5434   [(set (match_dup 0) (match_dup 1))]
5435   "
5436 {
5437   rtx insn;
5438
5439   if (TARGET_SHMEDIA64)
5440     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
5441   else
5442     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
5443
5444   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
5445                                         REG_NOTES (insn));
5446
5447   DONE;
5448 }")
5449
5450 (define_expand "movdi_const"
5451   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5452         (const:DI (sign_extend:DI
5453                    (truncate:HI
5454                     (ashiftrt:DI
5455                      (match_operand:DI 1 "immediate_operand" "s")
5456                      (const_int 48))))))
5457    (set (match_dup 0)
5458         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5459                 (const:DI
5460                  (zero_extend:DI
5461                   (truncate:HI
5462                    (ashiftrt:SI
5463                     (match_dup 1)
5464                     (const_int 32)))))))
5465    (set (match_dup 0)
5466         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5467                 (const:DI
5468                  (zero_extend:DI
5469                   (truncate:HI
5470                    (ashiftrt:SI
5471                     (match_dup 1)
5472                     (const_int 16)))))))
5473    (set (match_dup 0)
5474         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5475                 (const:DI
5476                  (zero_extend:DI
5477                   (truncate:HI
5478                    (match_dup 1))))))]
5479   "TARGET_SHMEDIA64 && reload_completed
5480    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5481   "
5482 {
5483   sh_mark_label (operands[1], 4);
5484 }")
5485
5486 (define_expand "movdi_const_32bit"
5487   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5488         (const:DI (sign_extend:DI
5489                    (truncate:HI
5490                     (ashiftrt:DI
5491                      (match_operand:DI 1 "immediate_operand" "s")
5492                      (const_int 16))))))
5493    (set (match_dup 0)
5494         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
5495                 (const:DI
5496                  (zero_extend:DI
5497                   (truncate:HI
5498                    (match_dup 1))))))]
5499   "TARGET_SHMEDIA32 && reload_completed
5500    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5501   "
5502 {
5503   sh_mark_label (operands[1], 2);
5504 }")
5505
5506 (define_expand "movdi_const_16bit"
5507   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5508         (const:DI (sign_extend:DI
5509                    (truncate:HI
5510                     (match_operand:DI 1 "immediate_operand" "s")))))]
5511   "TARGET_SHMEDIA && flag_pic && reload_completed
5512    && GET_CODE (operands[1]) == SYMBOL_REF"
5513   "")
5514
5515 (define_split
5516   [(set (match_operand:DI 0 "ext_dest_operand" "")
5517         (match_operand:DI 1 "immediate_operand" ""))]
5518   "TARGET_SHMEDIA && reload_completed
5519    && GET_CODE (operands[1]) == CONST_INT
5520    && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
5521   [(set (match_dup 0) (match_dup 2))
5522    (match_dup 1)]
5523   "
5524 {
5525   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5526   unsigned HOST_WIDE_INT low = val;
5527   unsigned HOST_WIDE_INT high = val;
5528   unsigned HOST_WIDE_INT sign;
5529   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
5530
5531   /* Zero-extend the 16 least-significant bits.  */
5532   low &= 0xffff;
5533
5534   /* Arithmetic shift right the word by 16 bits.  */
5535   high >>= 16;
5536   if (GET_CODE (operands[0]) == SUBREG
5537       && GET_MODE (SUBREG_REG (operands[0])) == SImode)
5538     {
5539       high &= 0xffff;
5540       high ^= 0x8000;
5541       high -= 0x8000;
5542     }
5543   else
5544     {
5545       sign = 1;
5546       sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5547       high ^= sign;
5548       high -= sign;
5549     }
5550   do
5551     {
5552       /* If we can't generate the constant with a two-insn movi / shori
5553          sequence, try some other strategies.  */
5554       if (! CONST_OK_FOR_I16 (high))
5555         {
5556           /* Try constant load / left shift.  We know VAL != 0.  */
5557           val2 = val ^ (val-1);
5558           if (val2 > 0x1ffff)
5559             {
5560               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
5561
5562               if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
5563                   || (! CONST_OK_FOR_I16 (high >> 16)
5564                       && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
5565                 {
5566                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
5567                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
5568                                                    GEN_INT (trailing_zeroes));
5569                   break;
5570                 }
5571             }
5572           /* Try constant load / right shift.  */
5573           val2 = (val >> 15) + 1;
5574           if (val2 == (val2 & -val2))
5575             {
5576               int shift = 49 - exact_log2 (val2);
5577
5578               val2 = trunc_int_for_mode (val << shift, DImode);
5579               if (CONST_OK_FOR_I16 (val2))
5580                 {
5581                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
5582                                                    GEN_INT (shift));
5583                   break;
5584                 }
5585             }
5586           /* Try mperm.w .  */
5587           val2 = val & 0xffff;
5588           if ((val >> 16 & 0xffff) == val2
5589               && (val >> 32 & 0xffff) == val2
5590               && (val >> 48 & 0xffff) == val2)
5591             {
5592               val2 = (HOST_WIDE_INT) val >> 48;
5593               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
5594               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
5595               break;
5596             }
5597           /* Try movi / mshflo.l  */
5598           val2 = (HOST_WIDE_INT) val >> 32;
5599           if (val2 == ((unsigned HOST_WIDE_INT)
5600                         trunc_int_for_mode (val, SImode)))
5601             {
5602               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5603                                              operands[0]);
5604               break;
5605             }
5606           /* Try movi / mshflo.l w/ r63.  */
5607           val2 = val + ((HOST_WIDE_INT) -1 << 32);
5608           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
5609             {
5610               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5611                                              const0_rtx);
5612               break;
5613             }
5614         }
5615       val2 = high;
5616       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
5617     }
5618   while (0);
5619   operands[2] = GEN_INT (val2);
5620 }")
5621
5622 (define_split
5623   [(set (match_operand:DI 0 "ext_dest_operand" "")
5624         (match_operand:DI 1 "immediate_operand" ""))]
5625   "TARGET_SHMEDIA && reload_completed
5626    && GET_CODE (operands[1]) == CONST_DOUBLE"
5627   [(set (match_dup 0) (match_dup 2))
5628   (set (match_dup 0)
5629        (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
5630   "
5631 {
5632   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
5633   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
5634   unsigned HOST_WIDE_INT val = low;
5635   unsigned HOST_WIDE_INT sign;
5636
5637   /* Zero-extend the 16 least-significant bits.  */
5638   val &= 0xffff;
5639   operands[1] = GEN_INT (val);
5640
5641   /* Arithmetic shift right the double-word by 16 bits.  */
5642   low >>= 16;
5643   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
5644   high >>= 16;
5645   sign = 1;
5646   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5647   high ^= sign;
5648   high -= sign;
5649
5650   /* This will only be true if high is a sign-extension of low, i.e.,
5651      it must be either 0 or (unsigned)-1, and be zero iff the
5652      most-significant bit of low is set.  */
5653   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
5654     operands[2] = GEN_INT (low);
5655   else
5656     operands[2] = immed_double_const (low, high, DImode);
5657 }")
5658
5659 (define_insn "shori_media"
5660   [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5661         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
5662                            (const_int 16))
5663                 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
5664   "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
5665   "@
5666         shori   %u2, %0
5667         #"
5668   [(set_attr "type" "arith_media,*")])
5669
5670 (define_insn "*shori_media_si"
5671   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5672         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5673                            (const_int 16))
5674                 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
5675   "TARGET_SHMEDIA"
5676   "shori        %u2, %0")
5677
5678 (define_expand "movdi"
5679   [(set (match_operand:DI 0 "general_movdst_operand" "")
5680         (match_operand:DI 1 "general_movsrc_operand" ""))]
5681   ""
5682   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
5683
5684 (define_insn "movdf_media"
5685   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
5686         (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
5687   "TARGET_SHMEDIA_FPU
5688    && (register_operand (operands[0], DFmode)
5689        || sh_register_operand (operands[1], DFmode))"
5690   "@
5691         fmov.d  %1, %0
5692         fmov.qd %N1, %0
5693         fmov.dq %1, %0
5694         add     %1, r63, %0
5695         #
5696         fld%M1.d        %m1, %0
5697         fst%M0.d        %m0, %1
5698         ld%M1.q %m1, %0
5699         st%M0.q %m0, %N1"
5700   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
5701
5702 (define_insn "movdf_media_nofpu"
5703   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5704         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
5705   "TARGET_SHMEDIA
5706    && (register_operand (operands[0], DFmode)
5707        || sh_register_operand (operands[1], DFmode))"
5708   "@
5709         add     %1, r63, %0
5710         #
5711         ld%M1.q %m1, %0
5712         st%M0.q %m0, %N1"
5713   [(set_attr "type" "arith_media,*,load_media,store_media")])
5714
5715 (define_split
5716   [(set (match_operand:DF 0 "arith_reg_dest" "")
5717         (match_operand:DF 1 "immediate_operand" ""))]
5718   "TARGET_SHMEDIA && reload_completed"
5719   [(set (match_dup 3) (match_dup 2))]
5720   "
5721 {
5722   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
5723   long values[2];
5724   REAL_VALUE_TYPE value;
5725
5726   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
5727   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
5728
5729   if (HOST_BITS_PER_WIDE_INT >= 64)
5730     operands[2] = immed_double_const ((unsigned long) values[endian]
5731                                       | ((HOST_WIDE_INT) values[1 - endian]
5732                                          << 32), 0, DImode);
5733   else
5734     {
5735       gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
5736       operands[2] = immed_double_const (values[endian], values[1 - endian],
5737                                         DImode);
5738     }
5739
5740   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5741 }")
5742
5743 ;; ??? This should be a define expand.
5744
5745 (define_insn "movdf_k"
5746   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5747         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
5748   "TARGET_SH1
5749    && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
5750        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
5751        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
5752        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
5753    && (arith_reg_operand (operands[0], DFmode)
5754        || arith_reg_operand (operands[1], DFmode))"
5755   "* return output_movedouble (insn, operands, DFmode);"
5756   [(set_attr "length" "4")
5757    (set_attr "type" "move,pcload,load,store")])
5758
5759 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
5760 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
5761 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
5762 ;; the d/m/c/X alternative, which is split later into single-precision
5763 ;; instructions.  And when not optimizing, no splits are done before fixing
5764 ;; up pcloads, so we need usable length information for that.
5765 (define_insn "movdf_i4"
5766   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
5767         (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
5768    (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
5769    (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
5770   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5771    && (arith_reg_operand (operands[0], DFmode)
5772        || arith_reg_operand (operands[1], DFmode))"
5773   "@
5774         fmov    %1,%0
5775         #
5776         #
5777         fmov.d  %1,%0
5778         fmov.d  %1,%0
5779         #
5780         #
5781         #
5782         #
5783         #"
5784   [(set_attr_alternative "length"
5785      [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
5786       (const_int 4)
5787       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5788       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5789       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5790       (const_int 4)
5791       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
5792       ;; We can't use 4-byte push/pop on SHcompact, so we have to
5793       ;; increment or decrement r15 explicitly.
5794       (if_then_else
5795        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5796        (const_int 10) (const_int 8))
5797       (if_then_else
5798        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5799        (const_int 10) (const_int 8))])
5800    (set_attr "type" "fmove,move,pcfload,fload,store,pcload,load,store,load,fload")
5801    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
5802    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
5803                                            (const_string "double")
5804                                            (const_string "none")))])
5805
5806 ;; Moving DFmode between fp/general registers through memory
5807 ;; (the top of the stack) is faster than moving through fpul even for
5808 ;; little endian.  Because the type of an instruction is important for its
5809 ;; scheduling,  it is beneficial to split these operations, rather than
5810 ;; emitting them in one single chunk, even if this will expose a stack
5811 ;; use that will prevent scheduling of other stack accesses beyond this
5812 ;; instruction.
5813 (define_split
5814   [(set (match_operand:DF 0 "register_operand" "")
5815         (match_operand:DF 1 "register_operand" ""))
5816    (use (match_operand:PSI 2 "fpscr_operand" ""))
5817    (clobber (match_scratch:SI 3 "=X"))]
5818   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
5819    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
5820   [(const_int 0)]
5821   "
5822 {
5823   rtx insn, tos;
5824
5825   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
5826     {
5827       emit_move_insn (stack_pointer_rtx,
5828                       plus_constant (stack_pointer_rtx, -8));
5829       tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5830     }
5831   else
5832     tos = gen_tmp_stack_mem (DFmode,
5833                              gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
5834   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
5835   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
5836     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
5837   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5838     tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5839   else
5840     tos = gen_tmp_stack_mem (DFmode,
5841                              gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
5842   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
5843   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5844     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
5845   else
5846     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
5847   DONE;
5848 }")
5849
5850 ;; local-alloc sometimes allocates scratch registers even when not required,
5851 ;; so we must be prepared to handle these.
5852
5853 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
5854 (define_split
5855   [(set (match_operand:DF 0 "general_movdst_operand" "")
5856         (match_operand:DF 1 "general_movsrc_operand"  ""))
5857    (use (match_operand:PSI 2 "fpscr_operand" ""))
5858    (clobber (match_scratch:SI 3 ""))]
5859   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5860    && reload_completed
5861    && true_regnum (operands[0]) < 16
5862    && true_regnum (operands[1]) < 16"
5863   [(set (match_dup 0) (match_dup 1))]
5864   "
5865 {
5866   /* If this was a reg <-> mem operation with base + index reg addressing,
5867      we have to handle this in a special way.  */
5868   rtx mem = operands[0];
5869   int store_p = 1;
5870   if (! memory_operand (mem, DFmode))
5871     {
5872       mem = operands[1];
5873       store_p = 0;
5874     }
5875   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
5876     mem = SUBREG_REG (mem);
5877   if (GET_CODE (mem) == MEM)
5878     {
5879       rtx addr = XEXP (mem, 0);
5880       if (GET_CODE (addr) == PLUS
5881           && GET_CODE (XEXP (addr, 0)) == REG
5882           && GET_CODE (XEXP (addr, 1)) == REG)
5883         {
5884           int offset;
5885           rtx reg0 = gen_rtx_REG (Pmode, 0);
5886           rtx regop = operands[store_p], word0 ,word1;
5887
5888           if (GET_CODE (regop) == SUBREG)
5889             alter_subreg (&regop);
5890           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
5891             offset = 2;
5892           else
5893             offset = 4;
5894           mem = copy_rtx (mem);
5895           PUT_MODE (mem, SImode);
5896           word0 = gen_rtx_SUBREG (SImode, regop, 0);
5897           alter_subreg (&word0);
5898           word1 = gen_rtx_SUBREG (SImode, regop, 4);
5899           alter_subreg (&word1);
5900           if (store_p || ! refers_to_regno_p (REGNO (word0),
5901                                               REGNO (word0) + 1, addr, 0))
5902             {
5903               emit_insn (store_p
5904                          ? gen_movsi_ie (mem, word0)
5905                          : gen_movsi_ie (word0, mem));
5906               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5907               mem = copy_rtx (mem);
5908               emit_insn (store_p
5909                          ? gen_movsi_ie (mem, word1)
5910                          : gen_movsi_ie (word1, mem));
5911               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5912             }
5913           else
5914             {
5915               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5916               emit_insn (gen_movsi_ie (word1, mem));
5917               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5918               mem = copy_rtx (mem);
5919               emit_insn (gen_movsi_ie (word0, mem));
5920             }
5921           DONE;
5922         }
5923     }
5924 }")
5925
5926 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
5927 (define_split
5928   [(set (match_operand:DF 0 "register_operand" "")
5929         (match_operand:DF 1 "memory_operand"  ""))
5930    (use (match_operand:PSI 2 "fpscr_operand" ""))
5931    (clobber (reg:SI R0_REG))]
5932   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
5933   [(parallel [(set (match_dup 0) (match_dup 1))
5934               (use (match_dup 2))
5935               (clobber (scratch:SI))])]
5936   "")
5937
5938 (define_expand "reload_indf__frn"
5939   [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
5940                    (match_operand:DF 1 "immediate_operand" "FQ"))
5941               (use (reg:PSI FPSCR_REG))
5942               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
5943   "TARGET_SH1"
5944   "")
5945
5946 (define_expand "reload_outdf__RnFRm"
5947   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
5948                    (match_operand:DF 1 "register_operand" "af,r"))
5949               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
5950   "TARGET_SH1"
5951   "")
5952
5953 ;; Simplify no-op moves.
5954 (define_split
5955   [(set (match_operand:SF 0 "register_operand" "")
5956         (match_operand:SF 1 "register_operand" ""))
5957    (use (match_operand:PSI 2 "fpscr_operand" ""))
5958    (clobber (match_scratch:SI 3 ""))]
5959   "TARGET_SH2E && reload_completed
5960    && true_regnum (operands[0]) == true_regnum (operands[1])"
5961   [(set (match_dup 0) (match_dup 0))]
5962   "")
5963
5964 ;; fmovd substitute post-reload splits
5965 (define_split
5966   [(set (match_operand:DF 0 "register_operand" "")
5967         (match_operand:DF 1 "register_operand" ""))
5968    (use (match_operand:PSI 2 "fpscr_operand" ""))
5969    (clobber (match_scratch:SI 3 ""))]
5970   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
5971    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
5972    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
5973   [(const_int 0)]
5974   "
5975 {
5976   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
5977   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
5978                            gen_rtx_REG (SFmode, src), operands[2]));
5979   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
5980                            gen_rtx_REG (SFmode, src + 1), operands[2]));
5981   DONE;
5982 }")
5983
5984 (define_split
5985   [(set (match_operand:DF 0 "register_operand" "")
5986         (mem:DF (match_operand:SI 1 "register_operand" "")))
5987    (use (match_operand:PSI 2 "fpscr_operand" ""))
5988    (clobber (match_scratch:SI 3 ""))]
5989   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
5990    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
5991    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
5992   [(const_int 0)]
5993   "
5994 {
5995   int regno = true_regnum (operands[0]);
5996   rtx insn;
5997   rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
5998   rtx mem2
5999     = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
6000   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6001                                            regno + !! TARGET_LITTLE_ENDIAN),
6002                                   mem2, operands[2]));
6003   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[1], NULL_RTX);
6004   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6005                                                regno + ! TARGET_LITTLE_ENDIAN),
6006                                   change_address (mem, SFmode, NULL_RTX),
6007                                   operands[2]));
6008   DONE;
6009 }")
6010
6011 (define_split
6012   [(set (match_operand:DF 0 "register_operand" "")
6013         (match_operand:DF 1 "memory_operand" ""))
6014    (use (match_operand:PSI 2 "fpscr_operand" ""))
6015    (clobber (match_scratch:SI 3 ""))]
6016   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6017    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
6018   [(const_int 0)]
6019   "
6020 {
6021   int regno = true_regnum (operands[0]);
6022   rtx addr, insn, adjust = NULL_RTX;
6023   rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
6024   rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
6025   rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
6026
6027   operands[1] = copy_rtx (mem2);
6028   addr = XEXP (mem2, 0);
6029   if (GET_CODE (addr) != POST_INC)
6030     {
6031       /* If we have to modify the stack pointer, the value that we have
6032          read with post-increment might be modified by an interrupt,
6033          so write it back.  */
6034       if (REGNO (addr) == STACK_POINTER_REGNUM)
6035         adjust = gen_push_e (reg0);
6036       else
6037         adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
6038       XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
6039     }
6040   addr = XEXP (addr, 0);
6041   insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
6042   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6043   insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6044   if (adjust)
6045     emit_insn (adjust);
6046   else
6047     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6048   DONE;
6049 }")
6050
6051 (define_split
6052   [(set (match_operand:DF 0 "memory_operand" "")
6053         (match_operand:DF 1 "register_operand" ""))
6054    (use (match_operand:PSI 2 "fpscr_operand" ""))
6055    (clobber (match_scratch:SI 3 ""))]
6056   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6057    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6058   [(const_int 0)]
6059   "
6060 {
6061   int regno = true_regnum (operands[1]);
6062   rtx insn, addr, adjust = NULL_RTX;
6063
6064   operands[0] = copy_rtx (operands[0]);
6065   PUT_MODE (operands[0], SFmode);
6066   insn = emit_insn (gen_movsf_ie (operands[0],
6067                                   gen_rtx_REG (SFmode,
6068                                            regno + ! TARGET_LITTLE_ENDIAN),
6069                                   operands[2]));
6070   operands[0] = copy_rtx (operands[0]);
6071   addr = XEXP (operands[0], 0);
6072   if (GET_CODE (addr) != PRE_DEC)
6073     {
6074       adjust = gen_addsi3 (addr, addr, GEN_INT (4));
6075       emit_insn_before (adjust, insn);
6076       XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
6077     }
6078   addr = XEXP (addr, 0);
6079   if (! adjust)
6080     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6081   insn = emit_insn (gen_movsf_ie (operands[0],
6082                                   gen_rtx_REG (SFmode,
6083                                            regno + !! TARGET_LITTLE_ENDIAN),
6084                                   operands[2]));
6085   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
6086   DONE;
6087 }")
6088
6089 ;; If the output is a register and the input is memory or a register, we have
6090 ;; to be careful and see which word needs to be loaded first.
6091
6092 (define_split
6093   [(set (match_operand:DF 0 "general_movdst_operand" "")
6094         (match_operand:DF 1 "general_movsrc_operand" ""))]
6095   "TARGET_SH1 && reload_completed"
6096   [(set (match_dup 2) (match_dup 3))
6097    (set (match_dup 4) (match_dup 5))]
6098   "
6099 {
6100   int regno;
6101
6102   if ((GET_CODE (operands[0]) == MEM
6103        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6104       || (GET_CODE (operands[1]) == MEM
6105           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6106     FAIL;
6107
6108   switch (GET_CODE (operands[0]))
6109     {
6110     case REG:
6111       regno = REGNO (operands[0]);
6112       break;
6113     case SUBREG:
6114       regno = subreg_regno (operands[0]);
6115       break;
6116     case MEM:
6117       regno = -1;
6118       break;
6119     default:
6120       gcc_unreachable ();
6121     }
6122
6123   if (regno == -1
6124       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6125     {
6126       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
6127       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
6128       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
6129       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
6130     }
6131   else
6132     {
6133       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
6134       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
6135       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
6136       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
6137     }
6138
6139   if (operands[2] == 0 || operands[3] == 0
6140       || operands[4] == 0 || operands[5] == 0)
6141     FAIL;
6142 }")
6143
6144 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
6145 ;; used only once, let combine add in the index again.
6146
6147 (define_split
6148   [(set (match_operand:SI 0 "register_operand" "")
6149         (match_operand:SI 1 "" ""))
6150    (clobber (match_operand 2 "register_operand" ""))]
6151   "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6152    && ALLOW_INDEXED_ADDRESS"
6153   [(use (reg:SI R0_REG))]
6154   "
6155 {
6156   rtx addr, reg, const_int;
6157
6158   if (GET_CODE (operands[1]) != MEM)
6159     FAIL;
6160   addr = XEXP (operands[1], 0);
6161   if (GET_CODE (addr) != PLUS)
6162     FAIL;
6163   reg = XEXP (addr, 0);
6164   const_int = XEXP (addr, 1);
6165   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6166          && GET_CODE (const_int) == CONST_INT))
6167     FAIL;
6168   emit_move_insn (operands[2], const_int);
6169   emit_move_insn (operands[0],
6170                   change_address (operands[1], VOIDmode,
6171                                   gen_rtx_PLUS (SImode, reg, operands[2])));
6172   DONE;
6173 }")
6174
6175 (define_split
6176   [(set (match_operand:SI 1 "" "")
6177         (match_operand:SI 0 "register_operand" ""))
6178    (clobber (match_operand 2 "register_operand" ""))]
6179   "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6180    && ALLOW_INDEXED_ADDRESS"
6181   [(use (reg:SI R0_REG))]
6182   "
6183 {
6184   rtx addr, reg, const_int;
6185
6186   if (GET_CODE (operands[1]) != MEM)
6187     FAIL;
6188   addr = XEXP (operands[1], 0);
6189   if (GET_CODE (addr) != PLUS)
6190     FAIL;
6191   reg = XEXP (addr, 0);
6192   const_int = XEXP (addr, 1);
6193   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6194          && GET_CODE (const_int) == CONST_INT))
6195     FAIL;
6196   emit_move_insn (operands[2], const_int);
6197   emit_move_insn (change_address (operands[1], VOIDmode,
6198                                   gen_rtx_PLUS (SImode, reg, operands[2])),
6199                   operands[0]);
6200   DONE;
6201 }")
6202
6203 (define_expand "movdf"
6204   [(set (match_operand:DF 0 "general_movdst_operand" "")
6205         (match_operand:DF 1 "general_movsrc_operand" ""))]
6206   ""
6207   "
6208 {
6209   if (prepare_move_operands (operands, DFmode)) DONE;
6210   if (TARGET_SHMEDIA)
6211     {
6212       if (TARGET_SHMEDIA_FPU)
6213         emit_insn (gen_movdf_media (operands[0], operands[1]));
6214       else
6215         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
6216       DONE;
6217     }
6218   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
6219     {
6220       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
6221       DONE;
6222     }
6223 }")
6224
6225 ;;This is incompatible with the way gcc uses subregs.
6226 ;;(define_insn "movv2sf_i"
6227 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
6228 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
6229 ;;  "TARGET_SHMEDIA_FPU
6230 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
6231 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
6232 ;;  "@
6233 ;;      #
6234 ;;      fld%M1.p        %m1, %0
6235 ;;      fst%M0.p        %m0, %1"
6236 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
6237
6238 (define_insn_and_split "movv2sf_i"
6239   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6240         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6241   "TARGET_SHMEDIA_FPU"
6242   "#"
6243   "TARGET_SHMEDIA_FPU && reload_completed"
6244   [(set (match_dup 0) (match_dup 1))]
6245   "
6246 {
6247   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
6248   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
6249 }")
6250
6251 (define_expand "movv2sf"
6252   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
6253         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
6254   "TARGET_SHMEDIA_FPU"
6255   "
6256 {
6257   if (prepare_move_operands (operands, V2SFmode))
6258     DONE;
6259 }")
6260
6261 (define_expand "addv2sf3"
6262   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6263    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6264    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6265   "TARGET_SHMEDIA_FPU"
6266   "
6267 {
6268   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
6269   DONE;
6270 }")
6271
6272 (define_expand "subv2sf3"
6273   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6274    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6275    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6276   "TARGET_SHMEDIA_FPU"
6277   "
6278 {
6279   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
6280   DONE;
6281 }")
6282
6283 (define_expand "mulv2sf3"
6284   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6285    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6286    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6287   "TARGET_SHMEDIA_FPU"
6288   "
6289 {
6290   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
6291   DONE;
6292 }")
6293
6294 (define_expand "divv2sf3"
6295   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6296    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6297    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6298   "TARGET_SHMEDIA_FPU"
6299   "
6300 {
6301   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
6302   DONE;
6303 }")
6304
6305 (define_insn_and_split "*movv4sf_i"
6306   [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6307         (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6308   "TARGET_SHMEDIA_FPU"
6309   "#"
6310   "&& reload_completed"
6311   [(const_int 0)]
6312   "
6313 {
6314   int i;
6315
6316   for (i = 0; i < 4/2; i++)
6317     {
6318       rtx x, y;
6319
6320       if (GET_CODE (operands[0]) == MEM)
6321         x = adjust_address (operands[0], V2SFmode,
6322                             i * GET_MODE_SIZE (V2SFmode));
6323       else
6324         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
6325
6326       if (GET_CODE (operands[1]) == MEM)
6327         y = adjust_address (operands[1], V2SFmode,
6328                             i * GET_MODE_SIZE (V2SFmode));
6329       else
6330         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
6331
6332       emit_insn (gen_movv2sf_i (x, y));
6333     }
6334
6335   DONE;
6336 }"
6337   [(set_attr "length" "8")])
6338
6339 (define_expand "movv4sf"
6340   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
6341         (match_operand:V4SF 1 "general_operand" ""))]
6342   "TARGET_SHMEDIA_FPU"
6343   "
6344 {
6345   if (prepare_move_operands (operands, V4SFmode))
6346     DONE;
6347 }")
6348
6349 (define_insn_and_split "*movv16sf_i"
6350   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6351         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6352   "TARGET_SHMEDIA_FPU"
6353   "#"
6354   "&& reload_completed"
6355   [(const_int 0)]
6356   "
6357 {
6358   int i;
6359
6360   for (i = 0; i < 16/2; i++)
6361     {
6362       rtx x,y;
6363
6364       if (GET_CODE (operands[0]) == MEM)
6365         x = adjust_address (operands[0], V2SFmode,
6366                             i * GET_MODE_SIZE (V2SFmode));
6367       else
6368         {
6369           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
6370           alter_subreg (&x);
6371         }
6372
6373       if (GET_CODE (operands[1]) == MEM)
6374         y = adjust_address (operands[1], V2SFmode,
6375                             i * GET_MODE_SIZE (V2SFmode));
6376       else
6377         {
6378           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
6379           alter_subreg (&y);
6380         }
6381
6382       emit_insn (gen_movv2sf_i (x, y));
6383     }
6384
6385   DONE;
6386 }"
6387   [(set_attr "length" "32")])
6388
6389 (define_expand "movv16sf"
6390   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6391         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6392   "TARGET_SHMEDIA_FPU"
6393   "
6394 {
6395   if (prepare_move_operands (operands, V16SFmode))
6396     DONE;
6397 }")
6398
6399 (define_insn "movsf_media"
6400   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6401         (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6402   "TARGET_SHMEDIA_FPU
6403    && (register_operand (operands[0], SFmode)
6404        || sh_register_operand (operands[1], SFmode))"
6405   "@
6406         fmov.s  %1, %0
6407         fmov.ls %N1, %0
6408         fmov.sl %1, %0
6409         add.l   %1, r63, %0
6410         #
6411         fld%M1.s        %m1, %0
6412         fst%M0.s        %m0, %1
6413         ld%M1.l %m1, %0
6414         st%M0.l %m0, %N1"
6415   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
6416    (set (attr "highpart")
6417         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6418                (const_string "user")]
6419               (const_string "ignore")))])
6420
6421 (define_insn "movsf_media_nofpu"
6422   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
6423         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6424   "TARGET_SHMEDIA
6425    && (register_operand (operands[0], SFmode)
6426        || sh_register_operand (operands[1], SFmode))"
6427   "@
6428         add.l   %1, r63, %0
6429         #
6430         ld%M1.l %m1, %0
6431         st%M0.l %m0, %N1"
6432   [(set_attr "type" "arith_media,*,load_media,store_media")
6433    (set (attr "highpart")
6434         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6435                (const_string "user")]
6436               (const_string "ignore")))])
6437
6438 (define_split
6439   [(set (match_operand:SF 0 "arith_reg_dest" "")
6440         (match_operand:SF 1 "immediate_operand" ""))]
6441   "TARGET_SHMEDIA && reload_completed
6442    && ! FP_REGISTER_P (true_regnum (operands[0]))"
6443   [(set (match_dup 3) (match_dup 2))]
6444   "
6445 {
6446   long values;
6447   REAL_VALUE_TYPE value;
6448
6449   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6450   REAL_VALUE_TO_TARGET_SINGLE (value, values);
6451   operands[2] = GEN_INT (values);
6452
6453   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6454 }")
6455
6456 (define_insn "movsf_i"
6457   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
6458         (match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
6459   "TARGET_SH1
6460    && (! TARGET_SH2E
6461        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
6462        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
6463        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
6464    && (arith_reg_operand (operands[0], SFmode)
6465        || arith_reg_operand (operands[1], SFmode))"
6466   "@
6467         mov     %1,%0
6468         mov     #0,%0
6469         mov.l   %1,%0
6470         mov.l   %1,%0
6471         mov.l   %1,%0
6472         lds     %1,%0
6473         sts     %1,%0"
6474   [(set_attr "type" "move,move,pcload,load,store,move,move")])
6475
6476 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
6477 ;; update_flow_info would not know where to put REG_EQUAL notes
6478 ;; when the destination changes mode.
6479 (define_insn "movsf_ie"
6480   [(set (match_operand:SF 0 "general_movdst_operand"
6481          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
6482         (match_operand:SF 1 "general_movsrc_operand"
6483           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
6484    (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"))
6485    (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
6486
6487   "TARGET_SH2E
6488    && (arith_reg_operand (operands[0], SFmode)
6489        || arith_reg_operand (operands[1], SFmode)
6490        || arith_reg_operand (operands[3], SImode)
6491        || (fpul_operand (operands[0], SFmode)
6492            && memory_operand (operands[1], SFmode)
6493            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
6494        || (fpul_operand (operands[1], SFmode)
6495            && memory_operand (operands[0], SFmode)
6496            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
6497   "@
6498         fmov    %1,%0
6499         mov     %1,%0
6500         fldi0   %0
6501         fldi1   %0
6502         #
6503         fmov.s  %1,%0
6504         fmov.s  %1,%0
6505         mov.l   %1,%0
6506         mov.l   %1,%0
6507         mov.l   %1,%0
6508         fsts    fpul,%0
6509         flds    %1,fpul
6510         lds.l   %1,%0
6511         #
6512         sts     %1,%0
6513         lds     %1,%0
6514         sts.l   %1,%0
6515         lds.l   %1,%0
6516         ! move optimized away"
6517   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,store,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,store,load,nil")
6518    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6519    (set_attr "length" "*,*,*,*,4,4,4,*,*,*,2,2,2,4,2,2,2,2,0")
6520    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6521                                            (const_string "single")
6522                                            (const_string "none")))])
6523
6524 (define_split
6525   [(set (match_operand:SF 0 "register_operand" "")
6526         (match_operand:SF 1 "register_operand" ""))
6527    (use (match_operand:PSI 2 "fpscr_operand" ""))
6528    (clobber (reg:SI FPUL_REG))]
6529   "TARGET_SH1"
6530   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
6531               (use (match_dup 2))
6532               (clobber (scratch:SI))])
6533    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
6534               (use (match_dup 2))
6535               (clobber (scratch:SI))])]
6536   "")
6537
6538 (define_expand "movsf"
6539   [(set (match_operand:SF 0 "general_movdst_operand" "")
6540         (match_operand:SF 1 "general_movsrc_operand" ""))]
6541   ""
6542   "
6543 {
6544   if (prepare_move_operands (operands, SFmode))
6545     DONE;
6546   if (TARGET_SHMEDIA)
6547     {
6548       if (TARGET_SHMEDIA_FPU)
6549         emit_insn (gen_movsf_media (operands[0], operands[1]));
6550       else
6551         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
6552       DONE;
6553     }
6554   if (TARGET_SH2E)
6555     {
6556       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
6557       DONE;
6558     }
6559 }")
6560
6561 (define_insn "mov_nop"
6562   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
6563   "TARGET_SH2E"
6564   ""
6565   [(set_attr "length" "0")
6566    (set_attr "type" "nil")])
6567
6568 (define_expand "reload_insf__frn"
6569   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
6570                    (match_operand:SF 1 "immediate_operand" "FQ"))
6571               (use (reg:PSI FPSCR_REG))
6572               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6573   "TARGET_SH1"
6574   "")
6575
6576 (define_expand "reload_insi__i_fpul"
6577   [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
6578                    (match_operand:SI 1 "immediate_operand" "i"))
6579               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6580   "TARGET_SH1"
6581   "")
6582
6583 (define_expand "ptabs"
6584   [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
6585   "TARGET_SHMEDIA"
6586   "
6587 {
6588   if (!TARGET_PT_FIXED)
6589     {
6590       rtx eq = operands[1];
6591
6592       /* ??? For canonical RTL we really should remove any CONST from EQ
6593          before wrapping it in the AND, and finally wrap the EQ into a
6594          const if is constant.  However, for reload we must expose the
6595          input register or symbolic constant, and we can't have
6596          different insn structures outside of the operands for different
6597          alternatives of the same pattern.  */
6598       eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
6599                        GEN_INT (3));
6600       operands[1]
6601         = (gen_rtx_IF_THEN_ELSE
6602             (PDImode,
6603              eq,
6604              gen_rtx_MEM (PDImode, operands[1]),
6605              gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
6606                             PDImode, operands[1])));
6607     }
6608 }")
6609
6610 ;; expanded by ptabs expander.
6611 (define_insn "*extendsipdi_media"
6612   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6613         (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
6614                                                           "r,Csy")
6615                                       (const_int 3))
6616                               (const_int 3))
6617                           (mem:PDI (match_dup 1))
6618                           (sign_extend:PDI (match_dup 1))))]
6619   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6620   "@
6621         ptabs   %1, %0
6622         pt      %1, %0"
6623   [(set_attr "type"   "ptabs_media,pt_media")
6624    (set_attr "length" "4,*")])
6625
6626 (define_insn "*truncdipdi_media"
6627   [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6628         (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
6629                                                           "r,Csy")
6630                                       (const_int 3))
6631                               (const_int 3))
6632                           (mem:PDI (match_dup 1))
6633                           (truncate:PDI (match_dup 1))))]
6634   "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6635   "@
6636         ptabs   %1, %0
6637         pt      %1, %0"
6638   [(set_attr "type"   "ptabs_media,pt_media")
6639    (set_attr "length" "4,*")])
6640
6641 (define_insn "*movsi_y"
6642   [(set (match_operand:SI 0 "register_operand" "=y,y")
6643         (match_operand:SI 1 "immediate_operand" "Qi,I08"))
6644    (clobber (match_scratch:SI 2 "=&z,r"))]
6645   "TARGET_SH2E
6646    && (reload_in_progress || reload_completed)"
6647   "#"
6648   [(set_attr "length" "4")
6649    (set_attr "type" "pcload,move")])
6650
6651 (define_split
6652   [(set (match_operand:SI 0 "register_operand" "")
6653         (match_operand:SI 1 "immediate_operand" ""))
6654    (clobber (match_operand:SI 2 "register_operand" ""))]
6655   "TARGET_SH1"
6656   [(set (match_dup 2) (match_dup 1))
6657    (set (match_dup 0) (match_dup 2))]
6658   "")
6659
6660 (define_split
6661   [(set (match_operand:SI 0 "register_operand" "")
6662         (match_operand:SI 1 "memory_operand" ""))
6663    (clobber (reg:SI R0_REG))]
6664   "TARGET_SH1"
6665   [(set (match_dup 0) (match_dup 1))]
6666   "")
6667 \f
6668 ;; ------------------------------------------------------------------------
6669 ;; Define the real conditional branch instructions.
6670 ;; ------------------------------------------------------------------------
6671
6672 (define_insn "branch_true"
6673   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
6674                            (label_ref (match_operand 0 "" ""))
6675                            (pc)))]
6676   "TARGET_SH1"
6677   "* return output_branch (1, insn, operands);"
6678   [(set_attr "type" "cbranch")])
6679
6680 (define_insn "branch_false"
6681   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
6682                            (label_ref (match_operand 0 "" ""))
6683                            (pc)))]
6684   "TARGET_SH1"
6685   "* return output_branch (0, insn, operands);"
6686   [(set_attr "type" "cbranch")])
6687
6688 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
6689 ;; which destination is too far away.
6690 ;; The const_int_operand is distinct for each branch target; it avoids
6691 ;; unwanted matches with redundant_insn.
6692 (define_insn "block_branch_redirect"
6693   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
6694   "TARGET_SH1"
6695   ""
6696   [(set_attr "length" "0")])
6697
6698 ;; This one has the additional purpose to record a possible scratch register
6699 ;; for the following branch.
6700 ;; ??? Unfortunately, just setting the scratch register is not good enough,
6701 ;; because the insn then might be deemed dead and deleted.  And we can't
6702 ;; make the use in the jump insn explicit because that would disable
6703 ;; delay slot scheduling from the target.
6704 (define_insn "indirect_jump_scratch"
6705   [(set (match_operand:SI 0 "register_operand" "=r")
6706         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
6707    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
6708   "TARGET_SH1"
6709   ""
6710   [(set_attr "length" "0")])
6711
6712 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
6713 ;; being pulled into the delay slot of a condbranch that has been made to
6714 ;; jump around the unconditional jump because it was out of range.
6715 (define_insn "stuff_delay_slot"
6716   [(set (pc)
6717         (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)] UNSPEC_BBR))
6718    (set (reg:SI T_REG) (match_operand:SI 1 "const_int_operand" ""))]
6719   "TARGET_SH1"
6720   ""
6721   [(set_attr "length" "0")
6722    (set_attr "cond_delay_slot" "yes")])
6723 \f
6724 ;; Conditional branch insns
6725
6726 (define_expand "beq_media"
6727   [(set (pc)
6728         (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
6729                           (match_operand:DI 2 "arith_operand" "r,I06"))
6730                       (match_operand 0 "" "")
6731                       (pc)))]
6732   "TARGET_SHMEDIA"
6733   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6734
6735 (define_insn "*beq_media_i"
6736   [(set (pc)
6737         (if_then_else (match_operator 3 "equality_comparison_operator"
6738                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
6739                          (match_operand:DI 2 "arith_operand" "r,I06")])
6740                       (match_operand 0 "target_operand" "b,b")
6741                       (pc)))]
6742   "TARGET_SHMEDIA"
6743   "@
6744         b%o3%'  %1, %2, %0%>
6745         b%o3i%' %1, %2, %0%>"
6746   [(set_attr "type" "cbranch_media")])
6747
6748 (define_insn "*beq_media_i32"
6749   [(set (pc)
6750         (if_then_else (match_operator 3 "equality_comparison_operator"
6751                         [(match_operand:SI 1 "arith_reg_operand" "r,r")
6752                          (match_operand:SI 2 "arith_operand" "r,I06")])
6753                       (match_operand 0 "target_operand" "b,b")
6754                       (pc)))]
6755   "TARGET_SHMEDIA"
6756   "@
6757         b%o3%'  %1, %2, %0%>
6758         b%o3i%' %1, %2, %0%>"
6759   [(set_attr "type" "cbranch_media")])
6760
6761 (define_expand "bne_media"
6762   [(set (pc)
6763         (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
6764                           (match_operand:DI 2 "arith_operand" "r,I06"))
6765                       (match_operand 0 "" "")
6766                       (pc)))]
6767   "TARGET_SHMEDIA"
6768   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6769
6770 (define_expand "bgt_media"
6771   [(set (pc)
6772         (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "")
6773                           (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6774                       (match_operand 0 "" "")
6775                       (pc)))]
6776   "TARGET_SHMEDIA"
6777   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6778
6779 (define_expand "bge_media"
6780   [(set (pc)
6781         (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "")
6782                           (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6783                       (match_operand 0 "" "")
6784                       (pc)))]
6785   "TARGET_SHMEDIA"
6786   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6787
6788 (define_expand "bgtu_media"
6789   [(set (pc)
6790         (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "")
6791                            (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6792                       (match_operand 0 "" "")
6793                       (pc)))]
6794   "TARGET_SHMEDIA"
6795   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6796
6797 (define_expand "bgeu_media"
6798   [(set (pc)
6799         (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "")
6800                            (match_operand:DI 2 "arith_reg_or_0_operand" ""))
6801                       (match_operand 0 "" "")
6802                       (pc)))]
6803   "TARGET_SHMEDIA"
6804   "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
6805
6806 (define_insn "*bgt_media_i"
6807   [(set (pc)
6808         (if_then_else (match_operator 3 "greater_comparison_operator"
6809                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6810                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6811                       (match_operand 0 "target_operand" "b")
6812                       (pc)))]
6813   "TARGET_SHMEDIA"
6814   "b%o3%'       %N1, %N2, %0%>"
6815   [(set_attr "type" "cbranch_media")])
6816
6817 (define_insn "*bgt_media_i32"
6818   [(set (pc)
6819         (if_then_else (match_operator 3 "greater_comparison_operator"
6820                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6821                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6822                       (match_operand 0 "target_operand" "b")
6823                       (pc)))]
6824   "TARGET_SHMEDIA"
6825   "b%o3%'       %N1, %N2, %0%>"
6826   [(set_attr "type" "cbranch_media")])
6827
6828 ;; These are only needed to make invert_jump() happy - otherwise, jump
6829 ;; optimization will be silently disabled.
6830 (define_insn "*blt_media_i"
6831   [(set (pc)
6832         (if_then_else (match_operator 3 "less_comparison_operator"
6833                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6834                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6835                       (match_operand 0 "target_operand" "b")
6836                       (pc)))]
6837   "TARGET_SHMEDIA"
6838   "b%o3%'       %N2, %N1, %0%>"
6839   [(set_attr "type" "cbranch_media")])
6840
6841 (define_insn "*blt_media_i32"
6842   [(set (pc)
6843         (if_then_else (match_operator 3 "less_comparison_operator"
6844                         [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6845                          (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6846                       (match_operand 0 "target_operand" "b")
6847                       (pc)))]
6848   "TARGET_SHMEDIA"
6849   "b%o3%'       %N2, %N1, %0%>"
6850   [(set_attr "type" "cbranch_media")])
6851
6852 (define_expand "beq"
6853   [(set (pc)
6854         (if_then_else (ne (reg:SI T_REG) (const_int 0))
6855                       (label_ref (match_operand 0 "" ""))
6856                       (pc)))]
6857   ""
6858   "
6859 {
6860   if (TARGET_SHMEDIA)
6861     {
6862       enum machine_mode mode = GET_MODE (sh_compare_op0);
6863
6864       if (mode != DImode && mode != SImode)
6865         {
6866           rtx tmp = gen_reg_rtx (DImode);
6867
6868           emit_insn (gen_seq (tmp));
6869           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6870           DONE;
6871         }
6872
6873       sh_compare_op0 = force_reg (mode, sh_compare_op0);
6874       if (CONSTANT_P (sh_compare_op1)
6875           && (GET_CODE (sh_compare_op1) != CONST_INT
6876               || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1))))
6877         sh_compare_op1 = force_reg (mode, sh_compare_op1);
6878       emit_jump_insn (gen_beq_media (operands[0],
6879                                      sh_compare_op0, sh_compare_op1));
6880       DONE;
6881     }
6882
6883   from_compare (operands, EQ);
6884 }")
6885
6886 (define_expand "bne"
6887   [(set (pc)
6888         (if_then_else (eq (reg:SI T_REG) (const_int 0))
6889                       (label_ref (match_operand 0 "" ""))
6890                       (pc)))]
6891   ""
6892   "
6893 {
6894   if (TARGET_SHMEDIA)
6895     {
6896       enum machine_mode mode = GET_MODE (sh_compare_op0);
6897
6898       if (mode != DImode && mode != SImode)
6899         {
6900           rtx tmp = gen_reg_rtx (DImode);
6901
6902           emit_insn (gen_seq (tmp));
6903           emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
6904           DONE;
6905         }
6906
6907       sh_compare_op0 = force_reg (mode, sh_compare_op0);
6908       if (CONSTANT_P (sh_compare_op1)
6909           && (GET_CODE (sh_compare_op1) != CONST_INT
6910               || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1))))
6911         sh_compare_op1 = force_reg (mode, sh_compare_op1);
6912       emit_jump_insn (gen_bne_media (operands[0],
6913                                      sh_compare_op0, sh_compare_op1));
6914       DONE;
6915     }
6916
6917   from_compare (operands, EQ);
6918 }")
6919
6920 (define_expand "bgt"
6921   [(set (pc)
6922         (if_then_else (ne (reg:SI T_REG) (const_int 0))
6923                       (label_ref (match_operand 0 "" ""))
6924                       (pc)))]
6925   ""
6926   "
6927 {
6928   if (TARGET_SHMEDIA)
6929     {
6930       enum machine_mode mode = GET_MODE (sh_compare_op0);
6931
6932       if (mode != DImode && mode != SImode)
6933         {
6934           rtx tmp = gen_reg_rtx (DImode);
6935
6936           emit_insn (gen_sgt (tmp));
6937           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6938           DONE;
6939         }
6940
6941       if (sh_compare_op0 != const0_rtx)
6942         sh_compare_op0 = force_reg (mode, sh_compare_op0);
6943       if (sh_compare_op1 != const0_rtx)
6944         sh_compare_op1 = force_reg (mode, sh_compare_op1);
6945       emit_jump_insn (gen_bgt_media (operands[0],
6946                                      sh_compare_op0, sh_compare_op1));
6947       DONE;
6948     }
6949
6950   from_compare (operands, GT);
6951 }")
6952
6953 (define_expand "blt"
6954   [(set (pc)
6955         (if_then_else (eq (reg:SI T_REG) (const_int 0))
6956                       (label_ref (match_operand 0 "" ""))
6957                       (pc)))]
6958   ""
6959   "
6960 {
6961   if (TARGET_SHMEDIA)
6962     {
6963       enum machine_mode mode = GET_MODE (sh_compare_op0);
6964
6965       if (mode != DImode && mode != SImode)
6966         {
6967           rtx tmp = gen_reg_rtx (DImode);
6968
6969           emit_insn (gen_slt (tmp));
6970           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
6971           DONE;
6972         }
6973
6974       if (sh_compare_op0 != const0_rtx)
6975         sh_compare_op0 = force_reg (mode, sh_compare_op0);
6976       if (sh_compare_op1 != const0_rtx)
6977         sh_compare_op1 = force_reg (mode, sh_compare_op1);
6978       emit_jump_insn (gen_bgt_media (operands[0],
6979                                      sh_compare_op1, sh_compare_op0));
6980       DONE;
6981     }
6982
6983   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
6984     {
6985       rtx tmp = sh_compare_op0;
6986       sh_compare_op0 = sh_compare_op1;
6987       sh_compare_op1 = tmp;
6988       emit_insn (gen_bgt (operands[0]));
6989       DONE;
6990     }
6991   from_compare (operands, GE);
6992 }")
6993
6994 (define_expand "ble"
6995   [(set (pc)
6996         (if_then_else (eq (reg:SI T_REG) (const_int 0))
6997                       (label_ref (match_operand 0 "" ""))
6998                       (pc)))]
6999   ""
7000   "
7001 {
7002   if (TARGET_SHMEDIA)
7003     {
7004       enum machine_mode mode = GET_MODE (sh_compare_op0);
7005
7006       if (mode != DImode && mode != SImode)
7007         {
7008           rtx tmp = gen_reg_rtx (DImode);
7009
7010           emit_insn (gen_sle (tmp));
7011           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7012           DONE;
7013         }
7014
7015       if (sh_compare_op0 != const0_rtx)
7016         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7017       if (sh_compare_op1 != const0_rtx)
7018         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7019       emit_jump_insn (gen_bge_media (operands[0],
7020                                      sh_compare_op1, sh_compare_op0));
7021       DONE;
7022     }
7023
7024   if (TARGET_SH2E
7025       && TARGET_IEEE
7026       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7027     {
7028       rtx tmp = sh_compare_op0;
7029       sh_compare_op0 = sh_compare_op1;
7030       sh_compare_op1 = tmp;
7031       emit_insn (gen_bge (operands[0]));
7032       DONE;
7033     }
7034   from_compare (operands, GT);
7035 }")
7036
7037 (define_expand "bge"
7038   [(set (pc)
7039         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7040                       (label_ref (match_operand 0 "" ""))
7041                       (pc)))]
7042   ""
7043   "
7044 {
7045   if (TARGET_SHMEDIA)
7046     {
7047       enum machine_mode mode = GET_MODE (sh_compare_op0);
7048
7049       if (mode != DImode && mode != SImode)
7050         {
7051           rtx tmp = gen_reg_rtx (DImode);
7052
7053           emit_insn (gen_sge (tmp));
7054           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
7055           DONE;
7056         }
7057
7058       if (sh_compare_op0 != const0_rtx)
7059         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7060       if (sh_compare_op1 != const0_rtx)
7061         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7062       emit_jump_insn (gen_bge_media (operands[0],
7063                                      sh_compare_op0, sh_compare_op1));
7064       DONE;
7065     }
7066
7067   if (TARGET_SH2E
7068       && ! TARGET_IEEE
7069       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7070     {
7071       rtx tmp = sh_compare_op0;
7072       sh_compare_op0 = sh_compare_op1;
7073       sh_compare_op1 = tmp;
7074       emit_insn (gen_ble (operands[0]));
7075       DONE;
7076     }
7077   from_compare (operands, GE);
7078 }")
7079
7080 (define_expand "bgtu"
7081   [(set (pc)
7082         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7083                       (label_ref (match_operand 0 "" ""))
7084                       (pc)))]
7085   ""
7086   "
7087 {
7088   if (TARGET_SHMEDIA)
7089     {
7090       enum machine_mode mode = GET_MODE (sh_compare_op0);
7091
7092       if (sh_compare_op0 != const0_rtx)
7093         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7094       if (sh_compare_op1 != const0_rtx)
7095         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7096       emit_jump_insn (gen_bgtu_media (operands[0],
7097                                       sh_compare_op0, sh_compare_op1));
7098       DONE;
7099     }
7100
7101   from_compare (operands, GTU);
7102 }")
7103
7104 (define_expand "bltu"
7105   [(set (pc)
7106         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7107                       (label_ref (match_operand 0 "" ""))
7108                       (pc)))]
7109   ""
7110   "
7111 {
7112   if (TARGET_SHMEDIA)
7113     {
7114       enum machine_mode mode = GET_MODE (sh_compare_op0);
7115
7116       if (sh_compare_op0 != const0_rtx)
7117         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7118       if (sh_compare_op1 != const0_rtx)
7119         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7120       emit_jump_insn (gen_bgtu_media (operands[0],
7121                                       sh_compare_op1, sh_compare_op0));
7122       DONE;
7123     }
7124
7125   from_compare (operands, GEU);
7126 }")
7127
7128 (define_expand "bgeu"
7129   [(set (pc)
7130         (if_then_else (ne (reg:SI T_REG) (const_int 0))
7131                       (label_ref (match_operand 0 "" ""))
7132                       (pc)))]
7133   ""
7134   "
7135 {
7136   if (TARGET_SHMEDIA)
7137     {
7138       enum machine_mode mode = GET_MODE (sh_compare_op0);
7139
7140       if (sh_compare_op0 != const0_rtx)
7141         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7142       if (sh_compare_op1 != const0_rtx)
7143         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7144       emit_jump_insn (gen_bgeu_media (operands[0],
7145                                       sh_compare_op0, sh_compare_op1));
7146       DONE;
7147     }
7148
7149   from_compare (operands, GEU);
7150 }")
7151
7152 (define_expand "bleu"
7153   [(set (pc)
7154         (if_then_else (eq (reg:SI T_REG) (const_int 0))
7155                       (label_ref (match_operand 0 "" ""))
7156                       (pc)))]
7157   ""
7158   "
7159 {
7160   if (TARGET_SHMEDIA)
7161     {
7162       enum machine_mode mode = GET_MODE (sh_compare_op0);
7163
7164       if (sh_compare_op0 != const0_rtx)
7165         sh_compare_op0 = force_reg (mode, sh_compare_op0);
7166       if (sh_compare_op1 != const0_rtx)
7167         sh_compare_op1 = force_reg (mode, sh_compare_op1);
7168       emit_jump_insn (gen_bgeu_media (operands[0],
7169                                       sh_compare_op1, sh_compare_op0));
7170       DONE;
7171     }
7172
7173   from_compare (operands, GTU);
7174 }")
7175
7176 (define_expand "bunordered"
7177   [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3)))
7178    (set (pc)
7179         (if_then_else (ne (match_dup 1) (const_int 0))
7180                       (match_operand 0 "" "")
7181                       (pc)))]
7182   "TARGET_SHMEDIA"
7183   "
7184 {
7185   operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);
7186   operands[1] = gen_reg_rtx (DImode);
7187   operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7188   operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
7189 }")
7190
7191 ;; combiner splitter for test-and-branch on single bit in register.  This
7192 ;; is endian dependent because the non-paradoxical subreg looks different
7193 ;; on big endian.
7194 (define_split
7195   [(set (pc)
7196         (if_then_else
7197           (match_operator 3 "equality_comparison_operator"
7198             [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
7199                                                       "extend_reg_operand" "")
7200                                                     0)
7201                                          (const_int 1)
7202                                          (match_operand 2
7203                                           "const_int_operand" "")) 0)
7204              (const_int 0)])
7205           (match_operand 0 "target_operand" "")
7206           (pc)))
7207    (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
7208   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
7209   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
7210    (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
7211
7212   "
7213 {
7214   operands[5] = GEN_INT (31 - INTVAL (operands[2]));
7215   operands[6] = (GET_CODE (operands[3]) == EQ
7216                  ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
7217                  : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
7218 }")
7219 \f
7220 ;; ------------------------------------------------------------------------
7221 ;; Jump and linkage insns
7222 ;; ------------------------------------------------------------------------
7223
7224 (define_insn "jump_compact"
7225   [(set (pc)
7226         (label_ref (match_operand 0 "" "")))]
7227   "TARGET_SH1"
7228   "*
7229 {
7230   /* The length is 16 if the delay slot is unfilled.  */
7231   if (get_attr_length(insn) > 4)
7232     return output_far_jump(insn, operands[0]);
7233   else
7234     return   \"bra      %l0%#\";
7235 }"
7236   [(set_attr "type" "jump")
7237    (set_attr "needs_delay_slot" "yes")])
7238
7239 ;; ??? It would be much saner to explicitly use the scratch register
7240 ;; in the jump insn, and have indirect_jump_scratch only set it,
7241 ;; but fill_simple_delay_slots would refuse to do delay slot filling
7242 ;; from the target then, as it uses simplejump_p.
7243 ;;(define_insn "jump_compact_far"
7244 ;;  [(set (pc)
7245 ;;      (label_ref (match_operand 0 "" "")))
7246 ;;   (use (match_operand 1 "register_operand" "r")]
7247 ;;  "TARGET_SH1"
7248 ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
7249 ;;  [(set_attr "type" "jump")
7250 ;;   (set_attr "needs_delay_slot" "yes")])
7251
7252 (define_insn "jump_media"
7253   [(set (pc)
7254         (match_operand 0 "target_operand" "b"))]
7255   "TARGET_SHMEDIA"
7256   "blink        %0, r63%>"
7257   [(set_attr "type" "jump_media")])
7258
7259 (define_expand "jump"
7260   [(set (pc)
7261         (label_ref (match_operand 0 "" "")))]
7262   ""
7263   "
7264 {
7265   if (TARGET_SH1)
7266     emit_jump_insn (gen_jump_compact (operands[0]));
7267   else if (TARGET_SHMEDIA)
7268     {
7269       if (reload_in_progress || reload_completed)
7270         FAIL;
7271       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
7272                                                          operands[0])));
7273     }
7274   DONE;
7275 }")
7276
7277 (define_insn "force_mode_for_call"
7278   [(use (reg:PSI FPSCR_REG))]
7279   "TARGET_SHCOMPACT"
7280   ""
7281   [(set_attr "length" "0")
7282    (set (attr "fp_mode")
7283         (if_then_else (eq_attr "fpu_single" "yes")
7284                       (const_string "single") (const_string "double")))])
7285
7286 (define_insn "calli"
7287   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7288          (match_operand 1 "" ""))
7289    (use (reg:PSI FPSCR_REG))
7290    (clobber (reg:SI PR_REG))]
7291   "TARGET_SH1"
7292   "jsr  @%0%#"
7293   [(set_attr "type" "call")
7294    (set (attr "fp_mode")
7295         (if_then_else (eq_attr "fpu_single" "yes")
7296                       (const_string "single") (const_string "double")))
7297    (set_attr "needs_delay_slot" "yes")
7298    (set_attr "fp_set" "unknown")])
7299
7300 ;; This is a pc-rel call, using bsrf, for use with PIC.
7301
7302 (define_insn "calli_pcrel"
7303   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7304          (match_operand 1 "" ""))
7305    (use (reg:PSI FPSCR_REG))
7306    (use (reg:SI PIC_REG))
7307    (use (match_operand 2 "" ""))
7308    (clobber (reg:SI PR_REG))]
7309   "TARGET_SH2"
7310   "bsrf %0\\n%O2:%#"
7311   [(set_attr "type" "call")
7312    (set (attr "fp_mode")
7313         (if_then_else (eq_attr "fpu_single" "yes")
7314                       (const_string "single") (const_string "double")))
7315    (set_attr "needs_delay_slot" "yes")
7316    (set_attr "fp_set" "unknown")])
7317
7318 (define_insn_and_split "call_pcrel"
7319   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7320          (match_operand 1 "" ""))
7321    (use (reg:PSI FPSCR_REG))
7322    (use (reg:SI PIC_REG))
7323    (clobber (reg:SI PR_REG))
7324    (clobber (match_scratch:SI 2 "=r"))]
7325   "TARGET_SH2"
7326   "#"
7327   "reload_completed"
7328   [(const_int 0)]
7329   "
7330 {
7331   rtx lab = PATTERN (gen_call_site ());
7332
7333   if (SYMBOL_REF_LOCAL_P (operands[0]))
7334     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7335   else
7336     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
7337   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], lab));
7338   DONE;
7339 }"
7340   [(set_attr "type" "call")
7341    (set (attr "fp_mode")
7342         (if_then_else (eq_attr "fpu_single" "yes")
7343                       (const_string "single") (const_string "double")))
7344    (set_attr "needs_delay_slot" "yes")
7345    (set_attr "fp_set" "unknown")])
7346
7347 (define_insn "call_compact"
7348   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7349          (match_operand 1 "" ""))
7350    (match_operand 2 "immediate_operand" "n")
7351    (use (reg:SI R0_REG))
7352    (use (reg:SI R1_REG))
7353    (use (reg:PSI FPSCR_REG))
7354    (clobber (reg:SI PR_REG))]
7355   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7356   "jsr  @%0%#"
7357   [(set_attr "type" "call")
7358    (set (attr "fp_mode")
7359         (if_then_else (eq_attr "fpu_single" "yes")
7360                       (const_string "single") (const_string "double")))
7361    (set_attr "needs_delay_slot" "yes")])
7362
7363 (define_insn "call_compact_rettramp"
7364   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7365          (match_operand 1 "" ""))
7366    (match_operand 2 "immediate_operand" "n")
7367    (use (reg:SI R0_REG))
7368    (use (reg:SI R1_REG))
7369    (use (reg:PSI FPSCR_REG))
7370    (clobber (reg:SI R10_REG))
7371    (clobber (reg:SI PR_REG))]
7372   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7373   "jsr  @%0%#"
7374   [(set_attr "type" "call")
7375    (set (attr "fp_mode")
7376         (if_then_else (eq_attr "fpu_single" "yes")
7377                       (const_string "single") (const_string "double")))
7378    (set_attr "needs_delay_slot" "yes")])
7379
7380 (define_insn "call_media"
7381   [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
7382          (match_operand 1 "" ""))
7383    (clobber (reg:DI PR_MEDIA_REG))]
7384   "TARGET_SHMEDIA"
7385   "blink        %0, r18"
7386   [(set_attr "type" "jump_media")])
7387
7388 (define_insn "call_valuei"
7389   [(set (match_operand 0 "" "=rf")
7390         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7391               (match_operand 2 "" "")))
7392    (use (reg:PSI FPSCR_REG))
7393    (clobber (reg:SI PR_REG))]
7394   "TARGET_SH1"
7395   "jsr  @%1%#"
7396   [(set_attr "type" "call")
7397    (set (attr "fp_mode")
7398         (if_then_else (eq_attr "fpu_single" "yes")
7399                       (const_string "single") (const_string "double")))
7400    (set_attr "needs_delay_slot" "yes")
7401    (set_attr "fp_set" "unknown")])
7402
7403 (define_insn "call_valuei_pcrel"
7404   [(set (match_operand 0 "" "=rf")
7405         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7406               (match_operand 2 "" "")))
7407    (use (reg:PSI FPSCR_REG))
7408    (use (reg:SI PIC_REG))
7409    (use (match_operand 3 "" ""))
7410    (clobber (reg:SI PR_REG))]
7411   "TARGET_SH2"
7412   "bsrf %1\\n%O3:%#"
7413   [(set_attr "type" "call")
7414    (set (attr "fp_mode")
7415         (if_then_else (eq_attr "fpu_single" "yes")
7416                       (const_string "single") (const_string "double")))
7417    (set_attr "needs_delay_slot" "yes")
7418    (set_attr "fp_set" "unknown")])
7419
7420 (define_insn_and_split "call_value_pcrel"
7421   [(set (match_operand 0 "" "=rf")
7422         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7423               (match_operand 2 "" "")))
7424    (use (reg:PSI FPSCR_REG))
7425    (use (reg:SI PIC_REG))
7426    (clobber (reg:SI PR_REG))
7427    (clobber (match_scratch:SI 3 "=r"))]
7428   "TARGET_SH2"
7429   "#"
7430   "reload_completed"
7431   [(const_int 0)]
7432   "
7433 {
7434   rtx lab = PATTERN (gen_call_site ());
7435
7436   if (SYMBOL_REF_LOCAL_P (operands[1]))
7437     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7438   else
7439     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
7440   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
7441                                          operands[2], lab));
7442   DONE;
7443 }"
7444   [(set_attr "type" "call")
7445    (set (attr "fp_mode")
7446         (if_then_else (eq_attr "fpu_single" "yes")
7447                       (const_string "single") (const_string "double")))
7448    (set_attr "needs_delay_slot" "yes")
7449    (set_attr "fp_set" "unknown")])
7450
7451 (define_insn "call_value_compact"
7452   [(set (match_operand 0 "" "=rf")
7453         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7454               (match_operand 2 "" "")))
7455    (match_operand 3 "immediate_operand" "n")
7456    (use (reg:SI R0_REG))
7457    (use (reg:SI R1_REG))
7458    (use (reg:PSI FPSCR_REG))
7459    (clobber (reg:SI PR_REG))]
7460   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7461   "jsr  @%1%#"
7462   [(set_attr "type" "call")
7463    (set (attr "fp_mode")
7464         (if_then_else (eq_attr "fpu_single" "yes")
7465                       (const_string "single") (const_string "double")))
7466    (set_attr "needs_delay_slot" "yes")])
7467
7468 (define_insn "call_value_compact_rettramp"
7469   [(set (match_operand 0 "" "=rf")
7470         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7471               (match_operand 2 "" "")))
7472    (match_operand 3 "immediate_operand" "n")
7473    (use (reg:SI R0_REG))
7474    (use (reg:SI R1_REG))
7475    (use (reg:PSI FPSCR_REG))
7476    (clobber (reg:SI R10_REG))
7477    (clobber (reg:SI PR_REG))]
7478   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7479   "jsr  @%1%#"
7480   [(set_attr "type" "call")
7481    (set (attr "fp_mode")
7482         (if_then_else (eq_attr "fpu_single" "yes")
7483                       (const_string "single") (const_string "double")))
7484    (set_attr "needs_delay_slot" "yes")])
7485
7486 (define_insn "call_value_media"
7487   [(set (match_operand 0 "" "=rf")
7488         (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
7489               (match_operand 2 "" "")))
7490    (clobber (reg:DI PR_MEDIA_REG))]
7491   "TARGET_SHMEDIA"
7492   "blink        %1, r18"
7493   [(set_attr "type" "jump_media")])
7494
7495 (define_expand "call"
7496   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7497                             (match_operand 1 "" ""))
7498               (match_operand 2 "" "")
7499               (use (reg:PSI FPSCR_REG))
7500               (clobber (reg:SI PR_REG))])]
7501   ""
7502   "
7503 {
7504   if (TARGET_SHMEDIA)
7505     {
7506       operands[0] = shmedia_prepare_call_address (operands[0], 0);
7507       emit_call_insn (gen_call_media (operands[0], operands[1]));
7508       DONE;
7509     }
7510   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
7511     {
7512       rtx cookie_rtx = operands[2];
7513       long cookie = INTVAL (cookie_rtx);
7514       rtx func = XEXP (operands[0], 0);
7515       rtx r0, r1;
7516
7517       if (flag_pic)
7518         {
7519           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7520             {
7521               rtx reg = gen_reg_rtx (Pmode);
7522
7523               emit_insn (gen_symGOTPLT2reg (reg, func));
7524               func = reg;
7525             }
7526           else
7527             func = legitimize_pic_address (func, Pmode, 0);
7528         }
7529
7530       r0 = gen_rtx_REG (SImode, R0_REG);
7531       r1 = gen_rtx_REG (SImode, R1_REG);
7532
7533       /* Since such a call function may use all call-clobbered
7534          registers, we force a mode switch earlier, so that we don't
7535          run out of registers when adjusting fpscr for the call.  */
7536       emit_insn (gen_force_mode_for_call ());
7537
7538       operands[0]
7539         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7540                            SFUNC_GOT);
7541       operands[0] = force_reg (SImode, operands[0]);
7542
7543       emit_move_insn (r0, func);
7544       emit_move_insn (r1, cookie_rtx);
7545
7546       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7547         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
7548                                                    operands[2]));
7549       else
7550         emit_call_insn (gen_call_compact (operands[0], operands[1],
7551                                           operands[2]));
7552
7553       DONE;
7554     }
7555   else if (TARGET_SHCOMPACT && flag_pic
7556            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7557            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7558     {
7559       rtx reg = gen_reg_rtx (Pmode);
7560
7561       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
7562       XEXP (operands[0], 0) = reg;
7563     }
7564   if (flag_pic && TARGET_SH2
7565       && GET_CODE (operands[0]) == MEM
7566       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7567     {
7568       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
7569       DONE;
7570     }
7571   else
7572   {
7573     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7574     operands[1] = operands[2];
7575   }
7576
7577   emit_call_insn (gen_calli (operands[0], operands[1]));
7578   DONE;
7579 }")
7580
7581 (define_insn "call_pop_compact"
7582   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7583          (match_operand 1 "" ""))
7584    (match_operand 2 "immediate_operand" "n")
7585    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7586                                  (match_operand 3 "immediate_operand" "n")))
7587    (use (reg:SI R0_REG))
7588    (use (reg:SI R1_REG))
7589    (use (reg:PSI FPSCR_REG))
7590    (clobber (reg:SI PR_REG))]
7591   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7592   "jsr  @%0%#"
7593   [(set_attr "type" "call")
7594    (set (attr "fp_mode")
7595         (if_then_else (eq_attr "fpu_single" "yes")
7596                       (const_string "single") (const_string "double")))
7597    (set_attr "needs_delay_slot" "yes")])
7598
7599 (define_insn "call_pop_compact_rettramp"
7600   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7601          (match_operand 1 "" ""))
7602    (match_operand 2 "immediate_operand" "n")
7603    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7604                                  (match_operand 3 "immediate_operand" "n")))
7605    (use (reg:SI R0_REG))
7606    (use (reg:SI R1_REG))
7607    (use (reg:PSI FPSCR_REG))
7608    (clobber (reg:SI R10_REG))
7609    (clobber (reg:SI PR_REG))]
7610   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7611   "jsr  @%0%#"
7612   [(set_attr "type" "call")
7613    (set (attr "fp_mode")
7614         (if_then_else (eq_attr "fpu_single" "yes")
7615                       (const_string "single") (const_string "double")))
7616    (set_attr "needs_delay_slot" "yes")])
7617
7618 (define_expand "call_pop"
7619   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7620                     (match_operand 1 "" ""))
7621              (match_operand 2 "" "")
7622              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7623                                            (match_operand 3 "" "")))])]
7624   "TARGET_SHCOMPACT"
7625   "
7626 {
7627   rtx cookie_rtx;
7628   long cookie;
7629   rtx func;
7630   rtx r0, r1;
7631
7632   gcc_assert (operands[2] && INTVAL (operands[2]));
7633   cookie_rtx = operands[2];
7634   cookie = INTVAL (cookie_rtx);
7635   func = XEXP (operands[0], 0);
7636
7637   if (flag_pic)
7638     {
7639       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7640         {
7641           rtx reg = gen_reg_rtx (Pmode);
7642           emit_insn (gen_symGOTPLT2reg (reg, func));
7643           func = reg;
7644         }
7645       else
7646         func = legitimize_pic_address (func, Pmode, 0);
7647     }
7648
7649   r0 = gen_rtx_REG (SImode, R0_REG);
7650   r1 = gen_rtx_REG (SImode, R1_REG);
7651
7652   /* Since such a call function may use all call-clobbered
7653      registers, we force a mode switch earlier, so that we don't
7654      run out of registers when adjusting fpscr for the call.  */
7655   emit_insn (gen_force_mode_for_call ());
7656
7657   operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7658                                  SFUNC_GOT);
7659   operands[0] = force_reg (SImode, operands[0]);
7660
7661   emit_move_insn (r0, func);
7662   emit_move_insn (r1, cookie_rtx);
7663
7664   if (cookie & CALL_COOKIE_RET_TRAMP (1))
7665     emit_call_insn (gen_call_pop_compact_rettramp
7666                      (operands[0], operands[1], operands[2], operands[3]));
7667   else
7668     emit_call_insn (gen_call_pop_compact
7669                      (operands[0], operands[1], operands[2], operands[3]));
7670
7671   DONE;
7672 }")
7673
7674 (define_expand "call_value"
7675   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7676                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7677                                  (match_operand 2 "" "")))
7678               (match_operand 3 "" "")
7679               (use (reg:PSI FPSCR_REG))
7680               (clobber (reg:SI PR_REG))])]
7681   ""
7682   "
7683 {
7684   if (TARGET_SHMEDIA)
7685     {
7686       operands[1] = shmedia_prepare_call_address (operands[1], 0);
7687       emit_call_insn (gen_call_value_media (operands[0], operands[1],
7688                                             operands[2]));
7689       DONE;
7690     }
7691   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
7692     {
7693       rtx cookie_rtx = operands[3];
7694       long cookie = INTVAL (cookie_rtx);
7695       rtx func = XEXP (operands[1], 0);
7696       rtx r0, r1;
7697
7698       if (flag_pic)
7699         {
7700           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7701             {
7702               rtx reg = gen_reg_rtx (Pmode);
7703
7704               emit_insn (gen_symGOTPLT2reg (reg, func));
7705               func = reg;
7706             }
7707           else
7708             func = legitimize_pic_address (func, Pmode, 0);
7709         }
7710
7711       r0 = gen_rtx_REG (SImode, R0_REG);
7712       r1 = gen_rtx_REG (SImode, R1_REG);
7713
7714       /* Since such a call function may use all call-clobbered
7715          registers, we force a mode switch earlier, so that we don't
7716          run out of registers when adjusting fpscr for the call.  */
7717       emit_insn (gen_force_mode_for_call ());
7718
7719       operands[1]
7720         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7721                            SFUNC_GOT);
7722       operands[1] = force_reg (SImode, operands[1]);
7723
7724       emit_move_insn (r0, func);
7725       emit_move_insn (r1, cookie_rtx);
7726
7727       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7728         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
7729                                                          operands[1],
7730                                                          operands[2],
7731                                                          operands[3]));
7732       else
7733         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
7734                                                 operands[2], operands[3]));
7735
7736       DONE;
7737     }
7738   else if (TARGET_SHCOMPACT && flag_pic
7739            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7740            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
7741     {
7742       rtx reg = gen_reg_rtx (Pmode);
7743
7744       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
7745       XEXP (operands[1], 0) = reg;
7746     }
7747   if (flag_pic && TARGET_SH2
7748       && GET_CODE (operands[1]) == MEM
7749       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7750     {
7751       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
7752                                             operands[2]));
7753       DONE;
7754     }
7755   else
7756     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
7757
7758   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
7759   DONE;
7760 }")
7761
7762 (define_insn "sibcalli"
7763   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
7764          (match_operand 1 "" ""))
7765    (use (reg:PSI FPSCR_REG))
7766    (return)]
7767   "TARGET_SH1"
7768   "jmp  @%0%#"
7769   [(set_attr "needs_delay_slot" "yes")
7770    (set (attr "fp_mode")
7771         (if_then_else (eq_attr "fpu_single" "yes")
7772                       (const_string "single") (const_string "double")))
7773    (set_attr "type" "jump_ind")])
7774
7775 (define_insn "sibcalli_pcrel"
7776   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
7777          (match_operand 1 "" ""))
7778    (use (match_operand 2 "" ""))
7779    (use (reg:PSI FPSCR_REG))
7780    (return)]
7781   "TARGET_SH2"
7782   "braf %0\\n%O2:%#"
7783   [(set_attr "needs_delay_slot" "yes")
7784    (set (attr "fp_mode")
7785         (if_then_else (eq_attr "fpu_single" "yes")
7786                       (const_string "single") (const_string "double")))
7787    (set_attr "type" "jump_ind")])
7788
7789 ;; This uses an unspec to describe that the symbol_ref is very close.
7790 (define_insn "sibcalli_thunk"
7791   [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
7792                              UNSPEC_THUNK))
7793          (match_operand 1 "" ""))
7794    (use (reg:PSI FPSCR_REG))
7795    (return)]
7796   "TARGET_SH1"
7797   "bra  %O0"
7798   [(set_attr "needs_delay_slot" "yes")
7799    (set (attr "fp_mode")
7800         (if_then_else (eq_attr "fpu_single" "yes")
7801                       (const_string "single") (const_string "double")))
7802    (set_attr "type" "jump")
7803    (set_attr "length" "2")])
7804
7805 (define_insn_and_split "sibcall_pcrel"
7806   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7807          (match_operand 1 "" ""))
7808    (use (reg:PSI FPSCR_REG))
7809    (clobber (match_scratch:SI 2 "=k"))
7810    (return)]
7811   "TARGET_SH2"
7812   "#"
7813   "reload_completed"
7814   [(const_int 0)]
7815   "
7816 {
7817   rtx lab = PATTERN (gen_call_site ());
7818   rtx call_insn;
7819
7820   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7821   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
7822                                                   lab));
7823   SIBLING_CALL_P (call_insn) = 1;
7824   DONE;
7825 }"
7826   [(set_attr "needs_delay_slot" "yes")
7827    (set (attr "fp_mode")
7828         (if_then_else (eq_attr "fpu_single" "yes")
7829                       (const_string "single") (const_string "double")))
7830    (set_attr "type" "jump_ind")])
7831
7832 (define_insn "sibcall_compact"
7833   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
7834          (match_operand 1 "" ""))
7835    (return)
7836    (use (match_operand:SI 2 "register_operand" "z,x"))
7837    (use (reg:SI R1_REG))
7838    (use (reg:PSI FPSCR_REG))
7839    ;; We want to make sure the `x' above will only match MACH_REG
7840    ;; because sibcall_epilogue may clobber MACL_REG.
7841    (clobber (reg:SI MACL_REG))]
7842   "TARGET_SHCOMPACT"
7843   "@
7844         jmp     @%0%#
7845         jmp     @%0\\n  sts     %2, r0"
7846   [(set_attr "needs_delay_slot" "yes,no")
7847    (set_attr "length" "2,4")
7848    (set (attr "fp_mode") (const_string "single"))
7849    (set_attr "type" "jump_ind")])
7850
7851 (define_insn "sibcall_media"
7852   [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
7853          (match_operand 1 "" ""))
7854    (use (reg:SI PR_MEDIA_REG))
7855    (return)]
7856   "TARGET_SHMEDIA"
7857   "blink        %0, r63"
7858   [(set_attr "type" "jump_media")])
7859
7860 (define_expand "sibcall"
7861   [(parallel
7862     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7863            (match_operand 1 "" ""))
7864      (match_operand 2 "" "")
7865      (use (reg:PSI FPSCR_REG))
7866      (return)])]
7867   ""
7868   "
7869 {
7870   if (TARGET_SHMEDIA)
7871     {
7872       operands[0] = shmedia_prepare_call_address (operands[0], 1);
7873       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
7874       DONE;
7875     }
7876   else if (TARGET_SHCOMPACT && operands[2]
7877            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
7878     {
7879       rtx cookie_rtx = operands[2];
7880       long cookie = INTVAL (cookie_rtx);
7881       rtx func = XEXP (operands[0], 0);
7882       rtx mach, r1;
7883
7884       if (flag_pic)
7885         {
7886           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7887             {
7888               rtx reg = gen_reg_rtx (Pmode);
7889
7890               emit_insn (gen_symGOT2reg (reg, func));
7891               func = reg;
7892             }
7893           else
7894             func = legitimize_pic_address (func, Pmode, 0);
7895         }
7896
7897       /* FIXME: if we could tell whether all argument registers are
7898          already taken, we could decide whether to force the use of
7899          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
7900          simple way to tell.  We could use the CALL_COOKIE, but we
7901          can't currently tell a register used for regular argument
7902          passing from one that is unused.  If we leave it up to reload
7903          to decide which register to use, it seems to always choose
7904          R0_REG, which leaves no available registers in SIBCALL_REGS
7905          to hold the address of the trampoline.  */
7906       mach = gen_rtx_REG (SImode, MACH_REG);
7907       r1 = gen_rtx_REG (SImode, R1_REG);
7908
7909       /* Since such a call function may use all call-clobbered
7910          registers, we force a mode switch earlier, so that we don't
7911          run out of registers when adjusting fpscr for the call.  */
7912       emit_insn (gen_force_mode_for_call ());
7913
7914       operands[0]
7915         = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7916                            SFUNC_GOT);
7917       operands[0] = force_reg (SImode, operands[0]);
7918
7919       /* We don't need a return trampoline, since the callee will
7920          return directly to the upper caller.  */
7921       if (cookie & CALL_COOKIE_RET_TRAMP (1))
7922         {
7923           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
7924           cookie_rtx = GEN_INT (cookie);
7925         }
7926
7927       emit_move_insn (mach, func);
7928       emit_move_insn (r1, cookie_rtx);
7929
7930       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
7931       DONE;
7932     }
7933   else if (TARGET_SHCOMPACT && flag_pic
7934            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7935            && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7936     {
7937       rtx reg = gen_reg_rtx (Pmode);
7938
7939       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
7940       XEXP (operands[0], 0) = reg;
7941     }
7942   if (flag_pic && TARGET_SH2
7943       && GET_CODE (operands[0]) == MEM
7944       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7945       /* The PLT needs the PIC register, but the epilogue would have
7946          to restore it, so we can only use PC-relative PIC calls for
7947          static functions.  */
7948       && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7949     {
7950       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
7951       DONE;
7952     }
7953   else
7954     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7955
7956   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
7957   DONE;
7958 }")
7959
7960 (define_expand "sibcall_value"
7961   [(set (match_operand 0 "" "")
7962         (call (match_operand 1 "" "")
7963               (match_operand 2 "" "")))
7964    (match_operand 3 "" "")]
7965   ""
7966   "
7967 {
7968   emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
7969   DONE;
7970 }")
7971
7972 (define_insn "call_value_pop_compact"
7973   [(set (match_operand 0 "" "=rf")
7974         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7975               (match_operand 2 "" "")))
7976    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7977                                  (match_operand 4 "immediate_operand" "n")))
7978    (match_operand 3 "immediate_operand" "n")
7979    (use (reg:SI R0_REG))
7980    (use (reg:SI R1_REG))
7981    (use (reg:PSI FPSCR_REG))
7982    (clobber (reg:SI PR_REG))]
7983   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7984   "jsr  @%1%#"
7985   [(set_attr "type" "call")
7986    (set (attr "fp_mode")
7987         (if_then_else (eq_attr "fpu_single" "yes")
7988                       (const_string "single") (const_string "double")))
7989    (set_attr "needs_delay_slot" "yes")])
7990
7991 (define_insn "call_value_pop_compact_rettramp"
7992   [(set (match_operand 0 "" "=rf")
7993         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7994               (match_operand 2 "" "")))
7995    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7996                                  (match_operand 4 "immediate_operand" "n")))
7997    (match_operand 3 "immediate_operand" "n")
7998    (use (reg:SI R0_REG))
7999    (use (reg:SI R1_REG))
8000    (use (reg:PSI FPSCR_REG))
8001    (clobber (reg:SI R10_REG))
8002    (clobber (reg:SI PR_REG))]
8003   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8004   "jsr  @%1%#"
8005   [(set_attr "type" "call")
8006    (set (attr "fp_mode")
8007         (if_then_else (eq_attr "fpu_single" "yes")
8008                       (const_string "single") (const_string "double")))
8009    (set_attr "needs_delay_slot" "yes")])
8010
8011 (define_expand "call_value_pop"
8012   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
8013                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8014                                  (match_operand 2 "" "")))
8015               (match_operand 3 "" "")
8016               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8017                                             (match_operand 4 "" "")))])]
8018   "TARGET_SHCOMPACT"
8019   "
8020 {
8021   rtx cookie_rtx;
8022   long cookie;
8023   rtx func;
8024   rtx r0, r1;
8025
8026   gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
8027   cookie_rtx = operands[3];
8028   cookie = INTVAL (cookie_rtx);
8029   func = XEXP (operands[1], 0);
8030
8031   if (flag_pic)
8032     {
8033       if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8034         {
8035           rtx reg = gen_reg_rtx (Pmode);
8036
8037           emit_insn (gen_symGOTPLT2reg (reg, func));
8038           func = reg;
8039         }
8040       else
8041         func = legitimize_pic_address (func, Pmode, 0);
8042     }
8043
8044   r0 = gen_rtx_REG (SImode, R0_REG);
8045   r1 = gen_rtx_REG (SImode, R1_REG);
8046
8047   /* Since such a call function may use all call-clobbered
8048      registers, we force a mode switch earlier, so that we don't
8049      run out of registers when adjusting fpscr for the call.  */
8050   emit_insn (gen_force_mode_for_call ());
8051
8052   operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8053                                  SFUNC_GOT);
8054   operands[1] = force_reg (SImode, operands[1]);
8055
8056   emit_move_insn (r0, func);
8057   emit_move_insn (r1, cookie_rtx);
8058
8059   if (cookie & CALL_COOKIE_RET_TRAMP (1))
8060     emit_call_insn (gen_call_value_pop_compact_rettramp
8061                         (operands[0], operands[1], operands[2],
8062                          operands[3], operands[4]));
8063   else
8064     emit_call_insn (gen_call_value_pop_compact
8065                         (operands[0], operands[1], operands[2],
8066                          operands[3], operands[4]));
8067
8068   DONE;
8069 }")
8070
8071 (define_expand "sibcall_epilogue"
8072   [(return)]
8073   ""
8074   "
8075 {
8076   sh_expand_epilogue (1);
8077   if (TARGET_SHCOMPACT)
8078     {
8079       rtx insn, set;
8080
8081       /* If epilogue clobbers r0, preserve it in macl.  */
8082       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
8083         if ((set = single_set (insn))
8084             && GET_CODE (SET_DEST (set)) == REG
8085             && REGNO (SET_DEST (set)) == R0_REG)
8086           {
8087             rtx r0 = gen_rtx_REG (SImode, R0_REG);
8088             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
8089             rtx i;
8090
8091             /* We can't tell at this point whether the sibcall is a
8092                sibcall_compact and, if it is, whether it uses r0 or
8093                mach as operand 2, so let the instructions that
8094                preserve r0 be optimized away if r0 turns out to be
8095                dead.  */
8096             i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
8097             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
8098                                                REG_NOTES (i));
8099             i = emit_move_insn (r0, tmp);
8100             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
8101                                                REG_NOTES (i));
8102             break;
8103           }
8104     }
8105   DONE;
8106 }")
8107
8108 (define_insn "indirect_jump_compact"
8109   [(set (pc)
8110         (match_operand:SI 0 "arith_reg_operand" "r"))]
8111   "TARGET_SH1"
8112   "jmp  @%0%#"
8113   [(set_attr "needs_delay_slot" "yes")
8114    (set_attr "type" "jump_ind")])
8115
8116 (define_expand "indirect_jump"
8117   [(set (pc)
8118         (match_operand 0 "register_operand" ""))]
8119   ""
8120   "
8121 {
8122   if (GET_MODE (operands[0]) != Pmode)
8123     operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
8124 }")
8125
8126 ;; The use of operand 1 / 2 helps us distinguish case table jumps
8127 ;; which can be present in structured code from indirect jumps which can not
8128 ;; be present in structured code.  This allows -fprofile-arcs to work.
8129
8130 ;; For SH1 processors.
8131 (define_insn "casesi_jump_1"
8132   [(set (pc)
8133         (match_operand:SI 0 "register_operand" "r"))
8134    (use (label_ref (match_operand 1 "" "")))]
8135   "TARGET_SH1"
8136   "jmp  @%0%#"
8137   [(set_attr "needs_delay_slot" "yes")
8138    (set_attr "type" "jump_ind")])
8139
8140 ;; For all later processors.
8141 (define_insn "casesi_jump_2"
8142   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
8143                       (label_ref (match_operand 1 "" ""))))
8144    (use (label_ref (match_operand 2 "" "")))]
8145   "TARGET_SH2
8146    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
8147   "braf %0%#"
8148   [(set_attr "needs_delay_slot" "yes")
8149    (set_attr "type" "jump_ind")])
8150
8151 (define_insn "casesi_jump_media"
8152   [(set (pc) (match_operand 0 "target_reg_operand" "b"))
8153    (use (label_ref (match_operand 1 "" "")))]
8154   "TARGET_SHMEDIA"
8155   "blink        %0, r63"
8156   [(set_attr "type" "jump_media")])
8157
8158 ;; Call subroutine returning any type.
8159 ;; ??? This probably doesn't work.
8160
8161 (define_expand "untyped_call"
8162   [(parallel [(call (match_operand 0 "" "")
8163                     (const_int 0))
8164               (match_operand 1 "" "")
8165               (match_operand 2 "" "")])]
8166   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
8167   "
8168 {
8169   int i;
8170
8171   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
8172
8173   for (i = 0; i < XVECLEN (operands[2], 0); i++)
8174     {
8175       rtx set = XVECEXP (operands[2], 0, i);
8176       emit_move_insn (SET_DEST (set), SET_SRC (set));
8177     }
8178
8179   /* The optimizer does not know that the call sets the function value
8180      registers we stored in the result block.  We avoid problems by
8181      claiming that all hard registers are used and clobbered at this
8182      point.  */
8183   emit_insn (gen_blockage ());
8184
8185   DONE;
8186 }")
8187 \f
8188 ;; ------------------------------------------------------------------------
8189 ;; Misc insns
8190 ;; ------------------------------------------------------------------------
8191
8192 (define_insn "dect"
8193   [(set (reg:SI T_REG)
8194         (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r") (const_int 1)))
8195    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
8196   "TARGET_SH2"
8197   "dt   %0"
8198   [(set_attr "type" "arith")])
8199
8200 (define_insn "nop"
8201   [(const_int 0)]
8202   ""
8203   "nop")
8204
8205 ;; Load address of a label. This is only generated by the casesi expand,
8206 ;; and by machine_dependent_reorg (fixing up fp moves).
8207 ;; This must use unspec, because this only works for labels that are
8208 ;; within range,
8209
8210 (define_insn "mova"
8211   [(set (reg:SI R0_REG)
8212         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
8213   "TARGET_SH1"
8214   "mova %O0,r0"
8215   [(set_attr "in_delay_slot" "no")
8216    (set_attr "type" "arith")])
8217
8218 ;; machine_dependent_reorg will make this a `mova'.
8219 (define_insn "mova_const"
8220   [(set (reg:SI R0_REG)
8221         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
8222   "TARGET_SH1"
8223   "#"
8224   [(set_attr "in_delay_slot" "no")
8225    (set_attr "type" "arith")])
8226
8227 (define_expand "GOTaddr2picreg"
8228   [(set (reg:SI R0_REG)
8229         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
8230                    UNSPEC_MOVA))
8231    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
8232    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8233   "" "
8234 {
8235   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
8236   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
8237
8238   if (TARGET_SHMEDIA)
8239     {
8240       rtx tr = gen_rtx_REG (Pmode, TR0_REG);
8241       rtx pic = operands[0];
8242       rtx lab = PATTERN (gen_call_site ());
8243       rtx insn, equiv;
8244
8245       equiv = operands[1];
8246       operands[1] = gen_rtx_MINUS (Pmode,
8247                                    operands[1],
8248                                    gen_rtx_CONST
8249                                    (Pmode,
8250                                     gen_rtx_MINUS (Pmode,
8251                                                    gen_rtx_CONST (Pmode,
8252                                                                   lab),
8253                                                    pc_rtx)));
8254       operands[1] = gen_sym2PIC (operands[1]);
8255       PUT_MODE (operands[1], Pmode);
8256
8257       if (Pmode == SImode)
8258         {
8259           emit_insn (gen_movsi_const (pic, operands[1]));
8260           emit_insn (gen_ptrel_si (tr, pic, lab));
8261         }
8262       else
8263         {
8264           emit_insn (gen_movdi_const (pic, operands[1]));
8265           emit_insn (gen_ptrel_di (tr, pic, lab));
8266         }
8267
8268       insn = emit_move_insn (operands[0], tr);
8269
8270       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
8271                                             REG_NOTES (insn));
8272
8273       DONE;
8274     }
8275 }
8276 ")
8277
8278 (define_insn "*ptb"
8279   [(set (match_operand 0 "target_reg_operand" "=b")
8280         (const (unspec [(match_operand 1 "" "Csy")]
8281                              UNSPEC_DATALABEL)))]
8282   "TARGET_SHMEDIA && flag_pic
8283    && EXTRA_CONSTRAINT_Csy (operands[1])"
8284   "ptb/u        datalabel %1, %0"
8285   [(set_attr "type" "ptabs_media")
8286    (set_attr "length" "*")])
8287
8288 (define_insn "ptrel_si"
8289   [(set (match_operand:SI 0 "target_reg_operand" "=b")
8290         (plus:SI (match_operand:SI 1 "register_operand" "r")
8291               (pc)))
8292    (match_operand:SI 2 "" "")]
8293   "TARGET_SHMEDIA"
8294   "%O2: ptrel/u %1, %0"
8295   [(set_attr "type" "ptabs_media")])
8296
8297 (define_insn "ptrel_di"
8298   [(set (match_operand:DI 0 "target_reg_operand" "=b")
8299         (plus:DI (match_operand:DI 1 "register_operand" "r")
8300               (pc)))
8301    (match_operand:DI 2 "" "")]
8302   "TARGET_SHMEDIA"
8303   "%O2: ptrel/u %1, %0"
8304   [(set_attr "type" "ptabs_media")])
8305
8306 (define_expand "builtin_setjmp_receiver"
8307   [(match_operand 0 "" "")]
8308   "flag_pic"
8309   "
8310 {
8311   emit_insn (gen_GOTaddr2picreg ());
8312   DONE;
8313 }")
8314
8315 (define_expand "call_site"
8316   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
8317   "TARGET_SH1"
8318   "
8319 {
8320   static HOST_WIDE_INT i = 0;
8321   operands[0] = GEN_INT (i);
8322   i++;
8323 }")
8324
8325 (define_expand "sym_label2reg"
8326   [(set (match_operand:SI 0 "" "")
8327         (const:SI (minus:SI
8328                    (const:SI
8329                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
8330                    (const:SI
8331                     (plus:SI
8332                      (match_operand:SI 2 "" "")
8333                      (const_int 2))))))]
8334   "TARGET_SH1" "")
8335
8336 (define_expand "symGOT_load"
8337   [(set (match_dup 2) (match_operand 1 "" ""))
8338    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
8339    (set (match_operand 0 "" "") (mem (match_dup 3)))]
8340   ""
8341   "
8342 {
8343   rtx insn, mem;
8344
8345   operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
8346   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
8347
8348   if (TARGET_SHMEDIA)
8349     {
8350       rtx reg = operands[2];
8351
8352       if (Pmode == DImode)
8353         {      
8354           if (flag_pic > 1)
8355             emit_insn (gen_movdi_const_32bit (reg, operands[1]));
8356           else
8357             emit_insn (gen_movdi_const_16bit (reg, operands[1]));
8358         }
8359       else
8360         {
8361           if (flag_pic > 1)
8362             emit_insn (gen_movsi_const (reg, operands[1]));
8363           else
8364             emit_insn (gen_movsi_const_16bit (reg, operands[1]));
8365         }
8366     }
8367   else
8368     emit_move_insn (operands[2], operands[1]);
8369
8370   emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
8371                                              operands[2],
8372                                              gen_rtx_REG (Pmode, PIC_REG)));
8373
8374   /* N.B. This is not constant for a GOTPLT relocation.  */
8375   mem = gen_rtx_MEM (Pmode, operands[3]);
8376   MEM_NOTRAP_P (mem) = 1;
8377   /* ??? Should we have a special alias set for the GOT?  */
8378   insn = emit_move_insn (operands[0], mem);
8379
8380   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, XVECEXP (XEXP (operands[1],
8381                                                                   0), 0, 0),
8382                                         REG_NOTES (insn));
8383
8384   DONE;
8385 }")
8386
8387 (define_expand "sym2GOT"
8388   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
8389   ""
8390   "")
8391
8392 (define_expand "symGOT2reg"
8393   [(match_operand 0 "" "") (match_operand 1 "" "")]
8394   ""
8395   "
8396 {
8397   rtx gotsym, insn;
8398
8399   gotsym = gen_sym2GOT (operands[1]);
8400   PUT_MODE (gotsym, Pmode);
8401   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
8402
8403   MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
8404
8405   DONE;
8406 }")
8407
8408 (define_expand "symGOTPLT2reg"
8409   [(match_operand 0 "" "") (match_operand 1 "" "")]
8410   ""
8411   "
8412 {
8413   rtx pltsym = gen_rtx_CONST (Pmode,
8414                               gen_rtx_UNSPEC (Pmode,
8415                                               gen_rtvec (1, operands[1]),
8416                                               UNSPEC_GOTPLT));
8417   emit_insn (gen_symGOT_load (operands[0], pltsym));
8418   DONE;
8419 }")
8420
8421 (define_expand "sym2GOTOFF"
8422   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
8423   ""
8424   "")
8425
8426 (define_expand "symGOTOFF2reg"
8427   [(match_operand 0 "" "") (match_operand 1 "" "")]
8428   ""
8429   "
8430 {
8431   rtx gotoffsym, insn;
8432   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
8433
8434   gotoffsym = gen_sym2GOTOFF (operands[1]);
8435   PUT_MODE (gotoffsym, Pmode);
8436   emit_move_insn (t, gotoffsym);
8437   insn = emit_move_insn (operands[0],
8438                          gen_rtx_PLUS (Pmode, t,
8439                                        gen_rtx_REG (Pmode, PIC_REG)));
8440
8441   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
8442                                         REG_NOTES (insn));
8443
8444   DONE;
8445 }")
8446
8447 (define_expand "symPLT_label2reg"
8448   [(set (match_operand:SI 0 "" "")
8449         (const:SI (minus:SI
8450                    (const:SI
8451                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
8452                    (const:SI
8453                     (minus:SI
8454                      (const:SI (plus:SI
8455                                 (match_operand:SI 2 "" "")
8456                                 (const_int 2)))
8457                      (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
8458    ;; Even though the PIC register is not really used by the call
8459    ;; sequence in which this is expanded, the PLT code assumes the PIC
8460    ;; register is set, so we must not skip its initialization.  Since
8461    ;; we only use this expand as part of calling sequences, and never
8462    ;; to take the address of a function, this is the best point to
8463    ;; insert the (use).  Using the PLT to take the address of a
8464    ;; function would be wrong, not only because the PLT entry could
8465    ;; then be called from a function that doesn't initialize the PIC
8466    ;; register to the proper GOT, but also because pointers to the
8467    ;; same function might not compare equal, should they be set by
8468    ;; different shared libraries.
8469    (use (reg:SI PIC_REG))]
8470   "TARGET_SH1"
8471   "")
8472
8473 (define_expand "sym2PIC"
8474   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
8475   ""
8476   "")
8477
8478 ;; TLS code generation.
8479 ;; ??? this should be a define_insn_and_split
8480 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
8481 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
8482 ;; for details.
8483
8484 (define_insn "tls_global_dynamic"
8485   [(set (match_operand:SI 0 "register_operand" "=&z")
8486         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8487                                   UNSPEC_TLSGD))
8488               (const_int 0)))
8489    (use (reg:PSI FPSCR_REG))
8490    (use (reg:SI PIC_REG))
8491    (clobber (reg:SI PR_REG))
8492    (clobber (scratch:SI))]
8493   "TARGET_SH1"
8494   "*
8495 {
8496   return \"\\
8497 mov.l\\t1f,r4\\n\\
8498 \\tmova\\t2f,r0\\n\\
8499 \\tmov.l\\t2f,r1\\n\\
8500 \\tadd\\tr0,r1\\n\\
8501 \\tjsr\\t@r1\\n\\
8502 \\tadd\\tr12,r4\\n\\
8503 \\tbra\\t3f\\n\\
8504 \\tnop\\n\\
8505 \\t.align\\t2\\n\\
8506 1:\\t.long\\t%a1@TLSGD\\n\\
8507 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8508 3:\";
8509 }"
8510   [(set_attr "type" "tls_load")
8511    (set_attr "length" "26")])
8512
8513 (define_insn "tls_local_dynamic"
8514   [(set (match_operand:SI 0 "register_operand" "=&z")
8515         (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8516                                   UNSPEC_TLSLDM))
8517               (const_int 0)))
8518    (use (reg:PSI FPSCR_REG))
8519    (use (reg:SI PIC_REG))
8520    (clobber (reg:SI PR_REG))
8521    (clobber (scratch:SI))]
8522   "TARGET_SH1"
8523   "*
8524 {
8525   return \"\\
8526 mov.l\\t1f,r4\\n\\
8527 \\tmova\\t2f,r0\\n\\
8528 \\tmov.l\\t2f,r1\\n\\
8529 \\tadd\\tr0,r1\\n\\
8530 \\tjsr\\t@r1\\n\\
8531 \\tadd\\tr12,r4\\n\\
8532 \\tbra\\t3f\\n\\
8533 \\tnop\\n\\
8534 \\t.align\\t2\\n\\
8535 1:\\t.long\\t%a1@TLSLDM\\n\\
8536 2:\\t.long\\t__tls_get_addr@PLT\\n\\
8537 3:\";
8538 }"
8539   [(set_attr "type" "tls_load")
8540    (set_attr "length" "26")])
8541
8542 (define_expand "sym2DTPOFF"
8543   [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
8544   ""
8545   "")
8546
8547 (define_expand "symDTPOFF2reg"
8548   [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
8549   ""
8550   "
8551 {
8552   rtx dtpoffsym, insn;
8553   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
8554
8555   dtpoffsym = gen_sym2DTPOFF (operands[1]);
8556   PUT_MODE (dtpoffsym, Pmode);
8557   emit_move_insn (t, dtpoffsym);
8558   insn = emit_move_insn (operands[0],
8559                          gen_rtx_PLUS (Pmode, t, operands[2]));
8560   DONE;
8561 }")
8562
8563 (define_expand "sym2GOTTPOFF"
8564   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
8565   ""
8566   "")
8567
8568 (define_insn "tls_initial_exec"
8569   [(set (match_operand:SI 0 "register_operand" "=&r")
8570         (unspec:SI [(match_operand:SI 1 "" "")]
8571                     UNSPEC_TLSIE))
8572    (use (reg:SI GBR_REG))
8573    (use (reg:SI PIC_REG))
8574    (clobber (reg:SI R0_REG))]
8575   ""
8576   "*
8577 {
8578   return \"\\
8579 mov.l\\t1f,r0\\n\\
8580 \\tstc\\tgbr,%0\\n\\
8581 \\tmov.l\\t@(r0,r12),r0\\n\\
8582 \\tbra\\t2f\\n\\
8583 \\tadd\\tr0,%0\\n\\
8584 \\t.align\\t2\\n\\
8585 1:\\t.long\\t%a1\\n\\
8586 2:\";
8587 }"
8588   [(set_attr "type" "tls_load")
8589    (set_attr "length" "16")])
8590
8591 (define_expand "sym2TPOFF"
8592   [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
8593   ""
8594   "")
8595
8596 (define_expand "symTPOFF2reg"
8597   [(match_operand 0 "" "") (match_operand 1 "" "")]
8598   ""
8599   "
8600 {
8601   rtx tpoffsym, insn;
8602
8603   tpoffsym = gen_sym2TPOFF (operands[1]);
8604   PUT_MODE (tpoffsym, Pmode);
8605   insn = emit_move_insn (operands[0], tpoffsym);
8606   DONE;
8607 }")
8608
8609 (define_insn "load_gbr"
8610   [(set (match_operand:SI 0 "register_operand" "") (reg:SI GBR_REG))
8611    (use (reg:SI GBR_REG))]
8612   ""
8613   "stc  gbr,%0"
8614   [(set_attr "type" "tls_load")])
8615
8616 ;; case instruction for switch statements.
8617
8618 ;; Operand 0 is index
8619 ;; operand 1 is the minimum bound
8620 ;; operand 2 is the maximum bound - minimum bound + 1
8621 ;; operand 3 is CODE_LABEL for the table;
8622 ;; operand 4 is the CODE_LABEL to go to if index out of range.
8623
8624 (define_expand "casesi"
8625   [(match_operand:SI 0 "arith_reg_operand" "")
8626    (match_operand:SI 1 "arith_reg_operand" "")
8627    (match_operand:SI 2 "arith_reg_operand" "")
8628    (match_operand 3 "" "") (match_operand 4 "" "")]
8629   ""
8630   "
8631 {
8632   rtx reg = gen_reg_rtx (SImode);
8633   rtx reg2 = gen_reg_rtx (SImode);
8634   if (TARGET_SHMEDIA)
8635     {
8636       rtx reg = gen_reg_rtx (DImode);
8637       rtx reg2 = gen_reg_rtx (DImode);
8638       rtx reg3 = gen_reg_rtx (Pmode);
8639       rtx reg4 = gen_reg_rtx (Pmode);
8640       rtx reg5 = gen_reg_rtx (Pmode);
8641       rtx load;
8642
8643       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
8644       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
8645       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
8646
8647       emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
8648       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
8649       emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
8650       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
8651       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
8652                                                (Pmode, operands[3])));
8653       /* Messy: can we subreg to clean this up? */
8654       if (Pmode == DImode)
8655         load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
8656       else
8657         load = gen_casesi_load_media (reg4,
8658                                       gen_rtx_SUBREG (DImode, reg3, 0),
8659                                       reg2, operands[3]);
8660       PUT_MODE (SET_SRC (load), Pmode);
8661       emit_insn (load);
8662       /* ??? The following add could be eliminated if we used ptrel.  */
8663       emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
8664       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
8665       emit_barrier ();
8666       DONE;
8667     }
8668   operands[1] = copy_to_mode_reg (SImode, operands[1]);
8669   operands[2] = copy_to_mode_reg (SImode, operands[2]);
8670   /* If optimizing, casesi_worker depends on the mode of the instruction
8671      before label it 'uses' - operands[3].  */
8672   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
8673                            reg));
8674   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
8675   if (TARGET_SH2)
8676     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
8677   else
8678     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
8679   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
8680      operands[3], but to lab.  We will fix this up in
8681      machine_dependent_reorg.  */
8682   emit_barrier ();
8683   DONE;
8684 }")
8685
8686 (define_expand "casesi_0"
8687   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
8688    (set (match_dup 4) (minus:SI (match_dup 4)
8689                                 (match_operand:SI 1 "arith_operand" "")))
8690    (set (reg:SI T_REG)
8691         (gtu:SI (match_dup 4)
8692                 (match_operand:SI 2 "arith_reg_operand" "")))
8693    (set (pc)
8694         (if_then_else (ne (reg:SI T_REG)
8695                           (const_int 0))
8696                       (label_ref (match_operand 3 "" ""))
8697                       (pc)))]
8698   "TARGET_SH1"
8699   "")
8700
8701 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
8702 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
8703 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
8704
8705 (define_insn "casesi_worker_0"
8706   [(set (match_operand:SI 0 "register_operand" "=r,r")
8707         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
8708                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8709    (clobber (match_scratch:SI 3 "=X,1"))
8710    (clobber (match_scratch:SI 4 "=&z,z"))]
8711   "TARGET_SH1"
8712   "#")
8713
8714 (define_split
8715   [(set (match_operand:SI 0 "register_operand" "")
8716         (unspec:SI [(match_operand:SI 1 "register_operand" "")
8717                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8718    (clobber (match_scratch:SI 3 ""))
8719    (clobber (match_scratch:SI 4 ""))]
8720   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
8721   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8722    (parallel [(set (match_dup 0)
8723               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8724                           (label_ref (match_dup 2))] UNSPEC_CASESI))
8725               (clobber (match_dup 3))])
8726    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8727   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8728
8729 (define_split
8730   [(set (match_operand:SI 0 "register_operand" "")
8731         (unspec:SI [(match_operand:SI 1 "register_operand" "")
8732                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8733    (clobber (match_scratch:SI 3 ""))
8734    (clobber (match_scratch:SI 4 ""))]
8735   "TARGET_SH2 && reload_completed"
8736   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8737    (parallel [(set (match_dup 0)
8738               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8739                           (label_ref (match_dup 2))] UNSPEC_CASESI))
8740               (clobber (match_dup 3))])]
8741   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8742
8743 (define_insn "casesi_worker_1"
8744   [(set (match_operand:SI 0 "register_operand" "=r,r")
8745         (unspec:SI [(reg:SI R0_REG)
8746                     (match_operand:SI 1 "register_operand" "0,r")
8747                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8748    (clobber (match_scratch:SI 3 "=X,1"))]
8749   "TARGET_SH1"
8750   "*
8751 {
8752   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8753
8754   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8755
8756   switch (GET_MODE (diff_vec))
8757     {
8758     case SImode:
8759       return \"shll2    %1\;mov.l       @(r0,%1),%0\";
8760     case HImode:
8761       return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
8762     case QImode:
8763       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8764         return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
8765       return \"mov.b    @(r0,%1),%0\";
8766     default:
8767       gcc_unreachable ();
8768     }
8769 }"
8770   [(set_attr "length" "4")])
8771
8772 (define_insn "casesi_worker_2"
8773   [(set (match_operand:SI 0 "register_operand" "=r,r")
8774         (unspec:SI [(reg:SI R0_REG)
8775                     (match_operand:SI 1 "register_operand" "0,r")
8776                     (label_ref (match_operand 2 "" ""))
8777                     (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
8778    (clobber (match_operand:SI 4 "" "=X,1"))]
8779   "TARGET_SH2 && reload_completed && flag_pic"
8780   "*
8781 {
8782   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8783   const char *load;
8784
8785   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8786
8787   switch (GET_MODE (diff_vec))
8788     {
8789     case SImode:
8790       output_asm_insn (\"shll2    %1\", operands);
8791       load = \"mov.l    @(r0,%1),%0\"; break;
8792     case HImode:
8793       output_asm_insn (\"add    %1,%1\", operands);
8794       load = \"mov.w    @(r0,%1),%0\"; break;
8795     case QImode:
8796       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8797         load = \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
8798       else
8799         load = \"mov.b  @(r0,%1),%0\";
8800       break;
8801     default:
8802       gcc_unreachable ();
8803     }
8804   output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
8805   return load;
8806 }"
8807   [(set_attr "length" "8")])
8808
8809 (define_insn "casesi_shift_media"
8810   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
8811         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
8812                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
8813                     UNSPEC_CASESI)))]
8814   "TARGET_SHMEDIA"
8815   "*
8816 {
8817   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8818
8819   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8820
8821   switch (GET_MODE (diff_vec))
8822     {
8823     case SImode:
8824       return \"shlli    %1, 2, %0\";
8825     case HImode:
8826       return \"shlli    %1, 1, %0\";
8827     case QImode:
8828       if (rtx_equal_p (operands[0], operands[1]))
8829         return \"\";
8830       return \"add      %1, r63, %0\";
8831     default:
8832       gcc_unreachable ();
8833     }
8834 }"
8835   [(set_attr "type" "arith_media")])
8836
8837 (define_insn "casesi_load_media"
8838   [(set (match_operand 0 "any_arith_reg_dest" "=r")
8839         (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
8840                          (match_operand:DI 2 "arith_reg_operand" "r")
8841                          (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
8842   "TARGET_SHMEDIA"
8843   "*
8844 {
8845   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
8846
8847   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8848
8849   switch (GET_MODE (diff_vec))
8850     {
8851     case SImode:
8852       return \"ldx.l    %1, %2, %0\";
8853     case HImode:
8854 #if 0
8855       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8856         return \"ldx.uw %1, %2, %0\";
8857 #endif
8858       return \"ldx.w    %1, %2, %0\";
8859     case QImode:
8860       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8861         return \"ldx.ub %1, %2, %0\";
8862       return \"ldx.b    %1, %2, %0\";
8863     default:
8864       gcc_unreachable ();
8865     }
8866 }"
8867   [(set_attr "type" "load_media")])
8868
8869 (define_expand "return"
8870   [(return)]
8871   "reload_completed && ! sh_need_epilogue ()"
8872   "
8873 {
8874   if (TARGET_SHMEDIA)
8875     {
8876       emit_jump_insn (gen_return_media ());
8877       DONE;
8878     }
8879
8880   if (TARGET_SHCOMPACT
8881       && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
8882     {
8883       emit_jump_insn (gen_shcompact_return_tramp ());
8884       DONE;
8885     }
8886 }")
8887
8888 (define_insn "*return_i"
8889   [(return)]
8890   "TARGET_SH1 && ! (TARGET_SHCOMPACT
8891                     && (current_function_args_info.call_cookie
8892                         & CALL_COOKIE_RET_TRAMP (1)))
8893    && reload_completed
8894    && lookup_attribute (\"trap_exit\",
8895                         DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
8896   "%@   %#"
8897   [(set_attr "type" "return")
8898    (set_attr "needs_delay_slot" "yes")])
8899
8900 ;; trapa has no delay slot.
8901 (define_insn "*return_trapa"
8902   [(return)]
8903   "TARGET_SH1 && !TARGET_SHCOMPACT
8904    && reload_completed"
8905   "%@"
8906   [(set_attr "type" "return")])
8907
8908 (define_expand "shcompact_return_tramp"
8909   [(return)]
8910   "TARGET_SHCOMPACT
8911    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
8912   "
8913 {
8914   rtx reg = gen_rtx_REG (Pmode, R0_REG);
8915
8916   function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC);
8917   emit_jump_insn (gen_shcompact_return_tramp_i ());
8918   DONE;
8919 }")
8920
8921 (define_insn "shcompact_return_tramp_i"
8922   [(parallel [(return) (use (reg:SI R0_REG))])]
8923   "TARGET_SHCOMPACT
8924    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
8925   "jmp  @r0%#"
8926   [(set_attr "type" "jump_ind")
8927    (set_attr "needs_delay_slot" "yes")])
8928
8929 (define_insn "return_media_i"
8930   [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
8931   "TARGET_SHMEDIA && reload_completed"
8932   "blink        %0, r63"
8933   [(set_attr "type" "jump_media")])
8934
8935 (define_insn "return_media_rte"
8936   [(return)]
8937   "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
8938   "rte"
8939   [(set_attr "type" "jump_media")])
8940
8941 (define_expand "return_media"
8942   [(return)]
8943   "TARGET_SHMEDIA && reload_completed"
8944   "
8945 {
8946   int tr_regno = sh_media_register_for_return ();
8947   rtx tr;
8948
8949   if (current_function_interrupt)
8950     {
8951       emit_jump_insn (gen_return_media_rte ());
8952       DONE;
8953     }
8954   if (tr_regno < 0)
8955     {
8956       rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
8957
8958       gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
8959       tr_regno = TR0_REG;
8960       tr = gen_rtx_REG (Pmode, tr_regno);
8961       emit_move_insn (tr, r18);
8962     }
8963   else
8964     tr = gen_rtx_REG (Pmode, tr_regno);
8965
8966   emit_jump_insn (gen_return_media_i (tr));
8967   DONE;
8968 }")
8969
8970 (define_insn "shcompact_preserve_incoming_args"
8971   [(set (match_operand:SI 0 "register_operand" "+r")
8972         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
8973   "TARGET_SHCOMPACT"
8974   ""
8975   [(set_attr "length" "0")])
8976
8977 (define_insn "shcompact_incoming_args"
8978   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
8979    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
8980    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
8981    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
8982    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
8983    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
8984    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
8985    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
8986    (set (mem:BLK (reg:SI MACL_REG))
8987         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
8988    (use (reg:SI R0_REG))
8989    (clobber (reg:SI R0_REG))
8990    (clobber (reg:SI MACL_REG))
8991    (clobber (reg:SI MACH_REG))
8992    (clobber (reg:SI PR_REG))]
8993   "TARGET_SHCOMPACT"
8994   "jsr  @r0%#"
8995   [(set_attr "needs_delay_slot" "yes")])
8996
8997 (define_insn "shmedia_save_restore_regs_compact"
8998   [(set (reg:SI SP_REG)
8999         (plus:SI (reg:SI SP_REG)
9000                  (match_operand:SI 0 "immediate_operand" "i")))
9001    (use (reg:SI R0_REG))
9002    (clobber (reg:SI PR_REG))]
9003   "TARGET_SHCOMPACT
9004    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
9005        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
9006   "jsr @r0%#"
9007   [(set_attr "needs_delay_slot" "yes")])
9008
9009 (define_expand "prologue"
9010   [(const_int 0)]
9011   ""
9012   "sh_expand_prologue (); DONE;")
9013
9014 (define_expand "epilogue"
9015   [(return)]
9016   ""
9017   "
9018 {
9019   sh_expand_epilogue (0);
9020   emit_jump_insn (gen_return ());
9021   DONE;
9022 }")
9023
9024 (define_expand "eh_return"
9025   [(use (match_operand 0 "register_operand" ""))]
9026   ""
9027 {
9028   rtx ra = operands[0];
9029
9030   if (TARGET_SHMEDIA64)
9031     emit_insn (gen_eh_set_ra_di (ra));
9032   else
9033     emit_insn (gen_eh_set_ra_si (ra));
9034
9035   DONE;
9036 })
9037
9038 ;; Clobber the return address on the stack.  We can't expand this
9039 ;; until we know where it will be put in the stack frame.
9040
9041 (define_insn "eh_set_ra_si"
9042   [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
9043    (clobber (match_scratch:SI 1 "=&r"))]
9044   "! TARGET_SHMEDIA64"
9045   "#")
9046
9047 (define_insn "eh_set_ra_di"
9048   [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
9049    (clobber (match_scratch:DI 1 "=&r"))]
9050   "TARGET_SHMEDIA64"
9051   "#")
9052
9053 (define_split
9054   [(unspec [(match_operand 0 "register_operand" "")] UNSPEC_EH_RETURN)
9055    (clobber (match_scratch 1 ""))]
9056   "reload_completed"
9057   [(const_int 0)]
9058   "
9059 {
9060   sh_set_return_address (operands[0], operands[1]);
9061   DONE;
9062 }")
9063
9064 (define_insn "blockage"
9065   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
9066   ""
9067   ""
9068   [(set_attr "length" "0")])
9069 \f
9070 ;; ------------------------------------------------------------------------
9071 ;; Scc instructions
9072 ;; ------------------------------------------------------------------------
9073
9074 (define_insn "movt"
9075   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9076         (eq:SI (reg:SI T_REG) (const_int 1)))]
9077   "TARGET_SH1"
9078   "movt %0"
9079   [(set_attr "type" "arith")])
9080
9081 (define_expand "seq"
9082   [(set (match_operand:SI 0 "arith_reg_dest" "")
9083         (match_dup 1))]
9084   ""
9085   "
9086 {
9087   if (TARGET_SHMEDIA)
9088     {
9089       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9090       if (sh_compare_op1 != const0_rtx)
9091         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9092                                     ? GET_MODE (sh_compare_op0)
9093                                     : GET_MODE (sh_compare_op1),
9094                                     sh_compare_op1);
9095       if (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4)
9096         {
9097           if (GET_MODE (operands[0]) != SImode)
9098             operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
9099
9100           switch (GET_MODE (sh_compare_op0))
9101             {
9102             case SImode:
9103               emit_insn (gen_cmpsieqsi_media (operands[0],
9104                                               sh_compare_op0, sh_compare_op1));
9105               break;
9106
9107             case DImode:
9108               emit_insn (gen_cmpsieqdi_media (operands[0],
9109                                               sh_compare_op0, sh_compare_op1));
9110               break;
9111
9112             case SFmode:
9113               if (! TARGET_SHMEDIA_FPU)
9114                 FAIL;
9115               emit_insn (gen_cmpsieqsf_media (operands[0],
9116                                               sh_compare_op0, sh_compare_op1));
9117               break;
9118
9119             case DFmode:
9120               if (! TARGET_SHMEDIA_FPU)
9121                 FAIL;
9122               emit_insn (gen_cmpsieqdf_media (operands[0],
9123                                               sh_compare_op0, sh_compare_op1));
9124               break;
9125
9126             default:
9127               FAIL;
9128             }
9129           DONE;
9130         }
9131
9132       if (GET_MODE (operands[0]) != DImode)
9133         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9134
9135       switch (GET_MODE (sh_compare_op0))
9136         {
9137         case SImode:
9138           emit_insn (gen_cmpeqsi_media (operands[0],
9139                                         sh_compare_op0, sh_compare_op1));
9140           break;
9141
9142         case DImode:
9143           emit_insn (gen_cmpeqdi_media (operands[0],
9144                                         sh_compare_op0, sh_compare_op1));
9145           break;
9146
9147         case SFmode:
9148           if (! TARGET_SHMEDIA_FPU)
9149             FAIL;
9150           emit_insn (gen_cmpeqsf_media (operands[0],
9151                                         sh_compare_op0, sh_compare_op1));
9152           break;
9153
9154         case DFmode:
9155           if (! TARGET_SHMEDIA_FPU)
9156             FAIL;
9157           emit_insn (gen_cmpeqdf_media (operands[0],
9158                                         sh_compare_op0, sh_compare_op1));
9159           break;
9160
9161         default:
9162           FAIL;
9163         }
9164       DONE;
9165     }
9166   if (sh_expand_t_scc (EQ, operands[0]))
9167     DONE;
9168   if (! currently_expanding_to_rtl)
9169     FAIL;
9170   operands[1] = prepare_scc_operands (EQ);
9171 }")
9172
9173 (define_expand "slt"
9174   [(set (match_operand:SI 0 "arith_reg_operand" "")
9175         (match_dup 1))]
9176   ""
9177   "
9178 {
9179   if (TARGET_SHMEDIA)
9180     {
9181       if (GET_MODE (operands[0]) != DImode)
9182         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9183       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9184       if (sh_compare_op1 != const0_rtx)
9185         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9186                                     ? GET_MODE (sh_compare_op0)
9187                                     : GET_MODE (sh_compare_op1),
9188                                     sh_compare_op1);
9189
9190       switch (GET_MODE (sh_compare_op0))
9191         {
9192         case SImode:
9193           emit_insn (gen_cmpgtsi_media (operands[0],
9194                                         sh_compare_op1, sh_compare_op0));
9195           break;
9196
9197         case DImode:
9198           emit_insn (gen_cmpgtdi_media (operands[0],
9199                                         sh_compare_op1, sh_compare_op0));
9200           break;
9201
9202         case SFmode:
9203           if (! TARGET_SHMEDIA_FPU)
9204             FAIL;
9205           emit_insn (gen_cmpgtsf_media (operands[0],
9206                                         sh_compare_op1, sh_compare_op0));
9207           break;
9208
9209         case DFmode:
9210           if (! TARGET_SHMEDIA_FPU)
9211             FAIL;
9212           emit_insn (gen_cmpgtdf_media (operands[0],
9213                                         sh_compare_op1, sh_compare_op0));
9214           break;
9215
9216         default:
9217           FAIL;
9218         }
9219       DONE;
9220     }
9221   if (! currently_expanding_to_rtl)
9222     FAIL;
9223   operands[1] = prepare_scc_operands (LT);
9224 }")
9225
9226 (define_expand "sle"
9227   [(match_operand:SI 0 "arith_reg_operand" "")]
9228   ""
9229   "
9230 {
9231   rtx tmp = sh_compare_op0;
9232
9233   if (TARGET_SHMEDIA)
9234     {
9235       if (GET_MODE (operands[0]) != DImode)
9236         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9237       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9238       if (sh_compare_op1 != const0_rtx)
9239         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9240                                     ? GET_MODE (sh_compare_op0)
9241                                     : GET_MODE (sh_compare_op1),
9242                                     sh_compare_op1);
9243
9244       switch (GET_MODE (sh_compare_op0))
9245         {
9246         case SImode:
9247           {
9248             tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
9249
9250             emit_insn (gen_cmpgtsi_media (tmp,
9251                                           sh_compare_op0, sh_compare_op1));
9252             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
9253             break;
9254           }
9255
9256         case DImode:
9257           {
9258             tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
9259
9260             emit_insn (gen_cmpgtdi_media (tmp,
9261                                           sh_compare_op0, sh_compare_op1));
9262             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
9263             break;
9264           }
9265
9266         case SFmode:
9267           if (! TARGET_SHMEDIA_FPU)
9268             FAIL;
9269           emit_insn (gen_cmpgesf_media (operands[0],
9270                                         sh_compare_op1, sh_compare_op0));
9271           break;
9272
9273         case DFmode:
9274           if (! TARGET_SHMEDIA_FPU)
9275             FAIL;
9276           emit_insn (gen_cmpgedf_media (operands[0],
9277                                         sh_compare_op1, sh_compare_op0));
9278           break;
9279
9280         default:
9281           FAIL;
9282         }
9283       DONE;
9284     }
9285
9286   sh_compare_op0 = sh_compare_op1;
9287   sh_compare_op1 = tmp;
9288   emit_insn (gen_sge (operands[0]));
9289   DONE;
9290 }")
9291
9292 (define_expand "sgt"
9293   [(set (match_operand:SI 0 "arith_reg_operand" "")
9294         (match_dup 1))]
9295   ""
9296   "
9297 {
9298   if (TARGET_SHMEDIA)
9299     {
9300       if (GET_MODE (operands[0]) != DImode)
9301         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9302       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9303       if (sh_compare_op1 != const0_rtx)
9304         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9305                                     ? GET_MODE (sh_compare_op0)
9306                                     : GET_MODE (sh_compare_op1),
9307                                     sh_compare_op1);
9308
9309       switch (GET_MODE (sh_compare_op0))
9310         {
9311         case SImode:
9312           emit_insn (gen_cmpgtsi_media (operands[0],
9313                                         sh_compare_op0, sh_compare_op1));
9314           break;
9315
9316         case DImode:
9317           emit_insn (gen_cmpgtdi_media (operands[0],
9318                                         sh_compare_op0, sh_compare_op1));
9319           break;
9320
9321         case SFmode:
9322           if (! TARGET_SHMEDIA_FPU)
9323             FAIL;
9324           emit_insn (gen_cmpgtsf_media (operands[0],
9325                                         sh_compare_op0, sh_compare_op1));
9326           break;
9327
9328         case DFmode:
9329           if (! TARGET_SHMEDIA_FPU)
9330             FAIL;
9331           emit_insn (gen_cmpgtdf_media (operands[0],
9332                                         sh_compare_op0, sh_compare_op1));
9333           break;
9334
9335         default:
9336           FAIL;
9337         }
9338       DONE;
9339     }
9340   if (! currently_expanding_to_rtl)
9341     FAIL;
9342   operands[1] = prepare_scc_operands (GT);
9343 }")
9344
9345 (define_expand "sge"
9346   [(set (match_operand:SI 0 "arith_reg_operand" "")
9347         (match_dup 1))]
9348   ""
9349   "
9350 {
9351   if (TARGET_SHMEDIA)
9352     {
9353       enum machine_mode mode = GET_MODE (sh_compare_op0);
9354
9355       if ((mode) == VOIDmode)
9356         mode = GET_MODE (sh_compare_op1);
9357       if (GET_MODE (operands[0]) != DImode)
9358         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9359       sh_compare_op0 = force_reg (mode, sh_compare_op0);
9360       if (sh_compare_op1 != const0_rtx)
9361         sh_compare_op1 = force_reg (mode, sh_compare_op1);
9362
9363       switch (mode)
9364         {
9365         case SImode:
9366           {
9367             rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
9368
9369             emit_insn (gen_cmpgtsi_media (tmp,
9370                                           sh_compare_op1, sh_compare_op0));
9371             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
9372             break;
9373           }
9374
9375         case DImode:
9376           {
9377             rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
9378
9379             emit_insn (gen_cmpgtdi_media (tmp,
9380                                           sh_compare_op1, sh_compare_op0));
9381             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
9382             break;
9383           }
9384
9385         case SFmode:
9386           if (! TARGET_SHMEDIA_FPU)
9387             FAIL;
9388           emit_insn (gen_cmpgesf_media (operands[0],
9389                                         sh_compare_op0, sh_compare_op1));
9390           break;
9391
9392         case DFmode:
9393           if (! TARGET_SHMEDIA_FPU)
9394             FAIL;
9395           emit_insn (gen_cmpgedf_media (operands[0],
9396                                         sh_compare_op0, sh_compare_op1));
9397           break;
9398
9399         default:
9400           FAIL;
9401         }
9402       DONE;
9403     }
9404
9405   if (! currently_expanding_to_rtl)
9406     FAIL;
9407   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
9408     {
9409       if (TARGET_IEEE)
9410         {
9411           rtx lab = gen_label_rtx ();
9412           prepare_scc_operands (EQ);
9413           emit_jump_insn (gen_branch_true (lab));
9414           prepare_scc_operands (GT);
9415           emit_label (lab);
9416           emit_insn (gen_movt (operands[0]));
9417         }
9418       else
9419         emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
9420       DONE;
9421     }
9422   operands[1] = prepare_scc_operands (GE);
9423 }")
9424
9425 (define_expand "sgtu"
9426   [(set (match_operand:SI 0 "arith_reg_operand" "")
9427         (match_dup 1))]
9428   ""
9429   "
9430 {
9431   if (TARGET_SHMEDIA)
9432     {
9433       if (GET_MODE (operands[0]) != DImode)
9434         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9435       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9436       if (sh_compare_op1 != const0_rtx)
9437         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9438                                     ? GET_MODE (sh_compare_op0)
9439                                     : GET_MODE (sh_compare_op1),
9440                                     sh_compare_op1);
9441
9442       emit_insn (gen_cmpgtudi_media (operands[0],
9443                                      sh_compare_op0, sh_compare_op1));
9444       DONE;
9445     }
9446   if (! currently_expanding_to_rtl)
9447     FAIL;
9448   operands[1] = prepare_scc_operands (GTU);
9449 }")
9450
9451 (define_expand "sltu"
9452   [(set (match_operand:SI 0 "arith_reg_operand" "")
9453         (match_dup 1))]
9454   ""
9455   "
9456 {
9457   if (TARGET_SHMEDIA)
9458     {
9459       if (GET_MODE (operands[0]) != DImode)
9460         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9461       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9462       if (sh_compare_op1 != const0_rtx)
9463         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9464                                     ? GET_MODE (sh_compare_op0)
9465                                     : GET_MODE (sh_compare_op1),
9466                                     sh_compare_op1);
9467
9468       emit_insn (gen_cmpgtudi_media (operands[0],
9469                                      sh_compare_op1, sh_compare_op0));
9470       DONE;
9471     }
9472   if (! currently_expanding_to_rtl)
9473     FAIL;
9474   operands[1] = prepare_scc_operands (LTU);
9475 }")
9476
9477 (define_expand "sleu"
9478   [(set (match_operand:SI 0 "arith_reg_operand" "")
9479         (match_dup 1))]
9480   ""
9481   "
9482 {
9483   if (TARGET_SHMEDIA)
9484     {
9485       rtx tmp;
9486
9487       if (GET_MODE (operands[0]) != DImode)
9488         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9489       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9490       if (sh_compare_op1 != const0_rtx)
9491         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9492                                     ? GET_MODE (sh_compare_op0)
9493                                     : GET_MODE (sh_compare_op1),
9494                                     sh_compare_op1);
9495
9496       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
9497
9498       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
9499       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
9500
9501       DONE;
9502     }
9503   if (! currently_expanding_to_rtl)
9504     FAIL;
9505   operands[1] = prepare_scc_operands (LEU);
9506 }")
9507
9508 (define_expand "sgeu"
9509   [(set (match_operand:SI 0 "arith_reg_operand" "")
9510         (match_dup 1))]
9511   ""
9512   "
9513 {
9514   if (TARGET_SHMEDIA)
9515     {
9516       rtx tmp;
9517
9518       if (GET_MODE (operands[0]) != DImode)
9519         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9520       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9521       if (sh_compare_op1 != const0_rtx)
9522         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9523                                     ? GET_MODE (sh_compare_op0)
9524                                     : GET_MODE (sh_compare_op1),
9525                                     sh_compare_op1);
9526
9527       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
9528
9529       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
9530       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
9531
9532       DONE;
9533     }
9534
9535   if (! currently_expanding_to_rtl)
9536     FAIL;
9537   operands[1] = prepare_scc_operands (GEU);
9538 }")
9539
9540 ;; sne moves the complement of the T reg to DEST like this:
9541 ;;      cmp/eq ...
9542 ;;      mov    #-1,temp
9543 ;;      negc   temp,dest
9544 ;;   This is better than xoring compare result with 1 because it does
9545 ;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
9546 ;;   loop.
9547
9548 (define_expand "sne"
9549   [(set (match_dup 2) (const_int -1))
9550    (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
9551                    (neg:SI (plus:SI (match_dup 1)
9552                                     (match_dup 2))))
9553               (set (reg:SI T_REG)
9554                    (ne:SI (ior:SI (match_dup 1) (match_dup 2))
9555                           (const_int 0)))])]
9556   ""
9557   "
9558 {
9559   if (TARGET_SHMEDIA)
9560     {
9561       rtx tmp;
9562
9563       if (GET_MODE (operands[0]) != DImode)
9564         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
9565
9566       if (! TARGET_SHMEDIA_FPU
9567           && GET_MODE (sh_compare_op0) != DImode
9568           && GET_MODE (sh_compare_op0) != SImode)
9569         FAIL;
9570
9571       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9572       if (sh_compare_op1 != const0_rtx)
9573         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
9574                                     ? GET_MODE (sh_compare_op0)
9575                                     : GET_MODE (sh_compare_op1),
9576                                     sh_compare_op1);
9577
9578       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
9579
9580       emit_insn (gen_seq (tmp));
9581       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
9582
9583       DONE;
9584     }
9585
9586   if (sh_expand_t_scc (NE, operands[0]))
9587     DONE;
9588   if (! currently_expanding_to_rtl)
9589     FAIL;
9590   operands[1] = prepare_scc_operands (EQ);
9591   operands[2] = gen_reg_rtx (SImode);
9592 }")
9593
9594 (define_expand "sunordered"
9595   [(set (match_operand:DI 0 "arith_reg_operand" "")
9596         (unordered:DI (match_dup 1) (match_dup 2)))]
9597   "TARGET_SHMEDIA_FPU"
9598   "
9599 {
9600   operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
9601   operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
9602 }")
9603
9604 ;; Use the same trick for FP sle / sge
9605
9606 ;; Apart from the constant use and the T setting, this is like movt,
9607 ;; except that it uses the logically negated value of T, i.e.
9608 ;; operand[0] := T ? 0 : 1.
9609 (define_expand "movnegt"
9610   [(set (match_dup 2) (const_int -1))
9611    (parallel [(set (match_operand 0 "" "")
9612                    (neg:SI (plus:SI (match_dup 1)
9613                                     (match_dup 2))))
9614               (set (reg:SI T_REG)
9615                    (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
9616                           (const_int 0)))])]
9617   "TARGET_SH1"
9618   "operands[2] = gen_reg_rtx (SImode);")
9619
9620 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
9621 ;; This prevents a regression that occurred when we switched from xor to
9622 ;; mov/neg for sne.
9623
9624 (define_split
9625   [(set (match_operand:SI 0 "arith_reg_dest" "")
9626         (plus:SI (reg:SI T_REG)
9627                  (const_int -1)))]
9628   "TARGET_SH1"
9629   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
9630    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
9631   "")
9632
9633 ;; -------------------------------------------------------------------------
9634 ;; Instructions to cope with inline literal tables
9635 ;; -------------------------------------------------------------------------
9636
9637 ; 2 byte integer in line
9638
9639 (define_insn "consttable_2"
9640  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9641                     (match_operand 1 "" "")]
9642                    UNSPECV_CONST2)]
9643  ""
9644  "*
9645 {
9646   if (operands[1] != const0_rtx)
9647     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
9648   return \"\";
9649 }"
9650  [(set_attr "length" "2")
9651  (set_attr "in_delay_slot" "no")])
9652
9653 ; 4 byte integer in line
9654
9655 (define_insn "consttable_4"
9656  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9657                     (match_operand 1 "" "")]
9658                    UNSPECV_CONST4)]
9659  ""
9660  "*
9661 {
9662   if (operands[1] != const0_rtx)
9663     assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
9664   return \"\";
9665 }"
9666  [(set_attr "length" "4")
9667   (set_attr "in_delay_slot" "no")])
9668
9669 ; 8 byte integer in line
9670
9671 (define_insn "consttable_8"
9672  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9673                     (match_operand 1 "" "")]
9674                    UNSPECV_CONST8)]
9675  ""
9676  "*
9677 {
9678   if (operands[1] != const0_rtx)
9679     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
9680   return \"\";
9681 }"
9682  [(set_attr "length" "8")
9683   (set_attr "in_delay_slot" "no")])
9684
9685 ; 4 byte floating point
9686
9687 (define_insn "consttable_sf"
9688  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
9689                     (match_operand 1 "" "")]
9690                    UNSPECV_CONST4)]
9691  ""
9692  "*
9693 {
9694   if (operands[1] != const0_rtx)
9695     {
9696       REAL_VALUE_TYPE d;
9697       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9698       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
9699     }
9700   return \"\";
9701 }"
9702  [(set_attr "length" "4")
9703   (set_attr "in_delay_slot" "no")])
9704
9705 ; 8 byte floating point
9706
9707 (define_insn "consttable_df"
9708  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
9709                     (match_operand 1 "" "")]
9710                    UNSPECV_CONST8)]
9711  ""
9712  "*
9713 {
9714   if (operands[1] != const0_rtx)
9715     {
9716       REAL_VALUE_TYPE d;
9717       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9718       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
9719     }
9720   return \"\";
9721 }"
9722  [(set_attr "length" "8")
9723   (set_attr "in_delay_slot" "no")])
9724
9725 ;; Alignment is needed for some constant tables; it may also be added for
9726 ;; Instructions at the start of loops, or after unconditional branches.
9727 ;; ??? We would get more accurate lengths if we did instruction
9728 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
9729 ;; here is too conservative.
9730
9731 ; align to a two byte boundary
9732
9733 (define_expand "align_2"
9734  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
9735  ""
9736  "")
9737
9738 ; align to a four byte boundary
9739 ;; align_4 and align_log are instructions for the starts of loops, or
9740 ;; after unconditional branches, which may take up extra room.
9741
9742 (define_expand "align_4"
9743  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
9744  ""
9745  "")
9746
9747 ; align to a cache line boundary
9748
9749 (define_insn "align_log"
9750  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
9751  ""
9752  ""
9753  [(set_attr "length" "0")
9754   (set_attr "in_delay_slot" "no")])
9755
9756 ; emitted at the end of the literal table, used to emit the
9757 ; 32bit branch labels if needed.
9758
9759 (define_insn "consttable_end"
9760   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
9761   ""
9762   "* return output_jump_label_table ();"
9763   [(set_attr "in_delay_slot" "no")])
9764
9765 ; emitted at the end of the window in the literal table.
9766
9767 (define_insn "consttable_window_end"
9768   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
9769   ""
9770   ""
9771   [(set_attr "length" "0")
9772    (set_attr "in_delay_slot" "no")])
9773
9774 ;; -------------------------------------------------------------------------
9775 ;; Misc
9776 ;; -------------------------------------------------------------------------
9777
9778 ;; String/block move insn.
9779
9780 (define_expand "movmemsi"
9781   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
9782                    (mem:BLK (match_operand:BLK 1 "" "")))
9783               (use (match_operand:SI 2 "nonmemory_operand" ""))
9784               (use (match_operand:SI 3 "immediate_operand" ""))
9785               (clobber (reg:SI PR_REG))
9786               (clobber (reg:SI R4_REG))
9787               (clobber (reg:SI R5_REG))
9788               (clobber (reg:SI R0_REG))])]
9789   "TARGET_SH1 && ! TARGET_SH5"
9790   "
9791 {
9792   if(expand_block_move (operands))
9793      DONE;
9794   else FAIL;
9795 }")
9796
9797 (define_insn "block_move_real"
9798   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9799                    (mem:BLK (reg:SI R5_REG)))
9800               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9801               (clobber (reg:SI PR_REG))
9802               (clobber (reg:SI R0_REG))])]
9803   "TARGET_SH1 && ! TARGET_HARD_SH4"
9804   "jsr  @%0%#"
9805   [(set_attr "type" "sfunc")
9806    (set_attr "needs_delay_slot" "yes")])
9807
9808 (define_insn "block_lump_real"
9809   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9810                    (mem:BLK (reg:SI R5_REG)))
9811               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9812               (use (reg:SI R6_REG))
9813               (clobber (reg:SI PR_REG))
9814               (clobber (reg:SI T_REG))
9815               (clobber (reg:SI R4_REG))
9816               (clobber (reg:SI R5_REG))
9817               (clobber (reg:SI R6_REG))
9818               (clobber (reg:SI R0_REG))])]
9819   "TARGET_SH1 && ! TARGET_HARD_SH4"
9820   "jsr  @%0%#"
9821   [(set_attr "type" "sfunc")
9822    (set_attr "needs_delay_slot" "yes")])
9823
9824 (define_insn "block_move_real_i4"
9825   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9826                    (mem:BLK (reg:SI R5_REG)))
9827               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9828               (clobber (reg:SI PR_REG))
9829               (clobber (reg:SI R0_REG))
9830               (clobber (reg:SI R1_REG))
9831               (clobber (reg:SI R2_REG))])]
9832   "TARGET_HARD_SH4"
9833   "jsr  @%0%#"
9834   [(set_attr "type" "sfunc")
9835    (set_attr "needs_delay_slot" "yes")])
9836
9837 (define_insn "block_lump_real_i4"
9838   [(parallel [(set (mem:BLK (reg:SI R4_REG))
9839                    (mem:BLK (reg:SI R5_REG)))
9840               (use (match_operand:SI 0 "arith_reg_operand" "r"))
9841               (use (reg:SI R6_REG))
9842               (clobber (reg:SI PR_REG))
9843               (clobber (reg:SI T_REG))
9844               (clobber (reg:SI R4_REG))
9845               (clobber (reg:SI R5_REG))
9846               (clobber (reg:SI R6_REG))
9847               (clobber (reg:SI R0_REG))
9848               (clobber (reg:SI R1_REG))
9849               (clobber (reg:SI R2_REG))
9850               (clobber (reg:SI R3_REG))])]
9851   "TARGET_HARD_SH4"
9852   "jsr  @%0%#"
9853   [(set_attr "type" "sfunc")
9854    (set_attr "needs_delay_slot" "yes")])
9855 \f
9856 ;; -------------------------------------------------------------------------
9857 ;; Floating point instructions.
9858 ;; -------------------------------------------------------------------------
9859
9860 ;; ??? All patterns should have a type attribute.
9861
9862 (define_expand "movpsi"
9863   [(set (match_operand:PSI 0 "register_operand" "")
9864         (match_operand:PSI 1 "general_movsrc_operand" ""))]
9865   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9866   "")
9867
9868 ;; The c / m alternative is a fake to guide reload to load directly into
9869 ;; fpscr, since reload doesn't know how to use post-increment.
9870 ;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
9871 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
9872 ;; predicate after reload.
9873 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
9874 ;; like a mac -> gpr move.
9875 (define_insn "fpu_switch"
9876   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
9877         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
9878   "TARGET_SH2E
9879    && (! reload_completed
9880        || true_regnum (operands[0]) != FPSCR_REG
9881        || GET_CODE (operands[1]) != MEM
9882        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
9883   "@
9884         ! precision stays the same
9885         lds.l   %1,fpscr
9886         mov.l   %1,%0
9887         #
9888         lds     %1,fpscr
9889         mov     %1,%0
9890         mov.l   %1,%0
9891         sts     fpscr,%0
9892         sts.l   fpscr,%0"
9893   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
9894    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,store")])
9895
9896 (define_peephole2
9897   [(set (reg:PSI FPSCR_REG)
9898         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
9899   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
9900   [(const_int 0)]
9901 {
9902   rtx fpscr, mem, new_insn;
9903
9904   fpscr = SET_DEST (PATTERN (curr_insn));
9905   mem = SET_SRC (PATTERN (curr_insn));
9906   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9907
9908   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9909   REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
9910   DONE;
9911 })
9912
9913 (define_split
9914   [(set (reg:PSI FPSCR_REG)
9915         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
9916   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
9917    && (flag_peephole2 ? flow2_completed : reload_completed)"
9918   [(const_int 0)]
9919 {
9920   rtx fpscr, mem, new_insn;
9921
9922   fpscr = SET_DEST (PATTERN (curr_insn));
9923   mem = SET_SRC (PATTERN (curr_insn));
9924   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9925
9926   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9927   REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
9928
9929   if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
9930     emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
9931   DONE;
9932 })
9933
9934 ;; ??? This uses the fp unit, but has no type indicating that.
9935 ;; If we did that, this would either give a bogus latency or introduce
9936 ;; a bogus FIFO constraint.
9937 ;; Since this insn is currently only used for prologues/epilogues,
9938 ;; it is probably best to claim no function unit, which matches the
9939 ;; current setting.
9940 (define_insn "toggle_sz"
9941   [(set (reg:PSI FPSCR_REG)
9942         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
9943   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9944   "fschg"
9945   [(set_attr "type" "fp") (set_attr "fp_set" "unknown")])
9946
9947 ;; There's no way we can use it today, since optimize mode switching
9948 ;; doesn't enable us to know from which mode we're switching to the
9949 ;; mode it requests, to tell whether we can use a relative mode switch
9950 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
9951 ;; memory).
9952 (define_insn "toggle_pr"
9953   [(set (reg:PSI FPSCR_REG)
9954         (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
9955   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
9956   "fpchg"
9957   [(set_attr "type" "fp")])
9958
9959 (define_expand "addsf3"
9960   [(set (match_operand:SF 0 "arith_reg_operand" "")
9961         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
9962                  (match_operand:SF 2 "arith_reg_operand" "")))]
9963   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9964   "
9965 {
9966   if (TARGET_SH2E)
9967     {
9968       expand_sf_binop (&gen_addsf3_i, operands);
9969       DONE;
9970     }
9971 }")
9972
9973 (define_insn "*addsf3_media"
9974   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9975         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
9976                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
9977   "TARGET_SHMEDIA_FPU"
9978   "fadd.s       %1, %2, %0"
9979   [(set_attr "type" "fparith_media")])
9980
9981 (define_insn_and_split "unary_sf_op"
9982   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
9983         (vec_select:V2SF
9984          (vec_concat:V2SF
9985           (vec_select:SF
9986            (match_dup 0)
9987            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
9988           (match_operator:SF 2 "unary_float_operator"
9989             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
9990                             (parallel [(match_operand 4
9991                                         "const_int_operand" "n")]))]))
9992          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
9993   "TARGET_SHMEDIA_FPU"
9994   "#"
9995   "TARGET_SHMEDIA_FPU && reload_completed"
9996   [(set (match_dup 5) (match_dup 6))]
9997   "
9998 {
9999   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10000   rtx op1 = gen_rtx_REG (SFmode,
10001                          (true_regnum (operands[1])
10002                           + (INTVAL (operands[4]) ^ endian)));
10003
10004   operands[7] = gen_rtx_REG (SFmode,
10005                              (true_regnum (operands[0])
10006                               + (INTVAL (operands[3]) ^ endian)));
10007   operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
10008 }"
10009   [(set_attr "type" "fparith_media")])
10010
10011 (define_insn_and_split "binary_sf_op"
10012   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10013         (vec_select:V2SF
10014          (vec_concat:V2SF
10015           (vec_select:SF
10016            (match_dup 0)
10017            (parallel [(match_operand 7 "const_int_operand" "n")]))
10018           (match_operator:SF 3 "binary_float_operator"
10019             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
10020                             (parallel [(match_operand 5
10021                                         "const_int_operand" "n")]))
10022              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
10023                             (parallel [(match_operand 6
10024                                         "const_int_operand" "n")]))]))
10025          (parallel [(match_dup 7) (match_operand 4 "const_int_operand" "n")])))]
10026   "TARGET_SHMEDIA_FPU && INTVAL (operands[4]) != INTVAL (operands[7])"
10027   "#"
10028   "&& reload_completed"
10029   [(set (match_dup 8) (match_dup 9))]
10030   "
10031 {
10032   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
10033   rtx op1 = gen_rtx_REG (SFmode,
10034                          (true_regnum (operands[1])
10035                           + (INTVAL (operands[5]) ^ endian)));
10036   rtx op2 = gen_rtx_REG (SFmode,
10037                          (true_regnum (operands[2])
10038                           + (INTVAL (operands[6]) ^ endian)));
10039
10040   operands[8] = gen_rtx_REG (SFmode,
10041                              (true_regnum (operands[0])
10042                               + (INTVAL (operands[4]) ^ endian)));
10043   operands[9] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
10044 }"
10045   [(set_attr "type" "fparith_media")])
10046
10047 (define_insn "addsf3_i"
10048   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10049         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10050                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10051    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10052   "TARGET_SH2E"
10053   "fadd %2,%0"
10054   [(set_attr "type" "fp")
10055    (set_attr "fp_mode" "single")])
10056
10057 (define_expand "subsf3"
10058   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10059         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10060                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10061   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10062   "
10063 {
10064   if (TARGET_SH2E)
10065     {
10066       expand_sf_binop (&gen_subsf3_i, operands);
10067       DONE;
10068     }
10069 }")
10070
10071 (define_insn "*subsf3_media"
10072   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10073         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10074                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10075   "TARGET_SHMEDIA_FPU"
10076   "fsub.s       %1, %2, %0"
10077   [(set_attr "type" "fparith_media")])
10078
10079 (define_insn "subsf3_i"
10080   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10081         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
10082                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10083    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10084   "TARGET_SH2E"
10085   "fsub %2,%0"
10086   [(set_attr "type" "fp")
10087    (set_attr "fp_mode" "single")])
10088
10089 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
10090 ;; register in feeding fp instructions.  Thus, we cannot generate fmac for
10091 ;; mixed-precision SH4 targets.  To allow it to be still generated for the
10092 ;; SH3E, we use a separate insn for SH3E mulsf3.
10093
10094 (define_expand "mulsf3"
10095   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10096         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
10097                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
10098   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10099   "
10100 {
10101   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10102     expand_sf_binop (&gen_mulsf3_i4, operands);
10103   else if (TARGET_SH2E)
10104     emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2]));
10105   if (! TARGET_SHMEDIA)
10106     DONE;
10107 }")
10108
10109 (define_insn "*mulsf3_media"
10110   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10111         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10112                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10113   "TARGET_SHMEDIA_FPU"
10114   "fmul.s       %1, %2, %0"
10115   [(set_attr "type" "fparith_media")])
10116
10117 (define_insn "mulsf3_i4"
10118   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10119         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10120                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
10121    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10122   "TARGET_SH2E"
10123   "fmul %2,%0"
10124   [(set_attr "type" "fp")
10125    (set_attr "fp_mode" "single")])
10126
10127 (define_insn "mulsf3_ie"
10128   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10129         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
10130                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10131   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10132   "fmul %2,%0"
10133   [(set_attr "type" "fp")])
10134
10135 (define_insn "mac_media"
10136   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10137         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
10138                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10139                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
10140   "TARGET_SHMEDIA_FPU"
10141   "fmac.s %1, %2, %0"
10142   [(set_attr "type" "fparith_media")])
10143
10144 (define_insn "*macsf3"
10145   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10146         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
10147                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
10148                  (match_operand:SF 3 "arith_reg_operand" "0")))
10149    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
10150   "TARGET_SH2E && ! TARGET_SH4"
10151   "fmac fr0,%2,%0"
10152   [(set_attr "type" "fp")
10153    (set_attr "fp_mode" "single")])
10154
10155 (define_expand "divsf3"
10156   [(set (match_operand:SF 0 "arith_reg_operand" "")
10157         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
10158                 (match_operand:SF 2 "arith_reg_operand" "")))]
10159   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10160   "
10161 {
10162   if (TARGET_SH2E)
10163     {
10164       expand_sf_binop (&gen_divsf3_i, operands);
10165       DONE;
10166     }
10167 }")
10168
10169 (define_insn "*divsf3_media"
10170   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10171         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10172                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10173   "TARGET_SHMEDIA_FPU"
10174   "fdiv.s       %1, %2, %0"
10175   [(set_attr "type" "fdiv_media")])
10176
10177 (define_insn "divsf3_i"
10178   [(set (match_operand:SF 0 "arith_reg_dest" "=f")
10179         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
10180                  (match_operand:SF 2 "arith_reg_operand" "f")))
10181    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10182   "TARGET_SH2E"
10183   "fdiv %2,%0"
10184   [(set_attr "type" "fdiv")
10185    (set_attr "fp_mode" "single")])
10186
10187 (define_insn "floatdisf2"
10188   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10189         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10190   "TARGET_SHMEDIA_FPU"
10191   "float.qs %1, %0"
10192   [(set_attr "type" "fpconv_media")])
10193
10194 (define_expand "floatsisf2"
10195   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10196         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
10197   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10198   "
10199 {
10200   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10201     {
10202       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10203       DONE;
10204     }
10205 }")
10206
10207 (define_insn "*floatsisf2_media"
10208   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10209         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10210   "TARGET_SHMEDIA_FPU"
10211   "float.ls     %1, %0"
10212   [(set_attr "type" "fpconv_media")])
10213
10214 (define_insn "floatsisf2_i4"
10215   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10216         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
10217    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10218   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10219   "float        %1,%0"
10220   [(set_attr "type" "fp")
10221    (set_attr "fp_mode" "single")])
10222
10223 (define_insn "*floatsisf2_ie"
10224   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10225         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
10226   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10227   "float        %1,%0"
10228   [(set_attr "type" "fp")])
10229
10230 (define_insn "fix_truncsfdi2"
10231   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10232         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10233   "TARGET_SHMEDIA_FPU"
10234   "ftrc.sq %1, %0"
10235   [(set_attr "type" "fpconv_media")])
10236
10237 (define_expand "fix_truncsfsi2"
10238   [(set (match_operand:SI 0 "fpul_operand" "=y")
10239         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10240   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10241   "
10242 {
10243   if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10244     {
10245       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10246       DONE;
10247     }
10248 }")
10249
10250 (define_insn "*fix_truncsfsi2_media"
10251   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10252         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10253   "TARGET_SHMEDIA_FPU"
10254   "ftrc.sl      %1, %0"
10255   [(set_attr "type" "fpconv_media")])
10256
10257 (define_insn "fix_truncsfsi2_i4"
10258   [(set (match_operand:SI 0 "fpul_operand" "=y")
10259         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10260    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10261   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10262   "ftrc %1,%0"
10263   [(set_attr "type" "ftrc_s")
10264    (set_attr "fp_mode" "single")])
10265
10266 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
10267 ;; fix_truncsfsi2_i4.
10268 ;; (define_insn "fix_truncsfsi2_i4_2"
10269 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10270 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10271 ;;   (use (reg:PSI FPSCR_REG))
10272 ;;   (clobber (reg:SI FPUL_REG))]
10273 ;;  "TARGET_SH4"
10274 ;;  "#"
10275 ;;  [(set_attr "length" "4")
10276 ;;   (set_attr "fp_mode" "single")])
10277
10278 ;;(define_split
10279 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10280 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10281 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
10282 ;;   (clobber (reg:SI FPUL_REG))]
10283 ;;  "TARGET_SH4"
10284 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10285 ;;            (use (match_dup 2))])
10286 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
10287
10288 (define_insn "*fixsfsi"
10289   [(set (match_operand:SI 0 "fpul_operand" "=y")
10290         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10291   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10292   "ftrc %1,%0"
10293   [(set_attr "type" "fp")])
10294
10295 (define_insn "cmpgtsf_t"
10296   [(set (reg:SI T_REG)
10297         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10298                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10299   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10300   "fcmp/gt      %1,%0"
10301   [(set_attr "type" "fp")
10302    (set_attr "fp_mode" "single")])
10303
10304 (define_insn "cmpeqsf_t"
10305   [(set (reg:SI T_REG)
10306         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10307                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10308   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10309   "fcmp/eq      %1,%0"
10310   [(set_attr "type" "fp")
10311    (set_attr "fp_mode" "single")])
10312
10313 (define_insn "ieee_ccmpeqsf_t"
10314   [(set (reg:SI T_REG)
10315         (ior:SI (reg:SI T_REG)
10316                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10317                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
10318   "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10319   "* return output_ieee_ccmpeq (insn, operands);"
10320   [(set_attr "length" "4")])
10321
10322
10323 (define_insn "cmpgtsf_t_i4"
10324   [(set (reg:SI T_REG)
10325         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10326                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10327    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10328   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10329   "fcmp/gt      %1,%0"
10330   [(set_attr "type" "fp")
10331    (set_attr "fp_mode" "single")])
10332
10333 (define_insn "cmpeqsf_t_i4"
10334   [(set (reg:SI T_REG)
10335         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10336                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10337    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10338   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10339   "fcmp/eq      %1,%0"
10340   [(set_attr "type" "fp")
10341    (set_attr "fp_mode" "single")])
10342
10343 (define_insn "*ieee_ccmpeqsf_t_4"
10344   [(set (reg:SI T_REG)
10345         (ior:SI (reg:SI T_REG)
10346                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10347                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
10348    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10349   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10350   "* return output_ieee_ccmpeq (insn, operands);"
10351   [(set_attr "length" "4")
10352    (set_attr "fp_mode" "single")])
10353
10354 (define_insn "cmpeqsf_media"
10355   [(set (match_operand:DI 0 "register_operand" "=r")
10356         (eq:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10357                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10358   "TARGET_SHMEDIA_FPU"
10359   "fcmpeq.s     %1, %2, %0"
10360   [(set_attr "type" "fcmp_media")])
10361
10362 (define_insn "cmpsieqsf_media"
10363   [(set (match_operand:SI 0 "register_operand" "=r")
10364         (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10365                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10366   "TARGET_SHMEDIA_FPU"
10367   "fcmpeq.s     %1, %2, %0"
10368   [(set_attr "type" "fcmp_media")])
10369
10370 (define_insn "cmpgtsf_media"
10371   [(set (match_operand:DI 0 "register_operand" "=r")
10372         (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10373                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10374   "TARGET_SHMEDIA_FPU"
10375   "fcmpgt.s     %1, %2, %0"
10376   [(set_attr "type" "fcmp_media")])
10377
10378 (define_insn "cmpgesf_media"
10379   [(set (match_operand:DI 0 "register_operand" "=r")
10380         (ge:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10381                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10382   "TARGET_SHMEDIA_FPU"
10383   "fcmpge.s     %1, %2, %0"
10384   [(set_attr "type" "fcmp_media")])
10385
10386 (define_insn "cmpunsf_media"
10387   [(set (match_operand:DI 0 "register_operand" "=r")
10388         (unordered:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10389                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10390   "TARGET_SHMEDIA_FPU"
10391   "fcmpun.s     %1, %2, %0"
10392   [(set_attr "type" "fcmp_media")])
10393
10394 (define_expand "cmpsf"
10395   [(set (reg:SI T_REG)
10396         (compare (match_operand:SF 0 "arith_operand" "")
10397                  (match_operand:SF 1 "arith_operand" "")))]
10398   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10399   "
10400 {
10401   sh_compare_op0 = operands[0];
10402   sh_compare_op1 = operands[1];
10403   DONE;
10404 }")
10405
10406 (define_expand "negsf2"
10407   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10408         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10409   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10410   "
10411 {
10412   if (TARGET_SH2E)
10413     {
10414       expand_sf_unop (&gen_negsf2_i, operands);
10415       DONE;
10416     }
10417 }")
10418
10419 (define_insn "*negsf2_media"
10420   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10421         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10422   "TARGET_SHMEDIA_FPU"
10423   "fneg.s       %1, %0"
10424   [(set_attr "type" "fmove_media")])
10425
10426 (define_insn "negsf2_i"
10427   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10428         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10429    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10430   "TARGET_SH2E"
10431   "fneg %0"
10432   [(set_attr "type" "fmove")
10433    (set_attr "fp_mode" "single")])
10434
10435 (define_expand "sqrtsf2"
10436   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10437         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10438   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
10439   "
10440 {
10441   if (TARGET_SH3E)
10442     {
10443       expand_sf_unop (&gen_sqrtsf2_i, operands);
10444       DONE;
10445     }
10446 }")
10447
10448 (define_insn "*sqrtsf2_media"
10449   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10450         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10451   "TARGET_SHMEDIA_FPU"
10452   "fsqrt.s      %1, %0"
10453   [(set_attr "type" "fdiv_media")])
10454
10455 (define_insn "sqrtsf2_i"
10456   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10457         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10458    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10459   "TARGET_SH3E"
10460   "fsqrt        %0"
10461   [(set_attr "type" "fdiv")
10462    (set_attr "fp_mode" "single")])
10463
10464 (define_insn "rsqrtsf2"
10465   [(set (match_operand:SF 0 "register_operand" "=f")
10466         (div:SF (match_operand:SF 1 "immediate_operand" "i")
10467                 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
10468    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10469   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10470    && operands[1] == CONST1_RTX (SFmode)"
10471   "fsrra        %0"
10472   [(set_attr "type" "fsrra")
10473    (set_attr "fp_mode" "single")])
10474
10475 (define_insn "fsca"
10476   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10477         (vec_concat:V2SF
10478          (unspec:SF [(mult:SF
10479                       (float:SF (match_operand:SI 1 "fpul_operand" "y"))
10480                       (match_operand:SF 2 "immediate_operand" "i"))
10481                     ] UNSPEC_FSINA)
10482          (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
10483                     ] UNSPEC_FCOSA)))
10484    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10485   "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10486    && operands[2] == sh_fsca_int2sf ()"
10487   "fsca fpul,%d0"
10488   [(set_attr "type" "fsca")
10489    (set_attr "fp_mode" "single")])
10490
10491 (define_expand "sinsf2"
10492   [(set (match_operand:SF 0 "nonimmediate_operand" "")
10493         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10494                    UNSPEC_FSINA))]
10495   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10496   "
10497 {
10498   rtx scaled = gen_reg_rtx (SFmode);
10499   rtx truncated = gen_reg_rtx (SImode);
10500   rtx fsca = gen_reg_rtx (V2SFmode);
10501   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10502
10503   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10504   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10505   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10506                           get_fpscr_rtx ()));
10507   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
10508   DONE;
10509 }")
10510
10511 (define_expand "cossf2"
10512   [(set (match_operand:SF 0 "nonimmediate_operand" "")
10513         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10514                    UNSPEC_FCOSA))]
10515   "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10516   "
10517 {
10518   rtx scaled = gen_reg_rtx (SFmode);
10519   rtx truncated = gen_reg_rtx (SImode);
10520   rtx fsca = gen_reg_rtx (V2SFmode);
10521   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10522
10523   emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10524   emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10525   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10526                           get_fpscr_rtx ()));
10527   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
10528   DONE;
10529 }")
10530
10531 (define_expand "sindf2"
10532   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10533         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10534                    UNSPEC_FSINA))]
10535   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10536   "
10537 {
10538   rtx scaled = gen_reg_rtx (DFmode);
10539   rtx truncated = gen_reg_rtx (SImode);
10540   rtx fsca = gen_reg_rtx (V2SFmode);
10541   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10542   rtx sfresult = gen_reg_rtx (SFmode);
10543
10544   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10545   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10546   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10547                           get_fpscr_rtx ()));
10548   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
10549   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10550   DONE;
10551 }")
10552
10553 (define_expand "cosdf2"
10554   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10555         (unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10556                    UNSPEC_FCOSA))]
10557   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10558   "
10559 {
10560   rtx scaled = gen_reg_rtx (DFmode);
10561   rtx truncated = gen_reg_rtx (SImode);
10562   rtx fsca = gen_reg_rtx (V2SFmode);
10563   rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10564   rtx sfresult = gen_reg_rtx (SFmode);
10565
10566   emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10567   emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10568   emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10569                           get_fpscr_rtx ()));
10570   emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
10571   emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10572   DONE;
10573 }")
10574
10575 (define_expand "abssf2"
10576   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10577         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10578   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10579   "
10580 {
10581   if (TARGET_SH2E)
10582     {
10583       expand_sf_unop (&gen_abssf2_i, operands);
10584       DONE;
10585     }
10586 }")
10587
10588 (define_insn "*abssf2_media"
10589   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10590         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10591   "TARGET_SHMEDIA_FPU"
10592   "fabs.s       %1, %0"
10593   [(set_attr "type" "fmove_media")])
10594
10595 (define_insn "abssf2_i"
10596   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10597         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10598    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10599   "TARGET_SH2E"
10600   "fabs %0"
10601   [(set_attr "type" "fmove")
10602    (set_attr "fp_mode" "single")])
10603
10604 (define_expand "adddf3"
10605   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10606         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10607                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10608   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10609   "
10610 {
10611   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10612     {
10613       expand_df_binop (&gen_adddf3_i, operands);
10614       DONE;
10615     }
10616 }")
10617
10618 (define_insn "*adddf3_media"
10619   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10620         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10621                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10622   "TARGET_SHMEDIA_FPU"
10623   "fadd.d       %1, %2, %0"
10624   [(set_attr "type" "dfparith_media")])
10625
10626 (define_insn "adddf3_i"
10627   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10628         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10629                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10630    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10631   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10632   "fadd %2,%0"
10633   [(set_attr "type" "dfp_arith")
10634    (set_attr "fp_mode" "double")])
10635
10636 (define_expand "subdf3"
10637   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10638         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10639                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10640   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10641   "
10642 {
10643   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10644     {
10645       expand_df_binop (&gen_subdf3_i, operands);
10646       DONE;
10647     }
10648 }")
10649
10650 (define_insn "*subdf3_media"
10651   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10652         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10653                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10654   "TARGET_SHMEDIA_FPU"
10655   "fsub.d       %1, %2, %0"
10656   [(set_attr "type" "dfparith_media")])
10657
10658 (define_insn "subdf3_i"
10659   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10660         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10661                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10662    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10663   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10664   "fsub %2,%0"
10665   [(set_attr "type" "dfp_arith")
10666    (set_attr "fp_mode" "double")])
10667
10668 (define_expand "muldf3"
10669   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10670         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10671                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10672   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10673   "
10674 {
10675   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10676     {
10677       expand_df_binop (&gen_muldf3_i, operands);
10678       DONE;
10679     }
10680 }")
10681
10682 (define_insn "*muldf3_media"
10683   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10684         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10685                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10686   "TARGET_SHMEDIA_FPU"
10687   "fmul.d       %1, %2, %0"
10688   [(set_attr "type" "dfmul_media")])
10689
10690 (define_insn "muldf3_i"
10691   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10692         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10693                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10694    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10695   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10696   "fmul %2,%0"
10697   [(set_attr "type" "dfp_arith")
10698    (set_attr "fp_mode" "double")])
10699
10700 (define_expand "divdf3"
10701   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10702         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10703                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10704   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10705   "
10706 {
10707   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10708     {
10709       expand_df_binop (&gen_divdf3_i, operands);
10710       DONE;
10711     }
10712 }")
10713
10714 (define_insn "*divdf3_media"
10715   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10716         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10717                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10718   "TARGET_SHMEDIA_FPU"
10719   "fdiv.d       %1, %2, %0"
10720   [(set_attr "type" "dfdiv_media")])
10721
10722 (define_insn "divdf3_i"
10723   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10724         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10725                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10726    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10727   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10728   "fdiv %2,%0"
10729   [(set_attr "type" "dfdiv")
10730    (set_attr "fp_mode" "double")])
10731
10732 (define_insn "floatdidf2"
10733   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10734         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10735   "TARGET_SHMEDIA_FPU"
10736   "float.qd     %1, %0"
10737   [(set_attr "type" "dfpconv_media")])
10738
10739 (define_expand "floatsidf2"
10740   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10741         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
10742   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10743   "
10744 {
10745   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10746     {
10747       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
10748                                       get_fpscr_rtx ()));
10749       DONE;
10750     }
10751 }")
10752
10753 (define_insn "*floatsidf2_media"
10754   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10755         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10756   "TARGET_SHMEDIA_FPU"
10757   "float.ld     %1, %0"
10758   [(set_attr "type" "dfpconv_media")])
10759
10760 (define_insn "floatsidf2_i"
10761   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10762         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
10763    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10764   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10765   "float        %1,%0"
10766   [(set_attr "type" "dfp_conv")
10767    (set_attr "fp_mode" "double")])
10768
10769 (define_insn "fix_truncdfdi2"
10770   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10771         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10772   "TARGET_SHMEDIA_FPU"
10773   "ftrc.dq      %1, %0"
10774   [(set_attr "type" "dfpconv_media")])
10775
10776 (define_expand "fix_truncdfsi2"
10777   [(set (match_operand:SI 0 "fpul_operand" "")
10778         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
10779   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10780   "
10781 {
10782   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10783     {
10784       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
10785                                           get_fpscr_rtx ()));
10786       DONE;
10787     }
10788 }")
10789
10790 (define_insn "*fix_truncdfsi2_media"
10791   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10792         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10793   "TARGET_SHMEDIA_FPU"
10794   "ftrc.dl      %1, %0"
10795   [(set_attr "type" "dfpconv_media")])
10796
10797 (define_insn "fix_truncdfsi2_i"
10798   [(set (match_operand:SI 0 "fpul_operand" "=y")
10799         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
10800    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10801   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10802   "ftrc %1,%0"
10803   [(set_attr "type" "dfp_conv")
10804    (set_attr "dfp_comp" "no")
10805    (set_attr "fp_mode" "double")])
10806
10807 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
10808 ;; fix_truncdfsi2_i.
10809 ;; (define_insn "fix_truncdfsi2_i4"
10810 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10811 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10812 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10813 ;;    (clobber (reg:SI FPUL_REG))]
10814 ;;   "TARGET_SH4"
10815 ;;   "#"
10816 ;;   [(set_attr "length" "4")
10817 ;;    (set_attr "fp_mode" "double")])
10818 ;;
10819 ;; (define_split
10820 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10821 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10822 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10823 ;;    (clobber (reg:SI FPUL_REG))]
10824 ;;   "TARGET_SH4"
10825 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10826 ;;            (use (match_dup 2))])
10827 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
10828
10829 (define_insn "cmpgtdf_t"
10830   [(set (reg:SI T_REG)
10831         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
10832                (match_operand:DF 1 "arith_reg_operand" "f")))
10833    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10834   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10835   "fcmp/gt      %1,%0"
10836   [(set_attr "type" "dfp_cmp")
10837    (set_attr "fp_mode" "double")])
10838
10839 (define_insn "cmpeqdf_t"
10840   [(set (reg:SI T_REG)
10841         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10842                (match_operand:DF 1 "arith_reg_operand" "f")))
10843    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10844   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10845   "fcmp/eq      %1,%0"
10846   [(set_attr "type" "dfp_cmp")
10847    (set_attr "fp_mode" "double")])
10848
10849 (define_insn "*ieee_ccmpeqdf_t"
10850   [(set (reg:SI T_REG)
10851         (ior:SI (reg:SI T_REG)
10852                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10853                        (match_operand:DF 1 "arith_reg_operand" "f"))))
10854    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10855   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10856   "* return output_ieee_ccmpeq (insn, operands);"
10857   [(set_attr "length" "4")
10858    (set_attr "fp_mode" "double")])
10859
10860 (define_insn "cmpeqdf_media"
10861   [(set (match_operand:DI 0 "register_operand" "=r")
10862         (eq:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10863                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10864   "TARGET_SHMEDIA_FPU"
10865   "fcmpeq.d     %1,%2,%0"
10866   [(set_attr "type" "fcmp_media")])
10867
10868 (define_insn "cmpsieqdf_media"
10869   [(set (match_operand:SI 0 "register_operand" "=r")
10870         (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10871                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10872   "TARGET_SHMEDIA_FPU"
10873   "fcmpeq.d     %1,%2,%0"
10874   [(set_attr "type" "fcmp_media")])
10875
10876 (define_insn "cmpgtdf_media"
10877   [(set (match_operand:DI 0 "register_operand" "=r")
10878         (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10879                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10880   "TARGET_SHMEDIA_FPU"
10881   "fcmpgt.d     %1,%2,%0"
10882   [(set_attr "type" "fcmp_media")])
10883
10884 (define_insn "cmpgedf_media"
10885   [(set (match_operand:DI 0 "register_operand" "=r")
10886         (ge:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10887                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10888   "TARGET_SHMEDIA_FPU"
10889   "fcmpge.d     %1,%2,%0"
10890   [(set_attr "type" "fcmp_media")])
10891
10892 (define_insn "cmpundf_media"
10893   [(set (match_operand:DI 0 "register_operand" "=r")
10894         (unordered:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10895                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10896   "TARGET_SHMEDIA_FPU"
10897   "fcmpun.d     %1,%2,%0"
10898   [(set_attr "type" "fcmp_media")])
10899
10900 (define_expand "cmpdf"
10901   [(set (reg:SI T_REG)
10902         (compare (match_operand:DF 0 "arith_operand" "")
10903                  (match_operand:DF 1 "arith_operand" "")))]
10904   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10905   "
10906 {
10907   sh_compare_op0 = operands[0];
10908   sh_compare_op1 = operands[1];
10909   DONE;
10910 }")
10911
10912 (define_expand "negdf2"
10913   [(set (match_operand:DF 0 "arith_reg_operand" "")
10914         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10915   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10916   "
10917 {
10918   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10919     {
10920       expand_df_unop (&gen_negdf2_i, operands);
10921       DONE;
10922     }
10923 }")
10924
10925 (define_insn "*negdf2_media"
10926   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10927         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10928   "TARGET_SHMEDIA_FPU"
10929   "fneg.d       %1, %0"
10930   [(set_attr "type" "fmove_media")])
10931
10932 (define_insn "negdf2_i"
10933   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10934         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10935    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10936   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10937   "fneg %0"
10938   [(set_attr "type" "fmove")
10939    (set_attr "fp_mode" "double")])
10940
10941 (define_expand "sqrtdf2"
10942   [(set (match_operand:DF 0 "arith_reg_operand" "")
10943         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10944   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10945   "
10946 {
10947   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10948     {
10949       expand_df_unop (&gen_sqrtdf2_i, operands);
10950       DONE;
10951     }
10952 }")
10953
10954 (define_insn "*sqrtdf2_media"
10955   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10956         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10957   "TARGET_SHMEDIA_FPU"
10958   "fsqrt.d      %1, %0"
10959   [(set_attr "type" "dfdiv_media")])
10960
10961 (define_insn "sqrtdf2_i"
10962   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10963         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10964    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10965   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10966   "fsqrt        %0"
10967   [(set_attr "type" "dfdiv")
10968    (set_attr "fp_mode" "double")])
10969
10970 (define_expand "absdf2"
10971   [(set (match_operand:DF 0 "arith_reg_operand" "")
10972         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10973   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10974   "
10975 {
10976   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10977     {
10978       expand_df_unop (&gen_absdf2_i, operands);
10979       DONE;
10980     }
10981 }")
10982
10983 (define_insn "*absdf2_media"
10984   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10985         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10986   "TARGET_SHMEDIA_FPU"
10987   "fabs.d       %1, %0"
10988   [(set_attr "type" "fmove_media")])
10989
10990 (define_insn "absdf2_i"
10991   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10992         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10993    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10994   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10995   "fabs %0"
10996   [(set_attr "type" "fmove")
10997    (set_attr "fp_mode" "double")])
10998
10999 (define_expand "extendsfdf2"
11000   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
11001         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
11002   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11003   "
11004 {
11005   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11006     {
11007       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
11008                                         get_fpscr_rtx ()));
11009       DONE;
11010     }
11011 }")
11012
11013 (define_insn "*extendsfdf2_media"
11014   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11015         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11016   "TARGET_SHMEDIA_FPU"
11017   "fcnv.sd      %1, %0"
11018   [(set_attr "type" "dfpconv_media")])
11019
11020 (define_insn "extendsfdf2_i4"
11021   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
11022         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
11023    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11024   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11025   "fcnvsd  %1,%0"
11026   [(set_attr "type" "fp")
11027    (set_attr "fp_mode" "double")])
11028
11029 (define_expand "truncdfsf2"
11030   [(set (match_operand:SF 0 "fpul_operand" "")
11031         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
11032   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11033   "
11034 {
11035   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
11036     {
11037       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
11038                                        get_fpscr_rtx ()));
11039       DONE;
11040     }
11041 }")
11042
11043 (define_insn "*truncdfsf2_media"
11044   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11045         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
11046   "TARGET_SHMEDIA_FPU"
11047   "fcnv.ds      %1, %0"
11048   [(set_attr "type" "dfpconv_media")])
11049
11050 (define_insn "truncdfsf2_i4"
11051   [(set (match_operand:SF 0 "fpul_operand" "=y")
11052         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
11053    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11054   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11055   "fcnvds  %1,%0"
11056   [(set_attr "type" "fp")
11057    (set_attr "fp_mode" "double")])
11058 \f
11059 ;; Bit field extract patterns.  These give better code for packed bitfields,
11060 ;; because they allow auto-increment addresses to be generated.
11061
11062 (define_expand "insv"
11063   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
11064                          (match_operand:SI 1 "immediate_operand" "")
11065                          (match_operand:SI 2 "immediate_operand" ""))
11066         (match_operand:SI 3 "general_operand" ""))]
11067   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
11068   "
11069 {
11070   rtx addr_target, orig_address, shift_reg, qi_val;
11071   HOST_WIDE_INT bitsize, size, v = 0;
11072   rtx x = operands[3];
11073
11074   /* ??? expmed doesn't care for non-register predicates.  */
11075   if (! memory_operand (operands[0], VOIDmode)
11076       || ! immediate_operand (operands[1], VOIDmode)
11077       || ! immediate_operand (operands[2], VOIDmode)
11078       || ! general_operand (x, VOIDmode))
11079     FAIL;
11080   /* If this isn't a 16 / 24 / 32 bit field, or if
11081      it doesn't start on a byte boundary, then fail.  */
11082   bitsize = INTVAL (operands[1]);
11083   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
11084       || (INTVAL (operands[2]) % 8) != 0)
11085     FAIL;
11086
11087   size = bitsize / 8;
11088   orig_address = XEXP (operands[0], 0);
11089   shift_reg = gen_reg_rtx (SImode);
11090   if (GET_CODE (x) == CONST_INT)
11091     {
11092       v = INTVAL (x);
11093       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
11094     }
11095   else
11096     {
11097       emit_insn (gen_movsi (shift_reg, operands[3]));
11098       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11099     }
11100   addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
11101
11102   operands[0] = replace_equiv_address (operands[0], addr_target);
11103   emit_insn (gen_movqi (operands[0], qi_val));
11104
11105   while (size -= 1)
11106     {
11107       if (GET_CODE (x) == CONST_INT)
11108         qi_val
11109           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
11110       else
11111         {
11112           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
11113           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
11114         }
11115       emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
11116       emit_insn (gen_movqi (operands[0], qi_val));
11117     }
11118
11119   DONE;
11120 }")
11121
11122 (define_insn "movua"
11123   [(set (match_operand:SI 0 "register_operand" "=z")
11124         (sign_extract:SI (match_operand:SI 1 "unaligned_load_operand" "Sua>")
11125                          (const_int 32) (const_int 0)))]
11126   "TARGET_SH4A_ARCH"
11127   "movua.l      %1,%0"
11128   [(set_attr "type" "movua")])
11129
11130 ;; We shouldn't need this, but cse replaces increments with references
11131 ;; to other regs before flow has a chance to create post_inc
11132 ;; addressing modes, and only postreload's cse_move2add brings the
11133 ;; increments back to a usable form.
11134 (define_peephole2
11135   [(set (match_operand:SI 0 "register_operand" "")
11136         (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
11137                          (const_int 32) (const_int 0)))
11138    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11139   "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
11140   [(set (match_operand:SI 0 "register_operand" "")
11141         (sign_extract:SI (mem:SI (post_inc:SI
11142                                   (match_operand:SI 1 "register_operand" "")))
11143                          (const_int 32) (const_int 0)))]
11144   "")
11145
11146 (define_expand "extv"
11147   [(set (match_operand:SI 0 "register_operand" "")
11148         (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11149                          (match_operand 2 "const_int_operand" "")
11150                          (match_operand 3 "const_int_operand" "")))]
11151   "TARGET_SH4A_ARCH"
11152 {
11153   if (TARGET_SH4A_ARCH
11154       && INTVAL (operands[2]) == 32
11155       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11156       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
11157     {
11158       emit_insn (gen_movua (operands[0],
11159                             adjust_address (operands[1], SImode, 0)));
11160       DONE;
11161     }
11162
11163   FAIL;
11164 })
11165
11166 (define_expand "extzv"
11167   [(set (match_operand:SI 0 "register_operand" "")
11168         (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11169                          (match_operand 2 "const_int_operand" "")
11170                          (match_operand 3 "const_int_operand" "")))]
11171   "TARGET_SH4A_ARCH"
11172 {
11173   if (TARGET_SH4A_ARCH
11174       && INTVAL (operands[2]) == 32
11175       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11176       && GET_CODE (operands[1]) == MEM && MEM_ALIGN (operands[1]) < 32)
11177     {
11178       emit_insn (gen_movua (operands[0],
11179                             adjust_address (operands[1], SImode, 0)));
11180       DONE;
11181     }
11182
11183   FAIL;
11184 })
11185
11186 \f
11187 ;; -------------------------------------------------------------------------
11188 ;; Peepholes
11189 ;; -------------------------------------------------------------------------
11190
11191 ;; This matches cases where a stack pointer increment at the start of the
11192 ;; epilogue combines with a stack slot read loading the return value.
11193
11194 (define_peephole
11195   [(set (match_operand:SI 0 "arith_reg_operand" "")
11196         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
11197    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11198   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
11199   "mov.l        @%1+,%0")
11200
11201 ;; See the comment on the dt combiner pattern above.
11202
11203 (define_peephole
11204   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11205         (plus:SI (match_dup 0)
11206                  (const_int -1)))
11207    (set (reg:SI T_REG)
11208         (eq:SI (match_dup 0)
11209                (const_int 0)))]
11210   "TARGET_SH2"
11211   "dt   %0")
11212
11213 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
11214 ;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
11215 ;; reload when the constant is too large for a reg+offset address.
11216
11217 ;; ??? We would get much better code if this was done in reload.  This would
11218 ;; require modifying find_reloads_address to recognize that if the constant
11219 ;; is out-of-range for an immediate add, then we get better code by reloading
11220 ;; the constant into a register than by reloading the sum into a register,
11221 ;; since the former is one instruction shorter if the address does not need
11222 ;; to be offsettable.  Unfortunately this does not work, because there is
11223 ;; only one register, r0, that can be used as an index register.  This register
11224 ;; is also the function return value register.  So, if we try to force reload
11225 ;; to use double-reg addresses, then we end up with some instructions that
11226 ;; need to use r0 twice.  The only way to fix this is to change the calling
11227 ;; convention so that r0 is not used to return values.
11228
11229 (define_peephole
11230   [(set (match_operand:SI 0 "register_operand" "=r")
11231         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11232    (set (mem:SI (match_dup 0))
11233         (match_operand:SI 2 "general_movsrc_operand" ""))]
11234   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11235   "mov.l        %2,@(%0,%1)")
11236
11237 (define_peephole
11238   [(set (match_operand:SI 0 "register_operand" "=r")
11239         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11240    (set (match_operand:SI 2 "general_movdst_operand" "")
11241         (mem:SI (match_dup 0)))]
11242   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11243   "mov.l        @(%0,%1),%2")
11244
11245 (define_peephole
11246   [(set (match_operand:SI 0 "register_operand" "=r")
11247         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11248    (set (mem:HI (match_dup 0))
11249         (match_operand:HI 2 "general_movsrc_operand" ""))]
11250   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11251   "mov.w        %2,@(%0,%1)")
11252
11253 (define_peephole
11254   [(set (match_operand:SI 0 "register_operand" "=r")
11255         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11256    (set (match_operand:HI 2 "general_movdst_operand" "")
11257         (mem:HI (match_dup 0)))]
11258   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11259   "mov.w        @(%0,%1),%2")
11260
11261 (define_peephole
11262   [(set (match_operand:SI 0 "register_operand" "=r")
11263         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11264    (set (mem:QI (match_dup 0))
11265         (match_operand:QI 2 "general_movsrc_operand" ""))]
11266   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11267   "mov.b        %2,@(%0,%1)")
11268
11269 (define_peephole
11270   [(set (match_operand:SI 0 "register_operand" "=r")
11271         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11272    (set (match_operand:QI 2 "general_movdst_operand" "")
11273         (mem:QI (match_dup 0)))]
11274   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11275   "mov.b        @(%0,%1),%2")
11276
11277 (define_peephole
11278   [(set (match_operand:SI 0 "register_operand" "=r")
11279         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11280    (set (mem:SF (match_dup 0))
11281         (match_operand:SF 2 "general_movsrc_operand" ""))]
11282   "TARGET_SH1 && REGNO (operands[0]) == 0
11283    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
11284        || (GET_CODE (operands[2]) == SUBREG
11285            && REGNO (SUBREG_REG (operands[2])) < 16))
11286    && reg_unused_after (operands[0], insn)"
11287   "mov.l        %2,@(%0,%1)")
11288
11289 (define_peephole
11290   [(set (match_operand:SI 0 "register_operand" "=r")
11291         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11292    (set (match_operand:SF 2 "general_movdst_operand" "")
11293
11294         (mem:SF (match_dup 0)))]
11295   "TARGET_SH1 && REGNO (operands[0]) == 0
11296    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
11297        || (GET_CODE (operands[2]) == SUBREG
11298            && REGNO (SUBREG_REG (operands[2])) < 16))
11299    && reg_unused_after (operands[0], insn)"
11300   "mov.l        @(%0,%1),%2")
11301
11302 (define_peephole
11303   [(set (match_operand:SI 0 "register_operand" "=r")
11304         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11305    (set (mem:SF (match_dup 0))
11306         (match_operand:SF 2 "general_movsrc_operand" ""))]
11307   "TARGET_SH2E && REGNO (operands[0]) == 0
11308    && ((GET_CODE (operands[2]) == REG
11309         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11310        || (GET_CODE (operands[2]) == SUBREG
11311            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11312    && reg_unused_after (operands[0], insn)"
11313   "fmov{.s|}    %2,@(%0,%1)")
11314
11315 (define_peephole
11316   [(set (match_operand:SI 0 "register_operand" "=r")
11317         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11318    (set (match_operand:SF 2 "general_movdst_operand" "")
11319
11320         (mem:SF (match_dup 0)))]
11321   "TARGET_SH2E && REGNO (operands[0]) == 0
11322    && ((GET_CODE (operands[2]) == REG
11323         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11324        || (GET_CODE (operands[2]) == SUBREG
11325            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11326    && reg_unused_after (operands[0], insn)"
11327   "fmov{.s|}    @(%0,%1),%2")
11328
11329 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
11330 (define_insn "sp_switch_1"
11331   [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
11332   "TARGET_SH1"
11333   "*
11334 {
11335   output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", operands);
11336   output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", operands);
11337   return \"mov r0,r15\";
11338 }"
11339   [(set_attr "length" "10")])
11340
11341 ;; Switch back to the original stack for interrupt functions with the
11342 ;; sp_switch attribute.  */
11343 (define_insn "sp_switch_2"
11344   [(const_int 2)]
11345   "TARGET_SH1"
11346   "mov.l @r15+,r15\;mov.l @r15+,r0"
11347   [(set_attr "length" "4")])
11348
11349 ;; Integer vector moves
11350
11351 (define_expand "movv8qi"
11352   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
11353         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
11354   "TARGET_SHMEDIA"
11355   "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
11356
11357 (define_insn "movv8qi_i"
11358   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
11359         (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11360   "TARGET_SHMEDIA
11361    && (register_operand (operands[0], V8QImode)
11362        || sh_register_operand (operands[1], V8QImode))"
11363   "@
11364         add     %1, r63, %0
11365         movi    %1, %0
11366         #
11367         ld%M1.q %m1, %0
11368         st%M0.q %m0, %N1"
11369   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11370    (set_attr "length" "4,4,16,4,4")])
11371
11372 (define_split
11373   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
11374         (subreg:V8QI (const_int 0) 0))]
11375   "TARGET_SHMEDIA"
11376   [(set (match_dup 0)
11377         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
11378                             (const_int 0) (const_int 0) (const_int 0)
11379                             (const_int 0) (const_int 0)]))])
11380
11381 (define_split
11382   [(set (match_operand 0 "arith_reg_dest" "")
11383         (match_operand 1 "sh_rep_vec" ""))]
11384   "TARGET_SHMEDIA && reload_completed
11385    && GET_MODE (operands[0]) == GET_MODE (operands[1])
11386    && sh_vector_mode_supported_p (GET_MODE (operands[0]))
11387    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
11388    && (XVECEXP (operands[1], 0, 0) != const0_rtx
11389        || XVECEXP (operands[1], 0, 1) != const0_rtx)
11390    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
11391        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
11392   [(set (match_dup 0) (match_dup 1))
11393    (match_dup 2)]
11394   "
11395 {
11396   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
11397   rtx elt1 = XVECEXP (operands[1], 0, 1);
11398
11399   if (unit_size > 2)
11400     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
11401   else
11402     {
11403       if (unit_size < 2)
11404         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
11405       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
11406     }
11407   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
11408   operands[1] = XVECEXP (operands[1], 0, 0);
11409   if (unit_size < 2)
11410     {
11411       if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (elt1) == CONST_INT)
11412         operands[1]
11413           = GEN_INT (TARGET_LITTLE_ENDIAN
11414                      ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
11415                      : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
11416       else
11417         {
11418           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
11419           operands[1]
11420             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
11421         }
11422     }
11423 }")
11424
11425 (define_split
11426   [(set (match_operand 0 "arith_reg_dest" "")
11427         (match_operand 1 "sh_const_vec" ""))]
11428   "TARGET_SHMEDIA && reload_completed
11429    && GET_MODE (operands[0]) == GET_MODE (operands[1])
11430    && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
11431   [(set (match_dup 0) (match_dup 1))]
11432   "
11433 {
11434   rtx v = operands[1];
11435   enum machine_mode new_mode
11436     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
11437
11438   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
11439   operands[1]
11440     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
11441 }")
11442
11443 (define_expand "movv2hi"
11444   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
11445         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
11446   "TARGET_SHMEDIA"
11447   "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
11448
11449 (define_insn "movv2hi_i"
11450   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11451         (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11452   "TARGET_SHMEDIA
11453    && (register_operand (operands[0], V2HImode)
11454        || sh_register_operand (operands[1], V2HImode))"
11455   "@
11456         add.l   %1, r63, %0
11457         movi    %1, %0
11458         #
11459         ld%M1.l %m1, %0
11460         st%M0.l %m0, %N1"
11461   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11462    (set_attr "length" "4,4,16,4,4")
11463    (set (attr "highpart")
11464         (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
11465                (const_string "user")]
11466               (const_string "ignore")))])
11467
11468 (define_expand "movv4hi"
11469   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
11470         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
11471   "TARGET_SHMEDIA"
11472   "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
11473
11474 (define_insn "movv4hi_i"
11475   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11476         (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11477   "TARGET_SHMEDIA
11478    && (register_operand (operands[0], V4HImode)
11479        || sh_register_operand (operands[1], V4HImode))"
11480   "@
11481         add     %1, r63, %0
11482         movi    %1, %0
11483         #
11484         ld%M1.q %m1, %0
11485         st%M0.q %m0, %N1"
11486   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11487    (set_attr "length" "4,4,16,4,4")
11488    (set_attr "highpart" "depend")])
11489
11490 (define_expand "movv2si"
11491   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
11492         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
11493   "TARGET_SHMEDIA"
11494   "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
11495
11496 (define_insn "movv2si_i"
11497   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
11498         (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11499   "TARGET_SHMEDIA
11500    && (register_operand (operands[0], V2SImode)
11501        || sh_register_operand (operands[1], V2SImode))"
11502   "@
11503         add     %1, r63, %0
11504         #
11505         #
11506         ld%M1.q %m1, %0
11507         st%M0.q %m0, %N1"
11508   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11509    (set_attr "length" "4,4,16,4,4")
11510    (set_attr "highpart" "depend")])
11511
11512 ;; Multimedia Intrinsics
11513
11514 (define_insn "absv2si2"
11515   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11516         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
11517   "TARGET_SHMEDIA"
11518   "mabs.l       %1, %0"
11519   [(set_attr "type" "mcmp_media")
11520    (set_attr "highpart" "depend")])
11521
11522 (define_insn "absv4hi2"
11523   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11524         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
11525   "TARGET_SHMEDIA"
11526   "mabs.w       %1, %0"
11527   [(set_attr "type" "mcmp_media")
11528    (set_attr "highpart" "depend")])
11529
11530 (define_insn "addv2si3"
11531   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11532         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11533                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11534   "TARGET_SHMEDIA"
11535   "madd.l       %1, %2, %0"
11536   [(set_attr "type" "arith_media")
11537    (set_attr "highpart" "depend")])
11538
11539 (define_insn "addv4hi3"
11540   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11541         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11542                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11543   "TARGET_SHMEDIA"
11544   "madd.w       %1, %2, %0"
11545   [(set_attr "type" "arith_media")
11546    (set_attr "highpart" "depend")])
11547
11548 (define_insn_and_split "addv2hi3"
11549   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
11550         (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
11551                    (match_operand:V2HI 2 "extend_reg_operand" "r")))]
11552   "TARGET_SHMEDIA"
11553   "#"
11554   "TARGET_SHMEDIA"
11555   [(const_int 0)]
11556   "
11557 {
11558   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
11559   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
11560   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
11561   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
11562   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
11563
11564   emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
11565   emit_insn (gen_truncdisi2 (si_dst, di_dst));
11566   DONE;
11567 }"
11568   [(set_attr "highpart" "must_split")])
11569
11570 (define_insn "ssaddv2si3"
11571   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11572         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11573                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11574   "TARGET_SHMEDIA"
11575   "madds.l      %1, %2, %0"
11576   [(set_attr "type" "mcmp_media")
11577    (set_attr "highpart" "depend")])
11578
11579 (define_insn "usaddv8qi3"
11580   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11581         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
11582                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
11583   "TARGET_SHMEDIA"
11584   "madds.ub     %1, %2, %0"
11585   [(set_attr "type" "mcmp_media")
11586    (set_attr "highpart" "depend")])
11587
11588 (define_insn "ssaddv4hi3"
11589   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11590         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11591                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11592   "TARGET_SHMEDIA"
11593   "madds.w      %1, %2, %0"
11594   [(set_attr "type" "mcmp_media")
11595    (set_attr "highpart" "depend")])
11596
11597 (define_insn "negcmpeqv8qi"
11598   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11599         (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11600                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11601   "TARGET_SHMEDIA"
11602   "mcmpeq.b     %N1, %N2, %0"
11603   [(set_attr "type" "mcmp_media")
11604    (set_attr "highpart" "depend")])
11605
11606 (define_insn "negcmpeqv2si"
11607   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11608         (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11609                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11610   "TARGET_SHMEDIA"
11611   "mcmpeq.l     %N1, %N2, %0"
11612   [(set_attr "type" "mcmp_media")
11613    (set_attr "highpart" "depend")])
11614
11615 (define_insn "negcmpeqv4hi"
11616   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11617         (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11618                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11619   "TARGET_SHMEDIA"
11620   "mcmpeq.w     %N1, %N2, %0"
11621   [(set_attr "type" "mcmp_media")
11622    (set_attr "highpart" "depend")])
11623
11624 (define_insn "negcmpgtuv8qi"
11625   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11626         (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11627                             (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11628   "TARGET_SHMEDIA"
11629   "mcmpgt.ub    %N1, %N2, %0"
11630   [(set_attr "type" "mcmp_media")
11631    (set_attr "highpart" "depend")])
11632
11633 (define_insn "negcmpgtv2si"
11634   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11635         (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11636                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11637   "TARGET_SHMEDIA"
11638   "mcmpgt.l     %N1, %N2, %0"
11639   [(set_attr "type" "mcmp_media")
11640    (set_attr "highpart" "depend")])
11641
11642 (define_insn "negcmpgtv4hi"
11643   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11644         (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11645                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11646   "TARGET_SHMEDIA"
11647   "mcmpgt.w     %N1, %N2, %0"
11648   [(set_attr "type" "mcmp_media")
11649    (set_attr "highpart" "depend")])
11650
11651 (define_insn "mcmv"
11652   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11653         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11654                         (match_operand:DI 2 "arith_reg_operand" "r"))
11655                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
11656                         (not:DI (match_dup 2)))))]
11657   "TARGET_SHMEDIA"
11658   "mcmv %N1, %2, %0"
11659   [(set_attr "type" "arith_media")
11660    (set_attr "highpart" "depend")])
11661
11662 (define_insn "mcnvs_lw"
11663   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11664         (vec_concat:V4HI
11665          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
11666          (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11667   "TARGET_SHMEDIA"
11668   "mcnvs.lw     %N1, %N2, %0"
11669   [(set_attr "type" "mcmp_media")])
11670
11671 (define_insn "mcnvs_wb"
11672   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11673         (vec_concat:V8QI
11674          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11675          (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11676   "TARGET_SHMEDIA"
11677   "mcnvs.wb     %N1, %N2, %0"
11678   [(set_attr "type" "mcmp_media")])
11679
11680 (define_insn "mcnvs_wub"
11681   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11682         (vec_concat:V8QI
11683          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11684          (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11685   "TARGET_SHMEDIA"
11686   "mcnvs.wub    %N1, %N2, %0"
11687   [(set_attr "type" "mcmp_media")])
11688
11689 (define_insn "mextr_rl"
11690   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11691         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11692                              (match_operand:HI 3 "mextr_bit_offset" "i"))
11693                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11694                           (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11695   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11696   "*
11697 {
11698   static char templ[21];
11699
11700   sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
11701            (int) INTVAL (operands[3]) >> 3);
11702   return templ;
11703 }"
11704   [(set_attr "type" "arith_media")])
11705
11706 (define_insn "*mextr_lr"
11707   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11708         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11709                            (match_operand:HI 3 "mextr_bit_offset" "i"))
11710                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11711                             (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11712   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11713   "*
11714 {
11715   static char templ[21];
11716
11717   sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
11718            (int) INTVAL (operands[4]) >> 3);
11719   return templ;
11720 }"
11721   [(set_attr "type" "arith_media")])
11722
11723 ; mextrN can be modelled with vec_select / vec_concat, but the selection
11724 ; vector then varies depending on endianness.
11725 (define_expand "mextr1"
11726   [(match_operand:DI 0 "arith_reg_dest" "")
11727    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11728    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11729   "TARGET_SHMEDIA"
11730   "
11731 {
11732   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11733                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
11734   DONE;
11735 }")
11736
11737 (define_expand "mextr2"
11738   [(match_operand:DI 0 "arith_reg_dest" "")
11739    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11740    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11741   "TARGET_SHMEDIA"
11742   "
11743 {
11744   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11745                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
11746   DONE;
11747 }")
11748
11749 (define_expand "mextr3"
11750   [(match_operand:DI 0 "arith_reg_dest" "")
11751    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11752    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11753   "TARGET_SHMEDIA"
11754   "
11755 {
11756   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11757                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
11758   DONE;
11759 }")
11760
11761 (define_expand "mextr4"
11762   [(match_operand:DI 0 "arith_reg_dest" "")
11763    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11764    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11765   "TARGET_SHMEDIA"
11766   "
11767 {
11768   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11769                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
11770   DONE;
11771 }")
11772
11773 (define_expand "mextr5"
11774   [(match_operand:DI 0 "arith_reg_dest" "")
11775    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11776    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11777   "TARGET_SHMEDIA"
11778   "
11779 {
11780   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11781                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
11782   DONE;
11783 }")
11784
11785 (define_expand "mextr6"
11786   [(match_operand:DI 0 "arith_reg_dest" "")
11787    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11788    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11789   "TARGET_SHMEDIA"
11790   "
11791 {
11792   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11793                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
11794   DONE;
11795 }")
11796
11797 (define_expand "mextr7"
11798   [(match_operand:DI 0 "arith_reg_dest" "")
11799    (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11800    (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11801   "TARGET_SHMEDIA"
11802   "
11803 {
11804   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11805                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
11806   DONE;
11807 }")
11808
11809 (define_expand "mmacfx_wl"
11810   [(match_operand:V2SI 0 "arith_reg_dest" "")
11811    (match_operand:V2HI 1 "extend_reg_operand" "")
11812    (match_operand:V2HI 2 "extend_reg_operand" "")
11813    (match_operand:V2SI 3 "arith_reg_operand" "")]
11814   "TARGET_SHMEDIA"
11815   "
11816 {
11817   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
11818                               operands[1], operands[2]));
11819   DONE;
11820 }")
11821
11822 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
11823 ;; is depend
11824 (define_insn "mmacfx_wl_i"
11825   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11826         (ss_plus:V2SI
11827          (match_operand:V2SI 1 "arith_reg_operand" "0")
11828          (ss_truncate:V2SI
11829           (ashift:V2DI
11830            (sign_extend:V2DI
11831             (mult:V2SI
11832              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
11833              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
11834            (const_int 1)))))]
11835   "TARGET_SHMEDIA"
11836   "mmacfx.wl    %2, %3, %0"
11837   [(set_attr "type" "mac_media")
11838    (set_attr "highpart" "depend")])
11839
11840 (define_expand "mmacnfx_wl"
11841   [(match_operand:V2SI 0 "arith_reg_dest" "")
11842    (match_operand:V2HI 1 "extend_reg_operand" "")
11843    (match_operand:V2HI 2 "extend_reg_operand" "")
11844    (match_operand:V2SI 3 "arith_reg_operand" "")]
11845   "TARGET_SHMEDIA"
11846   "
11847 {
11848   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
11849                                operands[1], operands[2]));
11850   DONE;
11851 }")
11852
11853 (define_insn "mmacnfx_wl_i"
11854   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11855         (ss_minus:V2SI
11856          (match_operand:V2SI 1 "arith_reg_operand" "0")
11857          (ss_truncate:V2SI
11858           (ashift:V2DI
11859            (sign_extend:V2DI
11860             (mult:V2SI
11861              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
11862              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
11863            (const_int 1)))))]
11864   "TARGET_SHMEDIA"
11865   "mmacnfx.wl   %2, %3, %0"
11866   [(set_attr "type" "mac_media")
11867    (set_attr "highpart" "depend")])
11868
11869 (define_insn "mulv2si3"
11870   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11871         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
11872                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11873   "TARGET_SHMEDIA"
11874   "mmul.l       %1, %2, %0"
11875   [(set_attr "type" "d2mpy_media")
11876    (set_attr "highpart" "depend")])
11877
11878 (define_insn "mulv4hi3"
11879   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11880         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
11881                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11882   "TARGET_SHMEDIA"
11883   "mmul.w       %1, %2, %0"
11884   [(set_attr "type" "dmpy_media")
11885    (set_attr "highpart" "depend")])
11886
11887 (define_insn "mmulfx_l"
11888   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11889         (ss_truncate:V2SI
11890          (ashiftrt:V2DI
11891           (mult:V2DI
11892            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
11893            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
11894           (const_int 31))))]
11895   "TARGET_SHMEDIA"
11896   "mmulfx.l     %1, %2, %0"
11897   [(set_attr "type" "d2mpy_media")
11898    (set_attr "highpart" "depend")])
11899
11900 (define_insn "mmulfx_w"
11901   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11902         (ss_truncate:V4HI
11903          (ashiftrt:V4SI
11904           (mult:V4SI
11905            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
11906            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
11907           (const_int 15))))]
11908   "TARGET_SHMEDIA"
11909   "mmulfx.w     %1, %2, %0"
11910   [(set_attr "type" "dmpy_media")
11911    (set_attr "highpart" "depend")])
11912
11913 (define_insn "mmulfxrp_w"
11914   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11915         (ss_truncate:V4HI
11916          (ashiftrt:V4SI
11917           (plus:V4SI
11918            (mult:V4SI
11919             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
11920             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
11921            (const_int 16384))
11922           (const_int 15))))]
11923   "TARGET_SHMEDIA"
11924   "mmulfxrp.w   %1, %2, %0"
11925   [(set_attr "type" "dmpy_media")
11926    (set_attr "highpart" "depend")])
11927
11928
11929 (define_expand "mmulhi_wl"
11930   [(match_operand:V2SI 0 "arith_reg_dest" "")
11931    (match_operand:V4HI 1 "arith_reg_operand" "")
11932    (match_operand:V4HI 2 "arith_reg_operand" "")]
11933   "TARGET_SHMEDIA"
11934   "
11935 {
11936   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
11937              (operands[0], operands[1], operands[2]));
11938   DONE;
11939 }")
11940
11941 (define_expand "mmullo_wl"
11942   [(match_operand:V2SI 0 "arith_reg_dest" "")
11943    (match_operand:V4HI 1 "arith_reg_operand" "")
11944    (match_operand:V4HI 2 "arith_reg_operand" "")]
11945   "TARGET_SHMEDIA"
11946   "
11947 {
11948   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
11949              (operands[0], operands[1], operands[2]));
11950   DONE;
11951 }")
11952
11953 (define_insn "mmul23_wl"
11954   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11955         (vec_select:V2SI
11956          (mult:V4SI
11957           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
11958           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
11959          (parallel [(const_int 2) (const_int 3)])))]
11960   "TARGET_SHMEDIA"
11961   "* return (TARGET_LITTLE_ENDIAN
11962              ? \"mmulhi.wl      %1, %2, %0\"
11963              : \"mmullo.wl      %1, %2, %0\");"
11964   [(set_attr "type" "dmpy_media")
11965    (set (attr "highpart")
11966         (cond [(eq_attr "endian" "big") (const_string "ignore")]
11967          (const_string "user")))])
11968
11969 (define_insn "mmul01_wl"
11970   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11971         (vec_select:V2SI
11972          (mult:V4SI
11973           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
11974           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
11975          (parallel [(const_int 0) (const_int 1)])))]
11976   "TARGET_SHMEDIA"
11977   "* return (TARGET_LITTLE_ENDIAN
11978              ? \"mmullo.wl      %1, %2, %0\"
11979              : \"mmulhi.wl      %1, %2, %0\");"
11980   [(set_attr "type" "dmpy_media")
11981    (set (attr "highpart")
11982         (cond [(eq_attr "endian" "little") (const_string "ignore")]
11983          (const_string "user")))])
11984
11985
11986 (define_expand "mmulsum_wq"
11987   [(match_operand:DI 0 "arith_reg_dest" "")
11988    (match_operand:V4HI 1 "arith_reg_operand" "")
11989    (match_operand:V4HI 2 "arith_reg_operand" "")
11990    (match_operand:DI 3 "arith_reg_operand" "")]
11991   "TARGET_SHMEDIA"
11992   "
11993 {
11994   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
11995                                operands[1], operands[2]));
11996   DONE;
11997 }")
11998
11999 (define_insn "mmulsum_wq_i"
12000   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12001         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
12002          (plus:DI
12003           (plus:DI
12004            (vec_select:DI
12005             (mult:V4DI
12006              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
12007              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
12008             (parallel [(const_int 0)]))
12009            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12010                                      (sign_extend:V4DI (match_dup 3)))
12011                           (parallel [(const_int 1)])))
12012           (plus:DI
12013            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12014                                      (sign_extend:V4DI (match_dup 3)))
12015                           (parallel [(const_int 2)]))
12016            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12017                                      (sign_extend:V4DI (match_dup 3)))
12018                           (parallel [(const_int 3)]))))))]
12019   "TARGET_SHMEDIA"
12020   "mmulsum.wq   %2, %3, %0"
12021   [(set_attr "type" "mac_media")])
12022
12023 (define_expand "mperm_w"
12024   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
12025    (match_operand:V4HI 1 "arith_reg_operand" "r")
12026    (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
12027   "TARGET_SHMEDIA"
12028   "
12029 {
12030   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
12031              (operands[0], operands[1], operands[2]));
12032   DONE;
12033 }")
12034
12035 ; This use of vec_select isn't exactly correct according to rtl.texi
12036 ; (because not constant), but it seems a straightforward extension.
12037 (define_insn "mperm_w_little"
12038   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12039         (vec_select:V4HI
12040          (match_operand:V4HI 1 "arith_reg_operand" "r")
12041          (parallel
12042           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
12043                             (const_int 2) (const_int 0))
12044            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
12045            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
12046            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
12047   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
12048   "mperm.w      %1, %N2, %0"
12049   [(set_attr "type" "arith_media")])
12050
12051 (define_insn "mperm_w_big"
12052   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12053         (vec_select:V4HI
12054          (match_operand:V4HI 1 "arith_reg_operand" "r")
12055          (parallel
12056           [(zero_extract:QI (not:QI (match_operand:QI 2
12057                                      "extend_reg_or_0_operand" "rZ"))
12058                             (const_int 2) (const_int 0))
12059            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
12060            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
12061            (zero_extract:QI (not:QI (match_dup 2))
12062                             (const_int 2) (const_int 6))])))]
12063   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
12064   "mperm.w      %1, %N2, %0"
12065   [(set_attr "type" "arith_media")])
12066
12067 (define_insn "mperm_w0"
12068   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12069         (vec_duplicate:V4HI (truncate:HI (match_operand 1
12070                                           "trunc_hi_operand" "r"))))]
12071   "TARGET_SHMEDIA"
12072   "mperm.w      %1, r63, %0"
12073   [(set_attr "type" "arith_media")
12074    (set_attr "highpart" "ignore")])
12075
12076 (define_expand "msad_ubq"
12077   [(match_operand:DI 0 "arith_reg_dest" "")
12078    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
12079    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
12080    (match_operand:DI 3 "arith_reg_operand" "")]
12081   "TARGET_SHMEDIA"
12082   "
12083 {
12084   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
12085                              operands[1], operands[2]));
12086   DONE;
12087 }")
12088
12089 (define_insn "msad_ubq_i"
12090   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12091         (plus:DI
12092          (plus:DI
12093           (plus:DI
12094            (plus:DI
12095             (match_operand:DI 1 "arith_reg_operand" "0")
12096             (abs:DI (vec_select:DI
12097                      (minus:V8DI
12098                       (zero_extend:V8DI
12099                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12100                       (zero_extend:V8DI
12101                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
12102                      (parallel [(const_int 0)]))))
12103            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12104                                               (zero_extend:V8DI (match_dup 3)))
12105                                   (parallel [(const_int 1)]))))
12106           (plus:DI
12107            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12108                                               (zero_extend:V8DI (match_dup 3)))
12109                                   (parallel [(const_int 2)])))
12110            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12111                                               (zero_extend:V8DI (match_dup 3)))
12112                                   (parallel [(const_int 3)])))))
12113          (plus:DI
12114           (plus:DI
12115            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12116                                               (zero_extend:V8DI (match_dup 3)))
12117                                   (parallel [(const_int 4)])))
12118            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12119                                               (zero_extend:V8DI (match_dup 3)))
12120                                   (parallel [(const_int 5)]))))
12121           (plus:DI
12122            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12123                                               (zero_extend:V8DI (match_dup 3)))
12124                                   (parallel [(const_int 6)])))
12125            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12126                                               (zero_extend:V8DI (match_dup 3)))
12127                                   (parallel [(const_int 7)])))))))]
12128   "TARGET_SHMEDIA"
12129   "msad.ubq     %N2, %N3, %0"
12130   [(set_attr "type" "mac_media")])
12131
12132 (define_insn "mshalds_l"
12133   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12134         (ss_truncate:V2SI
12135          (ashift:V2DI
12136           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12137           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12138                   (const_int 31)))))]
12139   "TARGET_SHMEDIA"
12140   "mshalds.l    %1, %2, %0"
12141   [(set_attr "type" "mcmp_media")
12142    (set_attr "highpart" "depend")])
12143
12144 (define_insn "mshalds_w"
12145   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12146         (ss_truncate:V4HI
12147          (ashift:V4SI
12148           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12149           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12150                   (const_int 15)))))]
12151   "TARGET_SHMEDIA"
12152   "mshalds.w    %1, %2, %0"
12153   [(set_attr "type" "mcmp_media")
12154    (set_attr "highpart" "depend")])
12155
12156 (define_insn "ashrv2si3"
12157   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12158         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12159                        (match_operand:DI 2 "arith_reg_operand" "r")))]
12160   "TARGET_SHMEDIA"
12161   "mshard.l     %1, %2, %0"
12162   [(set_attr "type" "arith_media")
12163    (set_attr "highpart" "depend")])
12164
12165 (define_insn "ashrv4hi3"
12166   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12167         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12168                        (match_operand:DI 2 "arith_reg_operand" "r")))]
12169   "TARGET_SHMEDIA"
12170   "mshard.w     %1, %2, %0"
12171   [(set_attr "type" "arith_media")
12172    (set_attr "highpart" "depend")])
12173
12174 (define_insn "mshards_q"
12175   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
12176         (ss_truncate:HI
12177          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
12178                       (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
12179   "TARGET_SHMEDIA"
12180   "mshards.q    %1, %N2, %0"
12181   [(set_attr "type" "mcmp_media")])
12182
12183 (define_expand "mshfhi_b"
12184   [(match_operand:V8QI 0 "arith_reg_dest" "")
12185    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12186    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12187   "TARGET_SHMEDIA"
12188   "
12189 {
12190   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
12191              (operands[0], operands[1], operands[2]));
12192   DONE;
12193 }")
12194
12195 (define_expand "mshflo_b"
12196   [(match_operand:V8QI 0 "arith_reg_dest" "")
12197    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12198    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12199   "TARGET_SHMEDIA"
12200   "
12201 {
12202   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
12203              (operands[0], operands[1], operands[2]));
12204   DONE;
12205 }")
12206
12207 (define_insn "mshf4_b"
12208   [(set
12209     (match_operand:V8QI 0 "arith_reg_dest" "=r")
12210     (vec_select:V8QI
12211      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12212                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12213      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
12214                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
12215   "TARGET_SHMEDIA"
12216   "* return (TARGET_LITTLE_ENDIAN
12217              ? \"mshfhi.b       %N1, %N2, %0\"
12218              : \"mshflo.b       %N1, %N2, %0\");"
12219   [(set_attr "type" "arith_media")
12220    (set (attr "highpart")
12221         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12222          (const_string "user")))])
12223
12224 (define_insn "mshf0_b"
12225   [(set
12226     (match_operand:V8QI 0 "arith_reg_dest" "=r")
12227     (vec_select:V8QI
12228      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12229                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12230      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
12231                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
12232   "TARGET_SHMEDIA"
12233   "* return (TARGET_LITTLE_ENDIAN
12234              ? \"mshflo.b       %N1, %N2, %0\"
12235              : \"mshfhi.b       %N1, %N2, %0\");"
12236   [(set_attr "type" "arith_media")
12237    (set (attr "highpart")
12238         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12239          (const_string "user")))])
12240
12241 (define_expand "mshfhi_l"
12242   [(match_operand:V2SI 0 "arith_reg_dest" "")
12243    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12244    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12245   "TARGET_SHMEDIA"
12246   "
12247 {
12248   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
12249              (operands[0], operands[1], operands[2]));
12250   DONE;
12251 }")
12252
12253 (define_expand "mshflo_l"
12254   [(match_operand:V2SI 0 "arith_reg_dest" "")
12255    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12256    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12257   "TARGET_SHMEDIA"
12258   "
12259 {
12260   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
12261              (operands[0], operands[1], operands[2]));
12262   DONE;
12263 }")
12264
12265 (define_insn "mshf4_l"
12266   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12267         (vec_select:V2SI
12268          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12269                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12270          (parallel [(const_int 1) (const_int 3)])))]
12271   "TARGET_SHMEDIA"
12272   "* return (TARGET_LITTLE_ENDIAN
12273              ? \"mshfhi.l       %N1, %N2, %0\"
12274              : \"mshflo.l       %N1, %N2, %0\");"
12275   [(set_attr "type" "arith_media")
12276    (set (attr "highpart")
12277         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12278          (const_string "user")))])
12279
12280 (define_insn "mshf0_l"
12281   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12282         (vec_select:V2SI
12283          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12284                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12285          (parallel [(const_int 0) (const_int 2)])))]
12286   "TARGET_SHMEDIA"
12287   "* return (TARGET_LITTLE_ENDIAN
12288              ? \"mshflo.l       %N1, %N2, %0\"
12289              : \"mshfhi.l       %N1, %N2, %0\");"
12290   [(set_attr "type" "arith_media")
12291    (set (attr "highpart")
12292         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12293          (const_string "user")))])
12294
12295 (define_expand "mshfhi_w"
12296   [(match_operand:V4HI 0 "arith_reg_dest" "")
12297    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12298    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12299   "TARGET_SHMEDIA"
12300   "
12301 {
12302   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
12303              (operands[0], operands[1], operands[2]));
12304   DONE;
12305 }")
12306
12307 (define_expand "mshflo_w"
12308   [(match_operand:V4HI 0 "arith_reg_dest" "")
12309    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12310    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12311   "TARGET_SHMEDIA"
12312   "
12313 {
12314   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
12315              (operands[0], operands[1], operands[2]));
12316   DONE;
12317 }")
12318
12319 (define_insn "mshf4_w"
12320   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12321         (vec_select:V4HI
12322          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12323                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12324          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
12325   "TARGET_SHMEDIA"
12326   "* return (TARGET_LITTLE_ENDIAN
12327              ? \"mshfhi.w       %N1, %N2, %0\"
12328              : \"mshflo.w       %N1, %N2, %0\");"
12329   [(set_attr "type" "arith_media")
12330    (set (attr "highpart")
12331         (cond [(eq_attr "endian" "big") (const_string "ignore")]
12332          (const_string "user")))])
12333
12334 (define_insn "mshf0_w"
12335   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12336         (vec_select:V4HI
12337          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12338                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12339          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
12340   "TARGET_SHMEDIA"
12341   "* return (TARGET_LITTLE_ENDIAN
12342              ? \"mshflo.w       %N1, %N2, %0\"
12343              : \"mshfhi.w       %N1, %N2, %0\");"
12344   [(set_attr "type" "arith_media")
12345    (set (attr "highpart")
12346         (cond [(eq_attr "endian" "little") (const_string "ignore")]
12347          (const_string "user")))])
12348
12349 (define_insn "mshflo_w_x"
12350   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12351         (vec_select:V4HI
12352          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
12353                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
12354          (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
12355   "TARGET_SHMEDIA"
12356   "mshflo.w     %N1, %N2, %0"
12357   [(set_attr "type" "arith_media")
12358    (set_attr "highpart" "ignore")])
12359
12360 /* These are useful to expand ANDs and as combiner patterns.  */
12361 (define_insn_and_split "mshfhi_l_di"
12362   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
12363         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
12364                              (const_int 32))
12365                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
12366                         (const_int -4294967296))))]
12367   "TARGET_SHMEDIA"
12368   "@
12369         mshfhi.l        %N1, %N2, %0
12370         #"
12371   "TARGET_SHMEDIA && reload_completed
12372    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12373   [(set (match_dup 3) (match_dup 4))
12374    (set (match_dup 5) (match_dup 6))]
12375   "
12376 {
12377   operands[3] = gen_lowpart (SImode, operands[0]);
12378   operands[4] = gen_highpart (SImode, operands[1]);
12379   operands[5] = gen_highpart (SImode, operands[0]);
12380   operands[6] = gen_highpart (SImode, operands[2]);
12381 }"
12382   [(set_attr "type" "arith_media")])
12383
12384 (define_insn "*mshfhi_l_di_rev"
12385   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12386         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12387                         (const_int -4294967296))
12388                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12389                              (const_int 32))))]
12390   "TARGET_SHMEDIA"
12391   "mshfhi.l     %N2, %N1, %0"
12392   [(set_attr "type" "arith_media")])
12393
12394 (define_split
12395   [(set (match_operand:DI 0 "arith_reg_dest" "")
12396         (ior:DI (zero_extend:DI (match_operand:SI 1
12397                                               "extend_reg_or_0_operand" ""))
12398                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
12399                         (const_int -4294967296))))
12400    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
12401   "TARGET_SHMEDIA"
12402   [(const_int 0)]
12403   "
12404 {
12405   emit_insn (gen_ashldi3_media (operands[3],
12406                                 simplify_gen_subreg (DImode, operands[1],
12407                                                      SImode, 0),
12408                                 GEN_INT (32)));
12409   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
12410   DONE;
12411 }")
12412
12413 (define_insn "mshflo_l_di"
12414   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12415         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12416                         (const_int 4294967295))
12417                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12418                            (const_int 32))))]
12419
12420   "TARGET_SHMEDIA"
12421   "mshflo.l     %N1, %N2, %0"
12422   [(set_attr "type" "arith_media")
12423    (set_attr "highpart" "ignore")])
12424
12425 (define_insn "*mshflo_l_di_rev"
12426   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12427         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12428                            (const_int 32))
12429                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12430                         (const_int 4294967295))))]
12431
12432   "TARGET_SHMEDIA"
12433   "mshflo.l     %N2, %N1, %0"
12434   [(set_attr "type" "arith_media")
12435    (set_attr "highpart" "ignore")])
12436
12437 ;; Combiner pattern for trampoline initialization.
12438 (define_insn_and_split "*double_shori"
12439   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12440         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
12441                            (const_int 32))
12442                 (match_operand:DI 2 "const_int_operand" "n")))]
12443   "TARGET_SHMEDIA
12444    && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
12445   "#"
12446   "rtx_equal_p (operands[0], operands[1])"
12447   [(const_int 0)]
12448   "
12449 {
12450   HOST_WIDE_INT v = INTVAL (operands[2]);
12451
12452   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
12453   emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
12454   DONE;
12455 }"
12456   [(set_attr "highpart" "ignore")])
12457
12458
12459 (define_insn "*mshflo_l_di_x"
12460   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12461         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
12462                                  "rZ"))
12463                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12464                            (const_int 32))))]
12465
12466   "TARGET_SHMEDIA"
12467   "mshflo.l     %N1, %N2, %0"
12468   [(set_attr "type" "arith_media")
12469    (set_attr "highpart" "ignore")])
12470
12471 (define_insn_and_split "concat_v2sf"
12472   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
12473 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
12474         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
12475                          (match_operand:SF 2 "register_operand" "rZ,f,f")))]
12476
12477   "TARGET_SHMEDIA"
12478   "@
12479         mshflo.l        %N1, %N2, %0
12480         #
12481         #"
12482   "TARGET_SHMEDIA && reload_completed
12483    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12484   [(set (match_dup 3) (match_dup 1))
12485    (set (match_dup 4) (match_dup 2))]
12486   "
12487 {
12488   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
12489   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
12490 }"
12491   [(set_attr "type" "arith_media")
12492    (set_attr "highpart" "ignore")])
12493
12494 (define_insn "*mshflo_l_di_x_rev"
12495   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12496         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12497                            (const_int 32))
12498                 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
12499
12500   "TARGET_SHMEDIA"
12501   "mshflo.l     %N2, %N1, %0"
12502   [(set_attr "type" "arith_media")
12503    (set_attr "highpart" "ignore")])
12504
12505 (define_insn "ashlv2si3"
12506   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12507         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12508                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12509   "TARGET_SHMEDIA"
12510   "mshlld.l     %1, %2, %0"
12511   [(set_attr "type" "arith_media")
12512    (set_attr "highpart" "depend")])
12513
12514 (define_split
12515   [(set (match_operand 0 "any_register_operand" "")
12516         (match_operator 3 "shift_operator"
12517           [(match_operand 1 "any_register_operand" "")
12518            (match_operand 2 "shift_count_reg_operand" "")]))]
12519   "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
12520   [(set (match_dup 0) (match_dup 3))]
12521   "
12522 {
12523   rtx count = operands[2];
12524   enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
12525
12526   while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
12527          || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
12528          || GET_CODE (count) == TRUNCATE)
12529     count = XEXP (count, 0);
12530   inner_mode = GET_MODE (count);
12531   count = simplify_gen_subreg (outer_mode, count, inner_mode,
12532                                subreg_lowpart_offset (outer_mode, inner_mode));
12533   operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
12534                                 operands[1], count);
12535 }")
12536
12537 (define_insn "ashlv4hi3"
12538   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12539         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12540                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12541   "TARGET_SHMEDIA"
12542   "mshlld.w     %1, %2, %0"
12543   [(set_attr "type" "arith_media")
12544    (set_attr "highpart" "depend")])
12545
12546 (define_insn "lshrv2si3"
12547   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12548         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12549                      (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12550   "TARGET_SHMEDIA"
12551   "mshlrd.l     %1, %2, %0"
12552   [(set_attr "type" "arith_media")
12553    (set_attr "highpart" "depend")])
12554
12555 (define_insn "lshrv4hi3"
12556   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12557         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12558                        (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12559   "TARGET_SHMEDIA"
12560   "mshlrd.w     %1, %2, %0"
12561   [(set_attr "type" "arith_media")
12562    (set_attr "highpart" "depend")])
12563
12564 (define_insn "subv2si3"
12565   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12566         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12567                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12568   "TARGET_SHMEDIA"
12569   "msub.l       %N1, %2, %0"
12570   [(set_attr "type" "arith_media")
12571    (set_attr "highpart" "depend")])
12572
12573 (define_insn "subv4hi3"
12574   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12575         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12576                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12577   "TARGET_SHMEDIA"
12578   "msub.w       %N1, %2, %0"
12579   [(set_attr "type" "arith_media")
12580    (set_attr "highpart" "depend")])
12581
12582 (define_insn_and_split "subv2hi3"
12583   [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
12584         (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
12585                    (match_operand:V2HI 2 "arith_reg_operand" "r")))]
12586   "TARGET_SHMEDIA"
12587   "#"
12588   "TARGET_SHMEDIA"
12589   [(const_int 0)]
12590   "
12591 {
12592   rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
12593   rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
12594   rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
12595   rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
12596   rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
12597
12598   emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
12599   emit_insn (gen_truncdisi2 (si_dst, di_dst));
12600   DONE;
12601 }"
12602   [(set_attr "highpart" "must_split")])
12603
12604 (define_insn "sssubv2si3"
12605   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12606         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12607                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12608   "TARGET_SHMEDIA"
12609   "msubs.l      %N1, %2, %0"
12610   [(set_attr "type" "mcmp_media")
12611    (set_attr "highpart" "depend")])
12612
12613 (define_insn "ussubv8qi3"
12614   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12615         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12616                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
12617   "TARGET_SHMEDIA"
12618   "msubs.ub     %N1, %2, %0"
12619   [(set_attr "type" "mcmp_media")
12620    (set_attr "highpart" "depend")])
12621
12622 (define_insn "sssubv4hi3"
12623   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12624         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12625                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12626   "TARGET_SHMEDIA"
12627   "msubs.w      %N1, %2, %0"
12628   [(set_attr "type" "mcmp_media")
12629    (set_attr "highpart" "depend")])
12630
12631 ;; Floating Point Intrinsics
12632
12633 (define_insn "fcosa_s"
12634   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12635         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12636                    UNSPEC_FCOSA))]
12637   "TARGET_SHMEDIA"
12638   "fcosa.s      %1, %0"
12639   [(set_attr "type" "atrans_media")])
12640
12641 (define_insn "fsina_s"
12642   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12643         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12644                    UNSPEC_FSINA))]
12645   "TARGET_SHMEDIA"
12646   "fsina.s      %1, %0"
12647   [(set_attr "type" "atrans_media")])
12648
12649 (define_insn "fipr"
12650   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12651         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
12652                                                     "fp_arith_reg_operand" "f")
12653                                                    (match_operand:V4SF 2
12654                                                     "fp_arith_reg_operand" "f"))
12655                                          (parallel [(const_int 0)]))
12656                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12657                                          (parallel [(const_int 1)])))
12658                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12659                                          (parallel [(const_int 2)]))
12660                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12661                                          (parallel [(const_int 3)])))))]
12662   "TARGET_SHMEDIA"
12663   "fipr.s       %1, %2, %0"
12664   [(set_attr "type" "fparith_media")])
12665
12666 (define_insn "fsrra_s"
12667   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12668         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
12669                    UNSPEC_FSRRA))]
12670   "TARGET_SHMEDIA"
12671   "fsrra.s      %1, %0"
12672   [(set_attr "type" "atrans_media")])
12673
12674 (define_insn "ftrv"
12675   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
12676         (plus:V4SF
12677          (plus:V4SF
12678           (mult:V4SF
12679            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
12680                             (parallel [(const_int 0) (const_int 5)
12681                                        (const_int 10) (const_int 15)]))
12682            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
12683           (mult:V4SF
12684            (vec_select:V4SF (match_dup 1)
12685                             (parallel [(const_int 4) (const_int 9)
12686                                        (const_int 14) (const_int 3)]))
12687            (vec_select:V4SF (match_dup 2)
12688                             (parallel [(const_int 1) (const_int 2)
12689                                        (const_int 3) (const_int 0)]))))
12690          (plus:V4SF
12691           (mult:V4SF
12692            (vec_select:V4SF (match_dup 1)
12693                             (parallel [(const_int 8) (const_int 13)
12694                                        (const_int 2) (const_int 7)]))
12695            (vec_select:V4SF (match_dup 2)
12696                             (parallel [(const_int 2) (const_int 3)
12697                                        (const_int 0) (const_int 1)])))
12698           (mult:V4SF
12699            (vec_select:V4SF (match_dup 1)
12700                             (parallel [(const_int 12) (const_int 1)
12701                                        (const_int 6) (const_int 11)]))
12702            (vec_select:V4SF (match_dup 2)
12703                             (parallel [(const_int 3) (const_int 0)
12704                                        (const_int 1) (const_int 2)]))))))]
12705   "TARGET_SHMEDIA"
12706   "ftrv.s %1, %2, %0"
12707   [(set_attr "type" "fparith_media")])
12708
12709 (define_insn "ldhi_l"
12710   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12711         (zero_extract:SI
12712          (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12713                                   (const_int 3))
12714                           (const_int -3)))
12715          (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
12716          (const_int 0)))]
12717   "TARGET_SHMEDIA32"
12718   "ldhi.l       %U1, %0"
12719   [(set_attr "type" "load_media")])
12720
12721 (define_insn "ldhi_q"
12722   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12723         (zero_extract:DI
12724          (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12725                                   (const_int 7))
12726                           (const_int -7)))
12727          (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
12728          (const_int 0)))]
12729   "TARGET_SHMEDIA32"
12730   "ldhi.q       %U1, %0"
12731   [(set_attr "type" "load_media")])
12732
12733 (define_insn_and_split "*ldhi_q_comb0"
12734   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12735         (zero_extract:DI
12736          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12737                                             "register_operand" "r")
12738                                            (match_operand:SI 2
12739                                             "ua_offset" "I06"))
12740                                   (const_int 7))
12741                           (const_int -7)))
12742          (plus:SI (and:SI (match_dup 1) (const_int 7))
12743                   (const_int 1))
12744          (const_int 0)))]
12745   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12746   "#"
12747   ""
12748   [(pc)]
12749   "emit_insn (gen_ldhi_q (operands[0],
12750                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
12751    DONE;")
12752
12753
12754 (define_insn_and_split "*ldhi_q_comb1"
12755   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12756         (zero_extract:DI
12757          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12758                                             "register_operand" "r")
12759                                            (match_operand:SI 2
12760                                             "ua_offset" "I06"))
12761                                   (const_int 7))
12762                           (const_int -7)))
12763          (plus:SI (and:SI (plus:SI (match_dup 1)  (match_operand:SI 3
12764                                                    "ua_offset" "I06"))
12765                           (const_int 7))
12766                   (const_int 1))
12767          (const_int 0)))]
12768   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12769    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12770   "#"
12771   ""
12772   [(pc)]
12773   "emit_insn (gen_ldhi_q (operands[0],
12774                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
12775    DONE;")
12776
12777
12778 (define_insn "ldlo_l"
12779   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12780         (zero_extract:SI
12781          (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12782                          (const_int -4)))
12783          (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
12784          (and:SI (match_dup 1) (const_int 3))))]
12785   "TARGET_SHMEDIA32"
12786   "ldlo.l       %U1, %0"
12787   [(set_attr "type" "load_media")])
12788
12789 (define_insn "ldlo_q"
12790   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12791         (zero_extract:DI
12792          (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12793                          (const_int -8)))
12794          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12795          (and:SI (match_dup 1) (const_int 7))))]
12796   "TARGET_SHMEDIA32"
12797   "ldlo.q       %U1, %0"
12798   [(set_attr "type" "load_media")])
12799
12800 (define_insn_and_split "*ldlo_q_comb0"
12801   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12802         (zero_extract:DI
12803          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12804                                   (match_operand:SI 2 "ua_offset" "I06"))
12805                          (const_int -8)))
12806          (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12807          (and:SI (match_dup 1) (const_int 7))))]
12808   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12809   "#"
12810   ""
12811   [(pc)]
12812   "emit_insn (gen_ldlo_q (operands[0],
12813                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
12814    DONE;")
12815
12816 (define_insn_and_split "*ldlo_q_comb1"
12817   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12818         (zero_extract:DI
12819          (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12820                                   (match_operand:SI 2 "ua_offset" "I06"))
12821                          (const_int -8)))
12822          (minus:SI (const_int 8)
12823                    (and:SI (plus:SI (match_dup 1)
12824                                     (match_operand:SI 3 "ua_offset" "I06"))
12825                            (const_int 7)))
12826          (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
12827   "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12828    && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12829   "#"
12830   ""
12831   [(pc)]
12832   "emit_insn (gen_ldlo_q (operands[0],
12833                           gen_rtx_PLUS (SImode, operands[1], operands[2])));
12834    DONE;")
12835
12836 (define_insn "sthi_l"
12837   [(set (zero_extract:SI
12838          (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
12839                                   (const_int 3))
12840                           (const_int -3)))
12841          (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
12842          (const_int 0))
12843         (match_operand:SI 1 "arith_reg_operand" "r"))]
12844   "TARGET_SHMEDIA32"
12845   "sthi.l       %U0, %1"
12846   [(set_attr "type" "ustore_media")])
12847
12848 ;; All unaligned stores are considered to be 'narrow' because they typically
12849 ;; operate on less that a quadword, and when they operate on a full quadword,
12850 ;; the vanilla store high / store low sequence will cause a stall if not
12851 ;; scheduled apart.
12852 (define_insn "sthi_q"
12853   [(set (zero_extract:DI
12854          (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
12855                                   (const_int 7))
12856                           (const_int -7)))
12857          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
12858          (const_int 0))
12859         (match_operand:DI 1 "arith_reg_operand" "r"))]
12860   "TARGET_SHMEDIA32"
12861   "sthi.q       %U0, %1"
12862   [(set_attr "type" "ustore_media")])
12863
12864 (define_insn_and_split "*sthi_q_comb0"
12865   [(set (zero_extract:DI
12866          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
12867                                             "register_operand" "r")
12868                                            (match_operand:SI 1 "ua_offset"
12869                                             "I06"))
12870                                   (const_int 7))
12871                           (const_int -7)))
12872          (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
12873          (const_int 0))
12874         (match_operand:DI 2 "arith_reg_operand" "r"))]
12875   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
12876   "#"
12877   ""
12878   [(pc)]
12879   "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12880                           operands[2]));
12881    DONE;")
12882
12883 (define_insn_and_split "*sthi_q_comb1"
12884   [(set (zero_extract:DI
12885          (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
12886                                             "register_operand" "r")
12887                                            (match_operand:SI 1 "ua_offset"
12888                                             "I06"))
12889                                   (const_int 7))
12890                           (const_int -7)))
12891          (plus:SI (and:SI (plus:SI (match_dup 0)
12892                                    (match_operand:SI 2 "ua_offset" "I06"))
12893                           (const_int 7))
12894                   (const_int 1))
12895          (const_int 0))
12896         (match_operand:DI 3 "arith_reg_operand" "r"))]
12897   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
12898    && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
12899   "#"
12900   ""
12901   [(pc)]
12902   "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12903                           operands[3]));
12904    DONE;")
12905
12906 ;; This is highpart user because the address is used as full 64 bit.
12907 (define_insn "stlo_l"
12908   [(set (zero_extract:SI
12909          (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
12910                          (const_int -4)))
12911          (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
12912          (and:SI (match_dup 0) (const_int 3)))
12913         (match_operand:SI 1 "arith_reg_operand" "r"))]
12914   "TARGET_SHMEDIA32"
12915   "stlo.l       %U0, %1"
12916   [(set_attr "type" "ustore_media")])
12917
12918 (define_insn "stlo_q"
12919   [(set (zero_extract:DI
12920          (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
12921                          (const_int -8)))
12922          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
12923          (and:SI (match_dup 0) (const_int 7)))
12924         (match_operand:DI 1 "arith_reg_operand" "r"))]
12925   "TARGET_SHMEDIA32"
12926   "stlo.q       %U0, %1"
12927   [(set_attr "type" "ustore_media")])
12928
12929 (define_insn_and_split "*stlo_q_comb0"
12930   [(set (zero_extract:DI
12931          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
12932                                   (match_operand:SI 1 "ua_offset" "I06"))
12933                          (const_int -8)))
12934          (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
12935          (and:SI (match_dup 0) (const_int 7)))
12936         (match_operand:DI 2 "arith_reg_operand" "r"))]
12937   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
12938   "#"
12939   ""
12940   [(pc)]
12941   "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12942                           operands[2]));
12943    DONE;")
12944
12945 (define_insn_and_split "*stlo_q_comb1"
12946   [(set (zero_extract:DI
12947          (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
12948                                   (match_operand:SI 1 "ua_offset" "I06"))
12949                          (const_int -8)))
12950          (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
12951                                                   (match_operand:SI 2
12952                                                    "ua_offset" "I06"))
12953                                          (const_int 7)))
12954          (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
12955         (match_operand:DI 3 "arith_reg_operand" "r"))]
12956   "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
12957   "#"
12958   ""
12959   [(pc)]
12960   "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12961                           operands[3]));
12962    DONE;")
12963
12964 (define_insn "ldhi_l64"
12965   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12966         (zero_extract:SI
12967          (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
12968                                   (const_int 3))
12969                           (const_int -3)))
12970          (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
12971          (const_int 0)))]
12972   "TARGET_SHMEDIA64"
12973   "ldhi.l       %U1, %0"
12974   [(set_attr "type" "load_media")])
12975
12976 (define_insn "ldhi_q64"
12977   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12978         (zero_extract:DI
12979          (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
12980                                   (const_int 7))
12981                           (const_int -7)))
12982          (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
12983          (const_int 0)))]
12984   "TARGET_SHMEDIA64"
12985   "ldhi.q       %U1, %0"
12986   [(set_attr "type" "load_media")])
12987
12988 (define_insn "ldlo_l64"
12989   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12990         (zero_extract:SI
12991          (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
12992                          (const_int -4)))
12993          (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
12994          (and:DI (match_dup 1) (const_int 3))))]
12995   "TARGET_SHMEDIA64"
12996   "ldlo.l       %U1, %0"
12997   [(set_attr "type" "load_media")])
12998
12999 (define_insn "ldlo_q64"
13000   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13001         (zero_extract:DI
13002          (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13003                          (const_int -8)))
13004          (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
13005          (and:DI (match_dup 1) (const_int 7))))]
13006   "TARGET_SHMEDIA64"
13007   "ldlo.q       %U1, %0"
13008   [(set_attr "type" "load_media")])
13009
13010 (define_insn "sthi_l64"
13011   [(set (zero_extract:SI
13012          (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13013                                   (const_int 3))
13014                           (const_int -3)))
13015          (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
13016          (const_int 0))
13017         (match_operand:SI 1 "arith_reg_operand" "r"))]
13018   "TARGET_SHMEDIA64"
13019   "sthi.l       %U0, %1"
13020   [(set_attr "type" "ustore_media")])
13021
13022 (define_insn "sthi_q64"
13023   [(set (zero_extract:DI
13024          (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13025                                   (const_int 7))
13026                           (const_int -7)))
13027          (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
13028          (const_int 0))
13029         (match_operand:DI 1 "arith_reg_operand" "r"))]
13030   "TARGET_SHMEDIA64"
13031   "sthi.q       %U0, %1"
13032   [(set_attr "type" "ustore_media")])
13033
13034 (define_insn "stlo_l64"
13035   [(set (zero_extract:SI
13036          (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13037                          (const_int -4)))
13038          (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
13039          (and:DI (match_dup 0) (const_int 3)))
13040         (match_operand:SI 1 "arith_reg_operand" "r"))]
13041   "TARGET_SHMEDIA64"
13042   "stlo.l       %U0, %1"
13043   [(set_attr "type" "ustore_media")])
13044
13045 (define_insn "stlo_q64"
13046   [(set (zero_extract:DI
13047          (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13048                          (const_int -8)))
13049          (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
13050          (and:DI (match_dup 0) (const_int 7)))
13051         (match_operand:DI 1 "arith_reg_operand" "r"))]
13052   "TARGET_SHMEDIA64"
13053   "stlo.q       %U0, %1"
13054   [(set_attr "type" "ustore_media")])
13055
13056 (define_insn "nsb"
13057   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
13058         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13059                    UNSPEC_NSB))]
13060   "TARGET_SHMEDIA"
13061   "nsb  %1, %0"
13062   [(set_attr "type" "arith_media")])
13063
13064 (define_insn "nsbsi"
13065   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13066         (zero_extend:SI
13067          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13068                     UNSPEC_NSB)))]
13069   "TARGET_SHMEDIA"
13070   "nsb  %1, %0"
13071   [(set_attr "type" "arith_media")])
13072
13073 (define_insn "nsbdi"
13074   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13075         (zero_extend:DI
13076          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13077                     UNSPEC_NSB)))]
13078   "TARGET_SHMEDIA"
13079   "nsb  %1, %0"
13080   [(set_attr "type" "arith_media")])
13081
13082 (define_expand "ffsdi2"
13083   [(set (match_operand:DI 0 "arith_reg_dest" "")
13084         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
13085   "TARGET_SHMEDIA"
13086   "
13087 {
13088   rtx scratch = gen_reg_rtx (DImode);
13089   rtx last;
13090
13091   emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
13092   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
13093   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
13094   emit_insn (gen_nsbdi (scratch, scratch));
13095   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
13096   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
13097   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
13098   REG_NOTES (last)
13099     = gen_rtx_EXPR_LIST (REG_EQUAL,
13100                          gen_rtx_FFS (DImode, operands[0]), REG_NOTES (last));
13101   DONE;
13102 }")
13103
13104 (define_expand "ffssi2"
13105   [(set (match_operand:SI 0 "arith_reg_dest" "")
13106         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
13107   "TARGET_SHMEDIA"
13108   "
13109 {
13110   rtx scratch = gen_reg_rtx (SImode);
13111   rtx discratch = gen_reg_rtx (DImode);
13112   rtx last;
13113
13114   emit_insn (gen_adddi3 (discratch,
13115                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
13116                          constm1_rtx));
13117   emit_insn (gen_andcdi3 (discratch,
13118                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
13119                           discratch));
13120   emit_insn (gen_nsbsi (scratch, discratch));
13121   last = emit_insn (gen_subsi3 (operands[0],
13122                                 force_reg (SImode, GEN_INT (63)), scratch));
13123   REG_NOTES (last)
13124     = gen_rtx_EXPR_LIST (REG_EQUAL,
13125                          gen_rtx_FFS (SImode, operands[0]), REG_NOTES (last));
13126   DONE;
13127 }")
13128
13129 (define_insn "byterev"
13130   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13131         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
13132                          (parallel [(const_int 7) (const_int 6) (const_int 5)
13133                                     (const_int 4) (const_int 3) (const_int 2)
13134                                     (const_int 1) (const_int 0)])))]
13135   "TARGET_SHMEDIA"
13136   "byterev      %1, %0"
13137   [(set_attr "type" "arith_media")])
13138
13139 (define_insn "*prefetch_media"
13140   [(prefetch (match_operand:QI 0 "address_operand" "p")
13141              (match_operand:SI 1 "const_int_operand" "n")
13142              (match_operand:SI 2 "const_int_operand" "n"))]
13143   "TARGET_SHMEDIA"
13144   "*
13145 {
13146   operands[0] = gen_rtx_MEM (QImode, operands[0]);
13147   output_asm_insn (\"ld%M0.b    %m0,r63\", operands);
13148   return \"\";
13149 }"
13150   [(set_attr "type" "other")])
13151
13152 (define_insn "*prefetch_i4"
13153   [(prefetch (match_operand:SI 0 "register_operand" "r")
13154              (match_operand:SI 1 "const_int_operand" "n")
13155              (match_operand:SI 2 "const_int_operand" "n"))]
13156   "TARGET_HARD_SH4 || TARGET_SHCOMPACT"
13157   "*
13158 {
13159   return \"pref @%0\";
13160 }"
13161   [(set_attr "type" "other")])
13162
13163 (define_expand "prefetch"
13164   [(prefetch (match_operand 0 "address_operand" "p")
13165              (match_operand:SI 1 "const_int_operand" "n")
13166              (match_operand:SI 2 "const_int_operand" "n"))]
13167   "TARGET_HARD_SH4 || TARGET_SH5"
13168   "
13169 {
13170   if (GET_MODE (operands[0]) != Pmode
13171       || GET_CODE (operands[1]) != CONST_INT
13172       || GET_CODE (operands[2]) != CONST_INT)
13173     FAIL;
13174   if (! TARGET_SHMEDIA)
13175     operands[0] = force_reg (Pmode, operands[0]);
13176 }")
13177
13178 (define_insn "alloco_i"
13179   [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
13180         (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
13181   "TARGET_SHMEDIA32"
13182   "*
13183 {
13184   rtx xops[2];
13185
13186   if (GET_CODE (operands[0]) == PLUS)
13187     {
13188       xops[0] = XEXP (operands[0], 0);
13189       xops[1] = XEXP (operands[0], 1);
13190     }
13191   else
13192     {
13193       xops[0] = operands[0];
13194       xops[1] = const0_rtx;
13195     }
13196   output_asm_insn (\"alloco   %0, %1\", xops);
13197   return \"\";
13198 }"
13199   [(set_attr "type" "other")])
13200
13201 (define_split
13202   [(set (match_operand 0 "any_register_operand" "")
13203         (match_operand 1 "" ""))]
13204   "TARGET_SHMEDIA && reload_completed"
13205   [(set (match_dup 0) (match_dup 1))]
13206   "
13207 {
13208   int n_changes = 0;
13209
13210   for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
13211   if (!n_changes)
13212     FAIL;
13213 }")
13214
13215 ; Stack Protector Patterns
13216
13217 (define_expand "stack_protect_set"
13218   [(set (match_operand 0 "memory_operand" "")
13219         (match_operand 1 "memory_operand" ""))]
13220   ""
13221 {
13222   if (TARGET_SHMEDIA)
13223     {
13224       if (TARGET_SHMEDIA64)
13225         emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
13226       else
13227         emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
13228     }
13229   else
13230     emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
13231
13232   DONE;
13233 })
13234
13235 (define_insn "stack_protect_set_si"
13236   [(set (match_operand:SI 0 "memory_operand" "=m")
13237         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13238    (set (match_scratch:SI 2 "=&r") (const_int 0))]
13239   "!TARGET_SHMEDIA"
13240   "mov.l\t%1, %2\;mov.l\t%2, %0\;mov\t#0, %2"
13241   [(set_attr "type" "other")
13242    (set_attr "length" "6")])
13243
13244 (define_insn "stack_protect_set_si_media"
13245   [(set (match_operand:SI 0 "memory_operand" "=m")
13246         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13247    (set (match_scratch:SI 2 "=&r") (const_int 0))]
13248   "TARGET_SHMEDIA"
13249   "ld%M1.l\t%m1, %2\;st%M0.l\t%m0, %2\;movi\t0, %2"
13250   [(set_attr "type" "other")
13251    (set_attr "length" "12")])
13252
13253 (define_insn "stack_protect_set_di_media"
13254   [(set (match_operand:DI 0 "memory_operand" "=m")
13255         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13256    (set (match_scratch:DI 2 "=&r") (const_int 0))]
13257   "TARGET_SHMEDIA64"
13258   "ld%M1.q\t%m1, %2\;st%M0.q\t%m0, %2\;movi\t0, %2"
13259   [(set_attr "type" "other")
13260    (set_attr "length" "12")])
13261
13262 (define_expand "stack_protect_test"
13263   [(match_operand 0 "memory_operand" "")
13264    (match_operand 1 "memory_operand" "")
13265    (match_operand 2 "" "")]
13266   ""
13267 {
13268   if (TARGET_SHMEDIA)
13269     {
13270       rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
13271
13272       if (TARGET_SHMEDIA64)
13273         emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
13274                                                     operands[1]));
13275       else
13276         emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
13277                                                     operands[1]));
13278
13279       emit_jump_insn (gen_bne_media (operands[2], tmp, const0_rtx));
13280     }
13281   else
13282     {
13283       emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
13284       emit_jump_insn (gen_branch_true (operands[2]));
13285     }
13286
13287   DONE;
13288 })
13289
13290 (define_insn "stack_protect_test_si"
13291   [(set (reg:SI T_REG)
13292         (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
13293                     (match_operand:SI 1 "memory_operand" "m")]
13294                    UNSPEC_SP_TEST))
13295   (set (match_scratch:SI 2 "=&r") (const_int 0))
13296   (set (match_scratch:SI 3 "=&r") (const_int 0))]
13297   "!TARGET_SHMEDIA"
13298   "mov.l\t%0, %2\;mov.l\t%1, %3\;cmp/eq\t%2, %3\;mov\t#0, %2\;mov\t#0, %3"
13299   [(set_attr "type" "other")
13300    (set_attr "length" "10")])
13301
13302 (define_insn "stack_protect_test_si_media"
13303   [(set (match_operand:SI 0 "register_operand" "=&r")
13304         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
13305                     (match_operand:SI 2 "memory_operand" "m")]
13306                    UNSPEC_SP_TEST))
13307   (set (match_scratch:SI 3 "=&r") (const_int 0))]
13308   "TARGET_SHMEDIA"
13309   "ld%M1.l\t%m1, %0\;ld%M2.l\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13310   [(set_attr "type" "other")
13311    (set_attr "length" "16")])
13312
13313 (define_insn "stack_protect_test_di_media"
13314   [(set (match_operand:DI 0 "register_operand" "=&r")
13315         (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
13316                     (match_operand:DI 2 "memory_operand" "m")]
13317                    UNSPEC_SP_TEST))
13318   (set (match_scratch:DI 3 "=&r") (const_int 0))]
13319   "TARGET_SHMEDIA64"
13320   "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13321   [(set_attr "type" "other")
13322    (set_attr "length" "16")])