OSDN Git Service

2002-12-06 Dhananjay Deshpande <dhananjayd@kpit.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.md
1 ;;- Machine description for Hitachi / SuperH SH.
2 ;;  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
3 ;;  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 GNU CC.
8
9 ;; GNU CC 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 ;; GNU CC 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 GNU CC; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24
25 ;; ??? Should prepend a * to all pattern names which are not used.
26 ;; This will make the compiler smaller, and rebuilds after changes faster.
27
28 ;; ??? Should be enhanced to include support for many more GNU superoptimizer
29 ;; sequences.  Especially the sequences for arithmetic right shifts.
30
31 ;; ??? Should check all DImode patterns for consistency and usefulness.
32
33 ;; ??? The MAC.W and MAC.L instructions are not supported.  There is no
34 ;; way to generate them.
35
36 ;; ??? The cmp/str instruction is not supported.  Perhaps it can be used
37 ;; for a str* inline function.
38
39 ;; BSR is not generated by the compiler proper, but when relaxing, it
40 ;; generates .uses pseudo-ops that allow linker relaxation to create
41 ;; BSR.  This is actually implemented in bfd/{coff,elf32}-sh.c
42
43 ;; Special constraints for SH machine description:
44 ;;
45 ;;    t -- T
46 ;;    x -- mac
47 ;;    l -- pr
48 ;;    z -- r0
49 ;;
50 ;; Special formats used for outputting SH instructions:
51 ;;
52 ;;   %.  --  print a .s if insn needs delay slot
53 ;;   %@  --  print rte/rts if is/isn't an interrupt function
54 ;;   %#  --  output a nop if there is nothing to put in the delay slot
55 ;;   %O  --  print a constant without the #
56 ;;   %R  --  print the lsw reg of a double
57 ;;   %S  --  print the msw reg of a double
58 ;;   %T  --  print next word of a double REG or MEM
59 ;;
60 ;; Special predicates:
61 ;;
62 ;;  arith_operand          -- operand is valid source for arithmetic op
63 ;;  arith_reg_operand      -- operand is valid register for arithmetic op
64 ;;  general_movdst_operand -- operand is valid move destination
65 ;;  general_movsrc_operand -- operand is valid move source
66 ;;  logical_operand        -- operand is valid source for logical op
67
68 ;; -------------------------------------------------------------------------
69 ;; Constants
70 ;; -------------------------------------------------------------------------
71
72 (define_constants [
73   (AP_REG       145)
74   (PR_REG       146)
75   (T_REG        147)
76   (GBR_REG      144)
77   (MACH_REG     148)
78   (MACL_REG     149)
79   (FPUL_REG     150)
80   (RAP_REG      152)
81
82   (FPSCR_REG    151)
83
84   (PIC_REG      12)
85   (FP_REG       14)
86   (SP_REG       15)
87
88   (PR_MEDIA_REG 18)
89   (T_MEDIA_REG  19)
90
91   (R0_REG       0)
92   (R1_REG       1)
93   (R2_REG       2)
94   (R3_REG       3)
95   (R4_REG       4)
96   (R5_REG       5)
97   (R6_REG       6)
98   (R7_REG       7)
99   (R8_REG       8)
100   (R9_REG       9)
101   (R10_REG      10)
102   (R20_REG      20)
103   (R21_REG      21)
104   (R22_REG      22)
105   (R23_REG      23)
106
107   (DR0_REG      64)
108   (DR2_REG      66)
109   (DR4_REG      68)
110   (FR23_REG     87)
111
112   (TR0_REG      128)
113   (TR1_REG      129)
114   (TR2_REG      130)
115
116   (XD0_REG      136)
117
118   ;; These are used with unspec.
119   (UNSPEC_COMPACT_ARGS  0)
120   (UNSPEC_MOVA          1)
121   (UNSPEC_CASESI        2)
122   (UNSPEC_DATALABEL     3)
123   (UNSPEC_BBR           4)
124   (UNSPEC_SFUNC         5)
125   (UNSPEC_PIC           6)
126   (UNSPEC_GOT           7)
127   (UNSPEC_GOTOFF        8)
128   (UNSPEC_PLT           9)
129   (UNSPEC_CALLER        10)
130   (UNSPEC_GOTPLT        11)
131   (UNSPEC_ICACHE        12)
132   (UNSPEC_INIT_TRAMP    13)
133   (UNSPEC_FCOSA         14)
134   (UNSPEC_FSRRA         15)
135   (UNSPEC_FSINA         16)
136   (UNSPEC_NSB           17)
137   (UNSPEC_ALLOCO        18)
138
139   ;; These are used with unspec_volatile.
140   (UNSPECV_BLOCKAGE     0)
141   (UNSPECV_ALIGN        1)
142   (UNSPECV_CONST2       2)
143   (UNSPECV_CONST4       4)
144   (UNSPECV_CONST8       6)
145   (UNSPECV_WINDOW_END   10)
146   (UNSPECV_CONST_END    11)
147 ])  
148
149 ;; -------------------------------------------------------------------------
150 ;; Attributes
151 ;; -------------------------------------------------------------------------
152
153 ;; Target CPU.
154
155 (define_attr "cpu"
156  "sh1,sh2,sh3,sh3e,sh4,sh5"
157   (const (symbol_ref "sh_cpu_attr")))
158
159 (define_attr "endian" "big,little"
160  (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
161                       (const_string "little") (const_string "big"))))
162
163 ;; Indicate if the default fpu mode is single precision.
164 (define_attr "fpu_single" "yes,no"
165   (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
166                          (const_string "yes") (const_string "no"))))
167
168 (define_attr "fmovd" "yes,no"
169   (const (if_then_else (symbol_ref "TARGET_FMOVD")
170                        (const_string "yes") (const_string "no"))))
171 ;; pipeline model
172 (define_attr "pipe_model" "sh1,sh4,sh5media"
173   (const
174    (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
175           (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
176          (const_string "sh1"))))
177
178 ;; cbranch      conditional branch instructions
179 ;; jump         unconditional jumps
180 ;; arith        ordinary arithmetic
181 ;; arith3       a compound insn that behaves similarly to a sequence of
182 ;;              three insns of type arith
183 ;; arith3b      like above, but might end with a redirected branch
184 ;; load         from memory
185 ;; load_si      Likewise, SImode variant for general register.
186 ;; fload        Likewise, but load to fp register.
187 ;; store        to memory
188 ;; move         general purpose register to register
189 ;; mt_group     other sh4 mt instructions
190 ;; fmove        register to register, floating point
191 ;; smpy         word precision integer multiply
192 ;; dmpy         longword or doublelongword precision integer multiply
193 ;; return       rts
194 ;; pload        load of pr reg, which can't be put into delay slot of rts
195 ;; prset        copy register to pr reg, ditto
196 ;; pstore       store of pr reg, which can't be put into delay slot of jsr
197 ;; prget        copy pr to register, ditto
198 ;; pcload       pc relative load of constant value
199 ;; pcfload      Likewise, but load to fp register.
200 ;; pcload_si    Likewise, SImode variant for general register.
201 ;; rte          return from exception
202 ;; sfunc        special function call with known used registers
203 ;; call         function call
204 ;; fp           floating point
205 ;; fdiv         floating point divide (or square root)
206 ;; gp_fpul      move from general purpose register to fpul
207 ;; fpul_gp      move from fpul to general purpose register
208 ;; mac_gp       move from mac[lh] to general purpose register
209 ;; dfp_arith, dfp_cmp,dfp_conv
210 ;; ftrc_s       fix_truncsfsi2_i4
211 ;; dfdiv        double precision floating point divide (or square root)
212 ;; cwb          ic_invalidate_line_i
213 ;; arith_media  SHmedia arithmetic, logical, and shift instructions
214 ;; cbranch_media SHmedia conditional branch instructions
215 ;; cmp_media    SHmedia compare instructions
216 ;; dfdiv_media  SHmedia double precision divide and square root
217 ;; dfmul_media  SHmedia double precision multiply instruction
218 ;; dfparith_media SHmedia double precision floating point arithmetic
219 ;; dfpconv_media SHmedia double precision floating point conversions
220 ;; dmpy_media   SHmedia longword multiply
221 ;; fcmp_media   SHmedia floating point compare instructions
222 ;; fdiv_media   SHmedia single precision divide and square root
223 ;; fload_media  SHmedia floating point register load instructions
224 ;; fmove_media  SHmedia floating point register moves (inc. fabs and fneg)
225 ;; fparith_media SHmedia single precision floating point arithmetic
226 ;; fpconv_media SHmedia single precision floating point conversions
227 ;; fstore_media SHmedia floating point register store instructions
228 ;; gettr_media  SHmedia gettr instruction
229 ;; invalidate_line_media SHmedia invaldiate_line sequence
230 ;; jump_media   SHmedia unconditional branch instructions
231 ;; load_media   SHmedia general register load instructions
232 ;; pt_media     SHmedia pt instruction (expanded by assembler)
233 ;; ptabs_media  SHmedia ptabs instruction
234 ;; store_media  SHmedia general register store instructions
235 ;; mcmp_media   SHmedia multimedia compare, absolute, saturating ops
236 ;; mac_media    SHmedia mac-style fixed point operations
237 ;; d2mpy_media  SHmedia: two 32 bit integer multiplies
238 ;; atrans       SHmedia approximate transcendential functions
239 ;; ustore_media SHmedia unaligned stores
240 ;; nil          no-op move, will be deleted.
241
242 (define_attr "type"
243  "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,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"
244   (const_string "other"))
245
246 ;; We define a new attribute namely "insn_class".We use
247 ;; this for the DFA based pipeline description.
248 ;;
249 ;; mt_group      SH4 "mt" group instructions.
250 ;;
251 ;; ex_group      SH4 "ex" group instructions.
252 ;;
253 ;; ls_group      SH4 "ls" group instructions.
254 ;;
255
256 (define_attr "insn_class"
257   "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
258   (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
259          (eq_attr "type" "arith,dyn_shift") (const_string "ex_group")
260          (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,gp_fpul,fpul_gp") (const_string "ls_group")
261          (eq_attr "type" "cbranch,jump") (const_string "br_group")
262          (eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
263            (const_string "fe_group")
264          (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")]
265         (const_string "none")))
266 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
267 ;; so these do not belong in an insn group, although they are modeled
268 ;; with their own define_insn_reservations.
269
270 ;; Indicate what precision must be selected in fpscr for this insn, if any.
271
272 (define_attr "fp_mode" "single,double,none" (const_string "none"))
273
274 ; If a conditional branch destination is within -252..258 bytes away
275 ; from the instruction it can be 2 bytes long.  Something in the
276 ; range -4090..4100 bytes can be 6 bytes long.  All other conditional
277 ; branches are initially assumed to be 16 bytes long.
278 ; In machine_dependent_reorg, we split all branches that are longer than
279 ; 2 bytes.
280
281 ;; The maximum range used for SImode constant pool entries is 1018.  A final
282 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
283 ;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
284 ;; instruction around the pool table, 2 bytes of alignment before the table,
285 ;; and 30 bytes of alignment after the table.  That gives a maximum total
286 ;; pool size of 1058 bytes.
287 ;; Worst case code/pool content size ratio is 1:2 (using asms).
288 ;; Thus, in the worst case, there is one instruction in front of a maximum
289 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
290 ;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
291 ;; If we have a forward branch, the initial table will be put after the
292 ;; unconditional branch.
293 ;;
294 ;; ??? We could do much better by keeping track of the actual pcloads within
295 ;; the branch range and in the pcload range in front of the branch range.
296
297 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
298 ;; inside an le.
299 (define_attr "short_cbranch_p" "no,yes"
300   (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
301          (const_string "no")
302          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
303          (const_string "yes")
304          (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
305          (const_string "no")
306          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
307          (const_string "yes")
308          ] (const_string "no")))
309
310 (define_attr "med_branch_p" "no,yes"
311   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
312               (const_int 1988))
313          (const_string "yes")
314          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
315          (const_string "no")
316          (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
317               (const_int 8186))
318          (const_string "yes")
319          ] (const_string "no")))
320
321 (define_attr "med_cbranch_p" "no,yes"
322   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
323               (const_int 1986))
324          (const_string "yes")
325          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
326          (const_string "no")
327          (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
328                (const_int 8184))
329          (const_string "yes")
330          ] (const_string "no")))
331
332 (define_attr "braf_branch_p" "no,yes"
333   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
334          (const_string "no")
335          (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
336               (const_int 20660))
337          (const_string "yes")
338          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
339          (const_string "no")
340          (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
341               (const_int 65530))
342          (const_string "yes")
343          ] (const_string "no")))
344
345 (define_attr "braf_cbranch_p" "no,yes"
346   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
347          (const_string "no")
348          (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
349               (const_int 20658))
350          (const_string "yes")
351          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
352          (const_string "no")
353          (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
354               (const_int 65528))
355          (const_string "yes")
356          ] (const_string "no")))
357
358 ; An unconditional jump in the range -4092..4098 can be 2 bytes long.
359 ; For wider ranges, we need a combination of a code and a data part.
360 ; If we can get a scratch register for a long range jump, the code
361 ; part can be 4 bytes long; otherwise, it must be 8 bytes long.
362 ; If the jump is in the range -32764..32770, the data part can be 2 bytes
363 ; long; otherwise, it must be 6 bytes long.
364
365 ; All other instructions are two bytes long by default.
366
367 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
368 ;; but getattrtab doesn't understand this.
369 (define_attr "length" ""
370   (cond [(eq_attr "type" "cbranch")
371          (cond [(eq_attr "short_cbranch_p" "yes")
372                 (const_int 2)
373                 (eq_attr "med_cbranch_p" "yes")
374                 (const_int 6)
375                 (eq_attr "braf_cbranch_p" "yes")
376                 (const_int 12)
377 ;; ??? using pc is not computed transitively.
378                 (ne (match_dup 0) (match_dup 0))
379                 (const_int 14)
380                 (ne (symbol_ref ("flag_pic")) (const_int 0))
381                 (const_int 24)
382                 ] (const_int 16))
383          (eq_attr "type" "jump")
384          (cond [(eq_attr "med_branch_p" "yes")
385                 (const_int 2)
386                 (and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))")
387                          (symbol_ref "INSN"))
388                      (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))")
389                          (symbol_ref "code_for_indirect_jump_scratch")))
390                 (if_then_else (eq_attr "braf_branch_p" "yes")
391                               (const_int 6)
392                               (const_int 10))
393                 (eq_attr "braf_branch_p" "yes")
394                 (const_int 10)
395 ;; ??? using pc is not computed transitively.
396                 (ne (match_dup 0) (match_dup 0))
397                 (const_int 12)
398                 (ne (symbol_ref ("flag_pic")) (const_int 0))
399                 (const_int 22)
400                 ] (const_int 14))
401          (eq_attr "type" "pt_media")
402          (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
403                        (const_int 20) (const_int 12))
404          ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
405                          (const_int 4)
406                          (const_int 2))))
407
408 ;; (define_function_unit {name} {num-units} {n-users} {test}
409 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
410
411 ;; Load and store instructions save a cycle if they are aligned on a
412 ;; four byte boundary.  Using a function unit for stores encourages
413 ;; gcc to separate load and store instructions by one instruction,
414 ;; which makes it more likely that the linker will be able to word
415 ;; align them when relaxing.
416
417 ;; Loads have a latency of two.
418 ;; However, call insns can have a delay slot, so that we want one more
419 ;; insn to be scheduled between the load of the function address and the call.
420 ;; This is equivalent to a latency of three.
421 ;; We cannot use a conflict list for this, because we need to distinguish
422 ;; between the actual call address and the function arguments.
423 ;; ADJUST_COST can only properly handle reductions of the cost, so we
424 ;; use a latency of three here.
425 ;; We only do this for SImode loads of general registers, to make the work
426 ;; for ADJUST_COST easier.
427 (define_function_unit "memory" 1 0
428   (and (eq_attr "pipe_model" "sh1")
429        (eq_attr "type" "load_si,pcload_si"))
430   3 2)
431 (define_function_unit "memory" 1 0
432   (and (eq_attr "pipe_model" "sh1")
433        (eq_attr "type" "load,pcload,pload,store,pstore"))
434   2 2)
435
436 (define_function_unit "int"    1 0
437   (and (eq_attr "pipe_model" "sh1") (eq_attr "type" "arith3,arith3b")) 3 3)
438
439 (define_function_unit "int"    1 0
440   (and (eq_attr "pipe_model" "sh1") (eq_attr "type" "dyn_shift")) 2 2)
441
442 (define_function_unit "int"    1 0
443   (and (eq_attr "pipe_model" "sh1") (eq_attr "type" "!arith3,arith3b,dyn_shift")) 1 1)
444
445 ;; ??? These are approximations.
446 (define_function_unit "mpy"    1 0
447   (and (eq_attr "pipe_model" "sh1") (eq_attr "type" "smpy")) 2 2)
448 (define_function_unit "mpy"    1 0
449   (and (eq_attr "pipe_model" "sh1") (eq_attr "type" "dmpy")) 3 3)
450
451 (define_function_unit "fp"     1 0
452   (and (eq_attr "pipe_model" "sh1") (eq_attr "type" "fp,fmove")) 2 1)
453 (define_function_unit "fp"     1 0
454   (and (eq_attr "pipe_model" "sh1") (eq_attr "type" "fdiv")) 13 12)
455
456
457 ;; SH-5 SHmedia scheduling
458 ;; When executing SHmedia code, the SH-5 is a fairly straightforward
459 ;; single-issue machine.  It has four pipelines, the branch unit (br),
460 ;; the integer and multimedia unit (imu), the load/store unit (lsu), and
461 ;; the floating point unit (fpu).
462 ;; Here model the instructions with a latency greater than one cycle.
463
464 ;; Every instruction on SH-5 occupies the issue resource for at least one
465 ;; cycle.
466 (define_function_unit "sh5issue" 1 0
467   (and (eq_attr "pipe_model" "sh5media")
468        (eq_attr "type" "!pt_media,ptabs_media,invalidate_line_media,dmpy_media,load_media,fload_media,fcmp_media,fmove_media,fparith_media,dfparith_media,fpconv_media,dfpconv_media,dfmul_media,store_media,fstore_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media")) 1 1)
469
470 ;; Specify the various types of instruction which have latency > 1
471 (define_function_unit "sh5issue" 1 0
472   (and (eq_attr "pipe_model" "sh5media")
473        (eq_attr "type" "mcmp_media")) 2 1)
474
475 (define_function_unit "sh5issue" 1 0
476   (and (eq_attr "pipe_model" "sh5media")
477        (eq_attr "type" "dmpy_media,load_media,fcmp_media,mac_media")) 3 1)
478 ;; but see sh_adjust_cost for mac_media exception.
479
480 (define_function_unit "sh5issue" 1 0
481   (and (eq_attr "pipe_model" "sh5media")
482        (eq_attr "type" "fload_media,fmove_media")) 4 1)
483
484 (define_function_unit "sh5issue" 1 0
485   (and (eq_attr "pipe_model" "sh5media")
486        (eq_attr "type" "d2mpy_media")) 4 2)
487
488 (define_function_unit "sh5issue" 1 0
489   (and (eq_attr "pipe_model" "sh5media")
490        (eq_attr "type" "pt_media,ptabs_media")) 5 1)
491
492 (define_function_unit "sh5issue" 1 0
493   (and (eq_attr "pipe_model" "sh5media")
494        (eq_attr "type" "fparith_media,dfparith_media,fpconv_media,dfpconv_media")) 6 1)
495
496 (define_function_unit "sh5issue" 1 0
497   (and (eq_attr "pipe_model" "sh5media")
498        (eq_attr "type" "invalidate_line_media")) 7 7)
499
500 (define_function_unit "sh5issue" 1 0
501   (and (eq_attr "pipe_model" "sh5media") (eq_attr "type" "dfmul_media")) 9 4)
502
503 (define_function_unit "sh5issue" 1 0
504   (and (eq_attr "pipe_model" "sh5media") (eq_attr "type" "atrans_media")) 10 5)
505
506 ;; Floating-point divide and square-root occupy an additional resource,
507 ;; which is not internally pipelined.  However, other instructions
508 ;; can continue to issue.
509 (define_function_unit "sh5fds" 1 0
510   (and (eq_attr "pipe_model" "sh5media") (eq_attr "type" "fdiv_media"))  19 19)
511
512 (define_function_unit "sh5fds" 1 0
513   (and (eq_attr "pipe_model" "sh5media") (eq_attr "type" "dfdiv_media")) 35 35)
514
515 ; Definitions for filling branch delay slots.
516
517 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
518
519 ;; ??? This should be (nil) instead of (const_int 0)
520 (define_attr "hit_stack" "yes,no"
521         (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
522                    (const_int 0))
523                (const_string "no")]
524               (const_string "yes")))
525
526 (define_attr "interrupt_function" "no,yes"
527   (const (symbol_ref "current_function_interrupt")))
528
529 (define_attr "in_delay_slot" "yes,no"
530   (cond [(eq_attr "type" "cbranch") (const_string "no")
531          (eq_attr "type" "pcload,pcload_si") (const_string "no")
532          (eq_attr "needs_delay_slot" "yes") (const_string "no")
533          (eq_attr "length" "2") (const_string "yes")
534          ] (const_string "no")))
535
536 (define_attr "cond_delay_slot" "yes,no"
537   (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
538          ] (const_string "no")))
539
540 (define_attr "is_sfunc" ""
541   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
542
543 (define_attr "is_mac_media" ""
544   (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
545
546 (define_attr "branch_zero" "yes,no"
547   (cond [(eq_attr "type" "!cbranch") (const_string "no")
548          (ne (symbol_ref "(next_active_insn (insn)\
549                            == (prev_active_insn\
550                                (XEXP (SET_SRC (PATTERN (insn)), 1))))\
551                           && get_attr_length (next_active_insn (insn)) == 2")
552              (const_int 0))
553          (const_string "yes")]
554         (const_string "no")))
555
556 ;; SH4 Double-precision computation with double-precision result -
557 ;; the two halves are ready at different times.
558 (define_attr "dfp_comp" "yes,no"
559   (cond [(eq_attr "type" "dfp_arith,dfp_conv,dfdiv") (const_string "yes")]
560         (const_string "no")))
561
562 ;; Insns for which the latency of a preceding fp insn is decreased by one.
563 (define_attr "late_fp_use" "yes,no" (const_string "no"))
564 ;; And feeding insns for which this relevant.
565 (define_attr "any_fp_comp" "yes,no"
566   (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
567          (const_string "yes")]
568         (const_string "no")))
569
570 (define_attr "any_int_load" "yes,no"
571   (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
572          (const_string "yes")]
573         (const_string "no")))
574
575 (define_delay
576   (eq_attr "needs_delay_slot" "yes")
577   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
578
579 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
580 ;; and thus we can't put a pop instruction in its delay slot.
581 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
582 ;; instruction can go in the delay slot.
583
584 ;; Since a normal return (rts) implicitly uses the PR register,
585 ;; we can't allow PR register loads in an rts delay slot.
586
587 (define_delay
588   (eq_attr "type" "return")
589   [(and (eq_attr "in_delay_slot" "yes")
590         (ior (and (eq_attr "interrupt_function" "no")
591                   (eq_attr "type" "!pload,prset"))
592              (and (eq_attr "interrupt_function" "yes")
593                   (ior
594                    (ne (symbol_ref "TARGET_SH3") (const_int 0))
595                    (eq_attr "hit_stack" "no"))))) (nil) (nil)])
596
597 ;; Since a call implicitly uses the PR register, we can't allow
598 ;; a PR register store in a jsr delay slot.
599
600 (define_delay
601   (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
602   [(and (eq_attr "in_delay_slot" "yes")
603         (eq_attr "type" "!pstore,prget")) (nil) (nil)])
604
605 ;; Say that we have annulled true branches, since this gives smaller and
606 ;; faster code when branches are predicted as not taken.
607
608 (define_delay
609   (and (eq_attr "type" "cbranch")
610        (ne (symbol_ref "TARGET_SH2") (const_int 0)))
611   [(eq_attr "in_delay_slot" "yes") (eq_attr "cond_delay_slot" "yes") (nil)])
612 \f
613 ;; -------------------------------------------------------------------------
614 ;; SImode signed integer comparisons
615 ;; -------------------------------------------------------------------------
616
617 (define_insn ""
618   [(set (reg:SI T_REG)
619         (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
620                        (match_operand:SI 1 "arith_operand" "L,r"))
621                (const_int 0)))]
622   "TARGET_SH1"
623   "tst  %1,%0"
624   [(set_attr "type" "mt_group")])
625
626 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
627 ;; That would still allow reload to create cmpi instructions, but would
628 ;; perhaps allow forcing the constant into a register when that is better.
629 ;; Probably should use r0 for mem/imm compares, but force constant into a
630 ;; register for pseudo/imm compares.
631
632 (define_insn "cmpeqsi_t"
633   [(set (reg:SI T_REG)
634         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
635                (match_operand:SI 1 "arith_operand" "N,rI,r")))]
636   "TARGET_SH1"
637   "@
638         tst     %0,%0
639         cmp/eq  %1,%0
640         cmp/eq  %1,%0"
641    [(set_attr "type" "mt_group")])
642
643 (define_insn "cmpgtsi_t"
644   [(set (reg:SI T_REG)
645         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
646                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
647   "TARGET_SH1"
648   "@
649         cmp/gt  %1,%0
650         cmp/pl  %0"
651    [(set_attr "type" "mt_group")])
652
653 (define_insn "cmpgesi_t"
654   [(set (reg:SI T_REG)
655         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
656                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
657   "TARGET_SH1"
658   "@
659         cmp/ge  %1,%0
660         cmp/pz  %0"
661    [(set_attr "type" "mt_group")])
662
663 ;; -------------------------------------------------------------------------
664 ;; SImode unsigned integer comparisons
665 ;; -------------------------------------------------------------------------
666
667 (define_insn "cmpgeusi_t"
668   [(set (reg:SI T_REG)
669         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
670                 (match_operand:SI 1 "arith_reg_operand" "r")))]
671   "TARGET_SH1"
672   "cmp/hs       %1,%0"
673    [(set_attr "type" "mt_group")])
674
675 (define_insn "cmpgtusi_t"
676   [(set (reg:SI T_REG)
677         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
678                 (match_operand:SI 1 "arith_reg_operand" "r")))]
679   "TARGET_SH1"
680   "cmp/hi       %1,%0"
681    [(set_attr "type" "mt_group")])
682
683 ;; We save the compare operands in the cmpxx patterns and use them when
684 ;; we generate the branch.
685
686 (define_expand "cmpsi"
687   [(set (reg:SI T_REG)
688         (compare (match_operand:SI 0 "arith_operand" "")
689                  (match_operand:SI 1 "arith_operand" "")))]
690   "TARGET_SH1"
691   "
692 {
693   sh_compare_op0 = operands[0];
694   sh_compare_op1 = operands[1];
695   DONE;
696 }")
697 \f
698 ;; -------------------------------------------------------------------------
699 ;; DImode signed integer comparisons
700 ;; -------------------------------------------------------------------------
701
702 ;; ??? Could get better scheduling by splitting the initial test from the
703 ;; rest of the insn after reload.  However, the gain would hardly justify
704 ;; the sh.md size increase necessary to do that.
705
706 (define_insn ""
707   [(set (reg:SI T_REG)
708         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
709                        (match_operand:DI 1 "arith_operand" "r"))
710                (const_int 0)))]
711   "TARGET_SH1"
712   "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
713                                  insn, operands);"
714   [(set_attr "length" "6")
715    (set_attr "type" "arith3b")])
716
717 (define_insn "cmpeqdi_t"
718   [(set (reg:SI T_REG)
719         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
720                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
721   "TARGET_SH1"
722   "@
723         tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
724         cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
725   [(set_attr "length" "6")
726    (set_attr "type" "arith3b")])
727
728 (define_split
729   [(set (reg:SI T_REG)
730         (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
731                (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
732 ;; If we applied this split when not optimizing, it would only be
733 ;; applied during the machine-dependent reorg, when no new basic blocks
734 ;; may be created.
735   "TARGET_SH1 && reload_completed && optimize"
736   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
737    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
738                            (label_ref (match_dup 6))
739                            (pc)))
740    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
741    (match_dup 6)]
742   "
743 {
744   operands[2]
745     = gen_rtx_REG (SImode,
746                    true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
747   operands[3]
748     = (operands[1] == const0_rtx
749        ? const0_rtx
750        : gen_rtx_REG (SImode,
751                       true_regnum (operands[1])
752                       + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
753   operands[4] = gen_lowpart (SImode, operands[0]);
754   operands[5] = gen_lowpart (SImode, operands[1]);
755   operands[6] = gen_label_rtx ();
756 }")
757
758 (define_insn "cmpgtdi_t"
759   [(set (reg:SI T_REG)
760         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
761                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
762   "TARGET_SH2"
763   "@
764         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
765         tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
766   [(set_attr "length" "8")
767    (set_attr "type" "arith3")])
768
769 (define_insn "cmpgedi_t"
770   [(set (reg:SI T_REG)
771         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
772                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
773   "TARGET_SH2"
774   "@
775         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
776         cmp/pz\\t%S0"
777   [(set_attr "length" "8,2")
778    (set_attr "type" "arith3,mt_group")])
779 \f
780 ;; -------------------------------------------------------------------------
781 ;; DImode unsigned integer comparisons
782 ;; -------------------------------------------------------------------------
783
784 (define_insn "cmpgeudi_t"
785   [(set (reg:SI T_REG)
786         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
787                 (match_operand:DI 1 "arith_reg_operand" "r")))]
788   "TARGET_SH2"
789   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
790   [(set_attr "length" "8")
791    (set_attr "type" "arith3")])
792
793 (define_insn "cmpgtudi_t"
794   [(set (reg:SI T_REG)
795         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
796                 (match_operand:DI 1 "arith_reg_operand" "r")))]
797   "TARGET_SH2"
798   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
799   [(set_attr "length" "8")
800    (set_attr "type" "arith3")])
801
802 (define_insn "cmpeqdi_media"
803   [(set (match_operand:DI 0 "register_operand" "=r")
804         (eq:DI (match_operand:DI 1 "register_operand" "%r")
805                (match_operand:DI 2 "arith_reg_or_0_operand" "Nr")))]
806   "TARGET_SHMEDIA"
807   "cmpeq        %1, %N2, %0"
808   [(set_attr "type" "cmp_media")])
809
810 (define_insn "cmpgtdi_media"
811   [(set (match_operand:DI 0 "register_operand" "=r")
812         (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
813                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
814   "TARGET_SHMEDIA"
815   "cmpgt        %N1, %N2, %0"
816   [(set_attr "type" "cmp_media")])
817
818 (define_insn "cmpgtudi_media"
819   [(set (match_operand:DI 0 "register_operand" "=r")
820         (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
821                 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
822   "TARGET_SHMEDIA"
823   "cmpgtu       %N1, %N2, %0"
824   [(set_attr "type" "cmp_media")])
825
826 ;; We save the compare operands in the cmpxx patterns and use them when
827 ;; we generate the branch.
828
829 (define_expand "cmpdi"
830   [(set (reg:SI T_REG)
831         (compare (match_operand:DI 0 "arith_operand" "")
832                  (match_operand:DI 1 "arith_operand" "")))]
833   "TARGET_SH2 || TARGET_SHMEDIA"
834   "
835 {
836   sh_compare_op0 = operands[0];
837   sh_compare_op1 = operands[1];
838   DONE;
839 }")
840 ;; -------------------------------------------------------------------------
841 ;; Conditional move instructions
842 ;; -------------------------------------------------------------------------
843
844 ;; The insn names may seem reversed, but note that cmveq performs the move
845 ;; if op1 == 0, and cmvne does it if op1 != 0.
846
847 (define_insn "movdicc_false"
848   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
849         (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
850                              (const_int 0))
851          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
852          (match_operand:DI 3 "arith_reg_operand" "0")))]
853   "TARGET_SHMEDIA"
854   "cmveq        %1, %N2, %0"
855   [(set_attr "type" "arith_media")])
856
857 (define_insn "movdicc_true"
858   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
859         (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
860                              (const_int 0))
861          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
862          (match_operand:DI 3 "arith_reg_operand" "0")))]
863   "TARGET_SHMEDIA"
864   "cmvne        %1, %N2, %0"
865   [(set_attr "type" "arith_media")])
866
867 (define_expand "movdicc"
868   [(set (match_operand:DI 0 "register_operand" "")
869         (if_then_else:DI (match_operand 1 "comparison_operator" "")
870                          (match_operand:DI 2 "register_operand" "")
871                          (match_operand:DI 3 "register_operand" "")))]
872   "TARGET_SHMEDIA"
873   "
874 {
875   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
876       && GET_MODE (sh_compare_op0) == DImode
877       && sh_compare_op1 == const0_rtx)
878     operands[1] = gen_rtx (GET_CODE (operands[1]), VOIDmode,
879                            sh_compare_op0, sh_compare_op1);
880   else
881     {
882       rtx tmp;
883
884       if (no_new_pseudos)
885         FAIL;
886
887       tmp = gen_reg_rtx (DImode);
888
889       switch (GET_CODE (operands[1]))
890         {
891         case EQ:
892           emit_insn (gen_seq (tmp));
893           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
894           break;
895
896         case NE:
897           emit_insn (gen_seq (tmp));
898           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
899           break;
900
901         case GT:
902           emit_insn (gen_sgt (tmp));
903           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
904           break;
905
906         case LT:
907           emit_insn (gen_slt (tmp));
908           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
909           break;
910
911         case GE:
912           emit_insn (gen_slt (tmp));
913           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
914           break;
915
916         case LE:
917           emit_insn (gen_sgt (tmp));
918           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
919           break;
920
921         case GTU:
922           emit_insn (gen_sgtu (tmp));
923           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
924           break;
925
926         case LTU:
927           emit_insn (gen_sltu (tmp));
928           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
929           break;
930
931         case GEU:
932           emit_insn (gen_sltu (tmp));
933           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
934           break;
935
936         case LEU:
937           emit_insn (gen_sgtu (tmp));
938           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
939           break;
940
941         case UNORDERED:
942           emit_insn (gen_sunordered (tmp));
943           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
944           break;
945
946         case ORDERED:
947           emit_insn (gen_sunordered (tmp));
948           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
949           break;
950
951         case UNEQ:
952         case UNGE:
953         case UNGT:
954         case UNLE:
955         case UNLT:
956         case LTGT:
957           FAIL;
958
959         default:
960           abort ();
961         }
962     }
963 }")
964 \f
965 ;; -------------------------------------------------------------------------
966 ;; Addition instructions
967 ;; -------------------------------------------------------------------------
968
969 (define_expand "adddi3"
970   [(set (match_operand:DI 0 "arith_reg_operand" "")
971         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
972                  (match_operand:DI 2 "arith_operand" "")))]
973   ""
974   "
975 {
976   if (TARGET_SH1)
977     {
978       if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
979         FAIL;
980       operands[2] = force_reg (DImode, operands[2]);
981       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
982       DONE;
983     }
984 }")
985
986 (define_insn "*adddi3_media"
987   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
988         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
989                  (match_operand:DI 2 "arith_operand" "r,P")))]
990   "TARGET_SHMEDIA"
991   "@
992         add     %1, %2, %0
993         addi    %1, %2, %0"
994   [(set_attr "type" "arith_media")])
995
996 (define_insn "adddi3z_media"
997   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
998         (zero_extend:DI
999          (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1000                   (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1001   "TARGET_SHMEDIA"
1002   "addz.l       %1, %N2, %0"
1003   [(set_attr "type" "arith_media")])
1004
1005 (define_insn "adddi3_compact"
1006   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1007         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1008                  (match_operand:DI 2 "arith_reg_operand" "r")))
1009    (clobber (reg:SI T_REG))]
1010   "TARGET_SH1"
1011   "#"
1012   [(set_attr "length" "6")])
1013
1014 (define_split
1015   [(set (match_operand:DI 0 "arith_reg_operand" "")
1016         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1017                  (match_operand:DI 2 "arith_reg_operand" "")))
1018    (clobber (reg:SI T_REG))]
1019   "TARGET_SH1 && reload_completed"
1020   [(const_int 0)]
1021   "
1022 {
1023   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1024   high0 = gen_rtx_REG (SImode,
1025                        true_regnum (operands[0])
1026                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1027   high2 = gen_rtx_REG (SImode,
1028                        true_regnum (operands[2])
1029                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1030   emit_insn (gen_clrt ());
1031   emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1032   emit_insn (gen_addc1 (high0, high0, high2));
1033   DONE;
1034 }")
1035
1036 (define_insn "addc"
1037   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1038         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1039                           (match_operand:SI 2 "arith_reg_operand" "r"))
1040                  (reg:SI T_REG)))
1041    (set (reg:SI T_REG)
1042         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1043   "TARGET_SH1"
1044   "addc %2,%0"
1045   [(set_attr "type" "arith")])
1046
1047 (define_insn "addc1"
1048   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1049         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1050                           (match_operand:SI 2 "arith_reg_operand" "r"))
1051                  (reg:SI T_REG)))
1052    (clobber (reg:SI T_REG))]
1053   "TARGET_SH1"
1054   "addc %2,%0"
1055   [(set_attr "type" "arith")])
1056
1057 (define_expand "addsi3"
1058   [(set (match_operand:SI 0 "arith_reg_operand" "")
1059         (plus:SI (match_operand:SI 1 "arith_operand" "")
1060                  (match_operand:SI 2 "arith_operand" "")))]
1061   ""
1062   "
1063 {
1064   if (TARGET_SHMEDIA)
1065     operands[1] = force_reg (SImode, operands[1]);
1066 }")
1067
1068 (define_insn "addsi3_media"
1069   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
1070         (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1071                  (match_operand:SI 2 "arith_operand" "r,P")))]
1072   "TARGET_SHMEDIA"
1073   "@
1074         add.l   %1, %2, %0
1075         addi.l  %1, %2, %0"
1076   [(set_attr "type" "arith_media")])
1077
1078 (define_insn "*addsi3_compact"
1079   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1080         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1081                  (match_operand:SI 2 "arith_operand" "rI")))]
1082   "TARGET_SH1"
1083   "add  %2,%0"
1084   [(set_attr "type" "arith")])
1085
1086 ;; -------------------------------------------------------------------------
1087 ;; Subtraction instructions
1088 ;; -------------------------------------------------------------------------
1089
1090 (define_expand "subdi3"
1091   [(set (match_operand:DI 0 "arith_reg_operand" "")
1092         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1093                   (match_operand:DI 2 "arith_reg_operand" "")))]
1094   ""
1095   "
1096 {
1097   if (TARGET_SH1)
1098     {
1099       operands[1] = force_reg (DImode, operands[1]);
1100       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1101       DONE;
1102     }
1103 }")
1104
1105 (define_insn "*subdi3_media"
1106   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1107         (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1108                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1109   "TARGET_SHMEDIA"
1110   "sub  %N1, %2, %0"
1111   [(set_attr "type" "arith_media")])
1112
1113 (define_insn "subdi3_compact"
1114   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1115         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1116                  (match_operand:DI 2 "arith_reg_operand" "r")))
1117    (clobber (reg:SI T_REG))]
1118   "TARGET_SH1"
1119   "#"
1120   [(set_attr "length" "6")])
1121
1122 (define_split
1123   [(set (match_operand:DI 0 "arith_reg_operand" "")
1124         (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1125                   (match_operand:DI 2 "arith_reg_operand" "")))
1126    (clobber (reg:SI T_REG))]
1127   "TARGET_SH1 && reload_completed"
1128   [(const_int 0)]
1129   "
1130 {
1131   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1132   high0 = gen_rtx_REG (SImode,
1133                        true_regnum (operands[0])
1134                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1135   high2 = gen_rtx_REG (SImode,
1136                        true_regnum (operands[2])
1137                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1138   emit_insn (gen_clrt ());
1139   emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1140   emit_insn (gen_subc1 (high0, high0, high2));
1141   DONE;
1142 }")
1143
1144 (define_insn "subc"
1145   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1146         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1147                             (match_operand:SI 2 "arith_reg_operand" "r"))
1148                   (reg:SI T_REG)))
1149    (set (reg:SI T_REG)
1150         (gtu:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1151   "TARGET_SH1"
1152   "subc %2,%0"
1153   [(set_attr "type" "arith")])
1154
1155 (define_insn "subc1"
1156   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1157         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1158                             (match_operand:SI 2 "arith_reg_operand" "r"))
1159                   (reg:SI T_REG)))
1160    (clobber (reg:SI T_REG))]
1161   "TARGET_SH1"
1162   "subc %2,%0"
1163   [(set_attr "type" "arith")])
1164
1165 (define_insn "*subsi3_internal"
1166   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1167         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1168                   (match_operand:SI 2 "arith_reg_operand" "r")))]
1169   "TARGET_SH1"
1170   "sub  %2,%0"
1171   [(set_attr "type" "arith")])
1172
1173 (define_insn "*subsi3_media"
1174   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1175         (minus:SI (match_operand:SI 1 "extend_reg_or_0_operand" "rN")
1176                   (match_operand:SI 2 "extend_reg_operand" "r")))]
1177   "TARGET_SHMEDIA"
1178   "sub.l        %N1, %2, %0"
1179   [(set_attr "type" "arith_media")])
1180
1181 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1182 ;; will sometimes save one instruction.  Otherwise we might get
1183 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1184 ;; are the same.
1185
1186 (define_expand "subsi3"
1187   [(set (match_operand:SI 0 "arith_reg_operand" "")
1188         (minus:SI (match_operand:SI 1 "arith_operand" "")
1189                   (match_operand:SI 2 "arith_reg_operand" "")))]
1190   ""
1191   "
1192 {
1193   if (TARGET_SH1 && GET_CODE (operands[1]) == CONST_INT)
1194     {
1195       emit_insn (gen_negsi2 (operands[0], operands[2]));
1196       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1197       DONE;
1198     }
1199   if (TARGET_SHMEDIA)
1200     {
1201       if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode))
1202         FAIL;
1203       if (operands[1] != const0_rtx)
1204         operands[1] = force_reg (SImode, operands[1]);
1205     }
1206 }")
1207 \f
1208 ;; -------------------------------------------------------------------------
1209 ;; Division instructions
1210 ;; -------------------------------------------------------------------------
1211
1212 ;; We take advantage of the library routines which don't clobber as many
1213 ;; registers as a normal function call would.
1214
1215 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1216 ;; also has an effect on the register that holds the address of the sfunc.
1217 ;; To make this work, we have an extra dummy insn that shows the use
1218 ;; of this register for reorg.
1219
1220 (define_insn "use_sfunc_addr"
1221   [(set (reg:SI PR_REG)
1222         (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1223   "TARGET_SH1"
1224   ""
1225   [(set_attr "length" "0")])
1226
1227 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1228 ;; hard register 0.  If we used hard register 0, then the next instruction
1229 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1230 ;; gets allocated to a stack slot that needs its address reloaded, then
1231 ;; there is nothing to prevent reload from using r0 to reload the address.
1232 ;; This reload would clobber the value in r0 we are trying to store.
1233 ;; If we let reload allocate r0, then this problem can never happen.
1234
1235 (define_insn "udivsi3_i1"
1236   [(set (match_operand:SI 0 "register_operand" "=z")
1237         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1238    (clobber (reg:SI T_REG))
1239    (clobber (reg:SI PR_REG))
1240    (clobber (reg:SI R4_REG))
1241    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1242   "TARGET_SH1 && ! TARGET_SH4"
1243   "jsr  @%1%#"
1244   [(set_attr "type" "sfunc")
1245    (set_attr "needs_delay_slot" "yes")])
1246
1247 ; Since shmedia-nofpu code could be linked against shcompact code, and
1248 ; the udivsi3 libcall has the same name, we must consider all registers
1249 ; clobbered that are in the union of the registers clobbered by the
1250 ; shmedia and the shcompact implementation.  Note, if the shcompact
1251 ; implemenation actually used shcompact code, we'd need to clobber
1252 ; also r23 and fr23.
1253 (define_insn "udivsi3_i1_media"
1254   [(set (match_operand:SI 0 "register_operand" "=z")
1255         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1256    (clobber (reg:SI T_MEDIA_REG))
1257    (clobber (reg:SI PR_MEDIA_REG))
1258    (clobber (reg:SI R20_REG))
1259    (clobber (reg:SI R21_REG))
1260    (clobber (reg:SI R22_REG))
1261    (clobber (reg:DI TR0_REG))
1262    (clobber (reg:DI TR1_REG))
1263    (clobber (reg:DI TR2_REG))
1264    (use (match_operand:DI 1 "target_operand" "b"))]
1265   "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
1266   "blink        %1, r18"
1267   [(set_attr "type" "sfunc")
1268    (set_attr "needs_delay_slot" "yes")])
1269
1270 (define_expand "udivsi3_i4_media"
1271   [(set (match_dup 3)
1272         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1273    (set (match_dup 4)
1274         (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1275    (set (match_dup 5) (float:DF (match_dup 3)))
1276    (set (match_dup 6) (float:DF (match_dup 4)))
1277    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1278    (set (match_dup 8) (fix:DI (match_dup 7)))
1279    (set (match_operand:SI 0 "register_operand" "")
1280         (truncate:SI (match_dup 8)))]
1281   "TARGET_SHMEDIA_FPU"
1282   "
1283 {
1284   operands[3] = gen_reg_rtx (DImode);
1285   operands[4] = gen_reg_rtx (DImode);
1286   operands[5] = gen_reg_rtx (DFmode);
1287   operands[6] = gen_reg_rtx (DFmode);
1288   operands[7] = gen_reg_rtx (DFmode);
1289   operands[8] = gen_reg_rtx (DImode);
1290 }")
1291
1292 (define_insn "udivsi3_i4"
1293   [(set (match_operand:SI 0 "register_operand" "=y")
1294         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1295    (clobber (reg:SI T_REG))
1296    (clobber (reg:SI PR_REG))
1297    (clobber (reg:DF DR0_REG))
1298    (clobber (reg:DF DR2_REG))
1299    (clobber (reg:DF DR4_REG))
1300    (clobber (reg:SI R0_REG))
1301    (clobber (reg:SI R1_REG))
1302    (clobber (reg:SI R4_REG))
1303    (clobber (reg:SI R5_REG))
1304    (use (reg:PSI FPSCR_REG))
1305    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1306   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1307   "jsr  @%1%#"
1308   [(set_attr "type" "sfunc")
1309    (set_attr "fp_mode" "double")
1310    (set_attr "needs_delay_slot" "yes")])
1311
1312 (define_insn "udivsi3_i4_single"
1313   [(set (match_operand:SI 0 "register_operand" "=y")
1314         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1315    (clobber (reg:SI T_REG))
1316    (clobber (reg:SI PR_REG))
1317    (clobber (reg:DF DR0_REG))
1318    (clobber (reg:DF DR2_REG))
1319    (clobber (reg:DF DR4_REG))
1320    (clobber (reg:SI R0_REG))
1321    (clobber (reg:SI R1_REG))
1322    (clobber (reg:SI R4_REG))
1323    (clobber (reg:SI R5_REG))
1324    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1325   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1326   "jsr  @%1%#"
1327   [(set_attr "type" "sfunc")
1328    (set_attr "needs_delay_slot" "yes")])
1329
1330 (define_expand "udivsi3"
1331   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1332    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1333    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1334    (parallel [(set (match_operand:SI 0 "register_operand" "")
1335                    (udiv:SI (reg:SI R4_REG)
1336                             (reg:SI R5_REG)))
1337               (clobber (reg:SI T_REG))
1338               (clobber (reg:SI PR_REG))
1339               (clobber (reg:SI R4_REG))
1340               (use (match_dup 3))])]
1341   ""
1342   "
1343 {
1344   rtx first, last;
1345
1346   operands[3] = gen_reg_rtx (Pmode);
1347   /* Emit the move of the address to a pseudo outside of the libcall.  */
1348   if (TARGET_HARD_SH4 && TARGET_SH3E)
1349     {
1350       emit_move_insn (operands[3],
1351                       gen_rtx_SYMBOL_REF (SImode, \"__udivsi3_i4\"));
1352       if (TARGET_FPU_SINGLE)
1353         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1354       else
1355         last = gen_udivsi3_i4 (operands[0], operands[3]);
1356     }
1357   else if (TARGET_SHMEDIA_FPU)
1358     {
1359       operands[1] = force_reg (SImode, operands[1]);
1360       operands[2] = force_reg (SImode, operands[2]);
1361       emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1362       DONE;
1363     }
1364   else if (TARGET_SH5)
1365     {
1366       emit_move_insn (operands[3],
1367                       gen_rtx_SYMBOL_REF (Pmode,
1368                                           (TARGET_FPU_ANY
1369                                            ? \"__udivsi3_i4\"
1370                                            : \"__udivsi3\")));
1371
1372       if (TARGET_SHMEDIA)
1373         last = gen_udivsi3_i1_media (operands[0],
1374                                      Pmode == DImode
1375                                      ? operands[3]
1376                                      : gen_rtx_SUBREG (DImode, operands[3],
1377                                                        0));
1378       else if (TARGET_FPU_ANY)
1379         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1380       else
1381         last = gen_udivsi3_i1 (operands[0], operands[3]);
1382     }
1383   else
1384     {
1385       emit_move_insn (operands[3],
1386                       gen_rtx_SYMBOL_REF (SImode, \"__udivsi3\"));
1387       last = gen_udivsi3_i1 (operands[0], operands[3]);
1388     }
1389   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1390   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1391   last = emit_insn (last);
1392   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1393      invariant code motion can move it.  */
1394   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1395   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1396   DONE;
1397 }")
1398
1399 (define_insn "divsi3_i1"
1400   [(set (match_operand:SI 0 "register_operand" "=z")
1401         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1402    (clobber (reg:SI T_REG))
1403    (clobber (reg:SI PR_REG))
1404    (clobber (reg:SI R1_REG))
1405    (clobber (reg:SI R2_REG))
1406    (clobber (reg:SI R3_REG))
1407    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1408   "TARGET_SH1 && ! TARGET_SH4"
1409   "jsr  @%1%#"
1410   [(set_attr "type" "sfunc")
1411    (set_attr "needs_delay_slot" "yes")])
1412
1413 ; Since shmedia-nofpu code could be linked against shcompact code, and
1414 ; the sdivsi3 libcall has the same name, we must consider all registers
1415 ; clobbered that are in the union of the registers clobbered by the
1416 ; shmedia and the shcompact implementation.  Note, if the shcompact
1417 ; implemenation actually used shcompact code, we'd need to clobber
1418 ; also r22, r23 and fr23.
1419 (define_insn "divsi3_i1_media"
1420   [(set (match_operand:SI 0 "register_operand" "=z")
1421         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1422    (clobber (reg:SI T_MEDIA_REG))
1423    (clobber (reg:SI PR_MEDIA_REG))
1424    (clobber (reg:SI R1_REG))
1425    (clobber (reg:SI R2_REG))
1426    (clobber (reg:SI R3_REG))
1427    (clobber (reg:SI R20_REG))
1428    (clobber (reg:SI R21_REG))
1429    (clobber (reg:DI TR0_REG))
1430    (clobber (reg:DI TR1_REG))
1431    (clobber (reg:DI TR2_REG))
1432    (use (match_operand:DI 1 "target_operand" "b"))]
1433   "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
1434   "blink        %1, r18"
1435   [(set_attr "type" "sfunc")])
1436
1437 (define_expand "divsi3_i4_media"
1438   [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
1439    (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
1440    (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
1441    (set (match_operand:SI 0 "register_operand" "=r")
1442         (fix:SI (match_dup 5)))]
1443   "TARGET_SHMEDIA_FPU"
1444   "
1445 {
1446   operands[3] = gen_reg_rtx (DFmode);
1447   operands[4] = gen_reg_rtx (DFmode);
1448   operands[5] = gen_reg_rtx (DFmode);
1449 }")
1450
1451 (define_insn "divsi3_i4"
1452   [(set (match_operand:SI 0 "register_operand" "=y")
1453         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1454    (clobber (reg:SI PR_REG))
1455    (clobber (reg:DF DR0_REG))
1456    (clobber (reg:DF DR2_REG))
1457    (use (reg:PSI FPSCR_REG))
1458    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1459   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1460   "jsr  @%1%#"
1461   [(set_attr "type" "sfunc")
1462    (set_attr "fp_mode" "double")
1463    (set_attr "needs_delay_slot" "yes")])
1464
1465 (define_insn "divsi3_i4_single"
1466   [(set (match_operand:SI 0 "register_operand" "=y")
1467         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1468    (clobber (reg:SI PR_REG))
1469    (clobber (reg:DF DR0_REG))
1470    (clobber (reg:DF DR2_REG))
1471    (clobber (reg:SI R2_REG))
1472    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1473   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1474   "jsr  @%1%#"
1475   [(set_attr "type" "sfunc")
1476    (set_attr "needs_delay_slot" "yes")])
1477
1478 (define_expand "divsi3"
1479   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
1480    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1481    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1482    (parallel [(set (match_operand:SI 0 "register_operand" "")
1483                    (div:SI (reg:SI R4_REG)
1484                            (reg:SI R5_REG)))
1485               (clobber (reg:SI T_REG))
1486               (clobber (reg:SI PR_REG))
1487               (clobber (reg:SI R1_REG))
1488               (clobber (reg:SI R2_REG))
1489               (clobber (reg:SI R3_REG))
1490               (use (match_dup 3))])]
1491   ""
1492   "
1493 {
1494   rtx first, last;
1495
1496   operands[3] = gen_reg_rtx (Pmode);
1497   /* Emit the move of the address to a pseudo outside of the libcall.  */
1498   if (TARGET_HARD_SH4 && TARGET_SH3E)
1499     {
1500       emit_move_insn (operands[3],
1501                       gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3_i4\"));
1502       if (TARGET_FPU_SINGLE)
1503         last = gen_divsi3_i4_single (operands[0], operands[3]);
1504       else
1505         last = gen_divsi3_i4 (operands[0], operands[3]);
1506     }
1507   else if (TARGET_SHMEDIA_FPU)
1508     {
1509       operands[1] = force_reg (SImode, operands[1]);
1510       operands[2] = force_reg (SImode, operands[2]);
1511       emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
1512       DONE;
1513     }
1514   else if (TARGET_SH5)
1515     {
1516       emit_move_insn (operands[3],
1517                       gen_rtx_SYMBOL_REF (Pmode,
1518                                           (TARGET_FPU_ANY
1519                                            ? \"__sdivsi3_i4\"
1520                                            : \"__sdivsi3\")));
1521
1522       if (TARGET_SHMEDIA)
1523         last = gen_divsi3_i1_media (operands[0],
1524                                     Pmode == DImode
1525                                     ? operands[3]
1526                                     : gen_rtx_SUBREG (DImode, operands[3],
1527                                                       0));
1528       else if (TARGET_FPU_ANY)
1529         last = gen_divsi3_i4_single (operands[0], operands[3]);
1530       else
1531         last = gen_divsi3_i1 (operands[0], operands[3]);
1532     }
1533   else
1534     {
1535       emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\"));
1536       last = gen_divsi3_i1 (operands[0], operands[3]);
1537     }
1538   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1539   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1540   last = emit_insn (last);
1541   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1542      invariant code motion can move it.  */
1543   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1544   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1545   DONE;
1546 }")
1547 \f
1548 ;; -------------------------------------------------------------------------
1549 ;; Multiplication instructions
1550 ;; -------------------------------------------------------------------------
1551
1552 (define_insn "umulhisi3_i"
1553   [(set (reg:SI MACL_REG)
1554         (mult:SI (zero_extend:SI
1555                   (match_operand:HI 0 "arith_reg_operand" "r"))
1556                  (zero_extend:SI
1557                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
1558   "TARGET_SH1"
1559   "mulu.w       %1,%0"
1560   [(set_attr "type" "smpy")])
1561
1562 (define_insn "mulhisi3_i"
1563   [(set (reg:SI MACL_REG)
1564         (mult:SI (sign_extend:SI
1565                   (match_operand:HI 0 "arith_reg_operand" "r"))
1566                  (sign_extend:SI
1567                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
1568   "TARGET_SH1"
1569   "muls.w       %1,%0"
1570   [(set_attr "type" "smpy")])
1571
1572 (define_expand "mulhisi3"
1573   [(set (reg:SI MACL_REG)
1574         (mult:SI (sign_extend:SI
1575                   (match_operand:HI 1 "arith_reg_operand" ""))
1576                  (sign_extend:SI
1577                   (match_operand:HI 2 "arith_reg_operand" ""))))
1578    (set (match_operand:SI 0 "arith_reg_operand" "")
1579         (reg:SI MACL_REG))]
1580   "TARGET_SH1"
1581   "
1582 {
1583   rtx first, last;
1584
1585   first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
1586   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
1587   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1588      invariant code motion can move it.  */
1589   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1590   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1591   /* expand_binop can't find a suitable code in umul_widen_optab to
1592      make a REG_EQUAL note from, so make one here.
1593      See also smulsi3_highpart.
1594      ??? Alternatively, we could put this at the calling site of expand_binop,
1595      i.e. expand_expr.  */
1596   REG_NOTES (last)
1597     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1598                          REG_NOTES (last));
1599   DONE;
1600 }")
1601
1602 (define_expand "umulhisi3"
1603   [(set (reg:SI MACL_REG)
1604         (mult:SI (zero_extend:SI
1605                   (match_operand:HI 1 "arith_reg_operand" ""))
1606                  (zero_extend:SI
1607                   (match_operand:HI 2 "arith_reg_operand" ""))))
1608    (set (match_operand:SI 0 "arith_reg_operand" "")
1609         (reg:SI MACL_REG))]
1610   "TARGET_SH1"
1611   "
1612 {
1613   rtx first, last;
1614
1615   first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
1616   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
1617   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1618      invariant code motion can move it.  */
1619   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1620   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1621   /* expand_binop can't find a suitable code in umul_widen_optab to
1622      make a REG_EQUAL note from, so make one here.
1623      See also smulsi3_highpart.
1624      ??? Alternatively, we could put this at the calling site of expand_binop,
1625      i.e. expand_expr.  */
1626   REG_NOTES (last)
1627     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1628                          REG_NOTES (last));
1629   DONE;
1630 }")
1631
1632 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
1633 ;; a call to a routine which clobbers known registers.
1634
1635 (define_insn ""
1636   [(set (match_operand:SI 1 "register_operand" "=z")
1637         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1638    (clobber (reg:SI MACL_REG))
1639    (clobber (reg:SI T_REG))
1640    (clobber (reg:SI PR_REG))
1641    (clobber (reg:SI R3_REG))
1642    (clobber (reg:SI R2_REG))
1643    (clobber (reg:SI R1_REG))
1644    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
1645   "TARGET_SH1"
1646   "jsr  @%0%#"
1647   [(set_attr "type" "sfunc")
1648    (set_attr "needs_delay_slot" "yes")])
1649
1650 (define_expand "mulsi3_call"
1651   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1652    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1653    (parallel[(set (match_operand:SI 0 "register_operand" "")
1654                   (mult:SI (reg:SI R4_REG)
1655                            (reg:SI R5_REG)))
1656              (clobber (reg:SI MACL_REG))
1657              (clobber (reg:SI T_REG))
1658              (clobber (reg:SI PR_REG))
1659              (clobber (reg:SI R3_REG))
1660              (clobber (reg:SI R2_REG))
1661              (clobber (reg:SI R1_REG))
1662              (use (match_operand:SI 3 "register_operand" ""))])]
1663   "TARGET_SH1"
1664   "")
1665
1666 (define_insn "mul_l"
1667   [(set (reg:SI MACL_REG)
1668         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
1669                  (match_operand:SI 1 "arith_reg_operand" "r")))]
1670   "TARGET_SH2"
1671   "mul.l        %1,%0"
1672   [(set_attr "type" "dmpy")])
1673
1674 (define_expand "mulsi3"
1675   [(set (reg:SI MACL_REG)
1676         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
1677                   (match_operand:SI 2 "arith_reg_operand" "")))
1678    (set (match_operand:SI 0 "arith_reg_operand" "")
1679         (reg:SI MACL_REG))]
1680   "TARGET_SH1"
1681   "
1682 {
1683   rtx first, last;
1684
1685   if (!TARGET_SH2)
1686     {
1687       /* The address must be set outside the libcall,
1688          since it goes into a pseudo.  */
1689       rtx sym = gen_rtx_SYMBOL_REF (SImode, \"__mulsi3\");
1690       rtx addr = force_reg (SImode, sym);
1691       rtx insns = gen_mulsi3_call (operands[0], operands[1],
1692                                    operands[2], addr);
1693       first = insns;
1694       last = emit_insn (insns);
1695     }
1696   else
1697     {
1698       rtx macl = gen_rtx_REG (SImode, MACL_REG);
1699
1700       first = emit_insn (gen_mul_l (operands[1], operands[2]));
1701       /* consec_sets_giv can only recognize the first insn that sets a
1702          giv as the giv insn.  So we must tag this also with a REG_EQUAL
1703          note.  */
1704       last = emit_insn (gen_movsi_i ((operands[0]), macl));
1705     }
1706   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1707      invariant code motion can move it.  */
1708   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1709   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1710   DONE;
1711 }")
1712
1713 (define_insn "mulsidi3_i"
1714   [(set (reg:SI MACH_REG)
1715         (truncate:SI
1716          (lshiftrt:DI
1717           (mult:DI
1718            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1719            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1720           (const_int 32))))
1721    (set (reg:SI MACL_REG)
1722         (mult:SI (match_dup 0)
1723                  (match_dup 1)))]
1724   "TARGET_SH2"
1725   "dmuls.l      %1,%0"
1726   [(set_attr "type" "dmpy")])
1727
1728 (define_expand "mulsidi3"
1729   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1730         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1731                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1732   "TARGET_SH2 || TARGET_SHMEDIA"
1733   "
1734 {
1735   if (TARGET_SH2)
1736     {
1737        emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
1738                                         operands[2]));
1739        DONE;
1740     }
1741 }")
1742
1743 (define_insn "mulsidi3_media"
1744   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1745         (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
1746                  (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
1747   "TARGET_SHMEDIA"
1748   "muls.l       %1, %2, %0"
1749   [(set_attr "type" "dmpy_media")])
1750
1751 (define_insn "mulsidi3_compact"
1752   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1753         (mult:DI
1754          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1755          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
1756    (clobber (reg:SI MACH_REG))
1757    (clobber (reg:SI MACL_REG))]
1758   "TARGET_SH2"
1759   "#")
1760
1761 (define_split
1762   [(set (match_operand:DI 0 "arith_reg_operand" "")
1763         (mult:DI
1764          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1765          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
1766    (clobber (reg:SI MACH_REG))
1767    (clobber (reg:SI MACL_REG))]
1768   "TARGET_SH2"
1769   [(const_int 0)]
1770   "
1771 {
1772   rtx low_dst = gen_lowpart (SImode, operands[0]);
1773   rtx high_dst = gen_highpart (SImode, operands[0]);
1774
1775   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
1776
1777   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
1778   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
1779   /* We need something to tag the possible REG_EQUAL notes on to.  */
1780   emit_move_insn (operands[0], operands[0]);
1781   DONE;
1782 }")
1783
1784 (define_insn "umulsidi3_i"
1785   [(set (reg:SI MACH_REG)
1786         (truncate:SI
1787          (lshiftrt:DI
1788           (mult:DI
1789            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1790            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1791           (const_int 32))))
1792    (set (reg:SI MACL_REG)
1793         (mult:SI (match_dup 0)
1794                  (match_dup 1)))]
1795   "TARGET_SH2"
1796   "dmulu.l      %1,%0"
1797   [(set_attr "type" "dmpy")])
1798
1799 (define_expand "umulsidi3"
1800   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1801         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1802                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1803   "TARGET_SH2 || TARGET_SHMEDIA"
1804   "
1805 {
1806   if (TARGET_SH2)
1807     {
1808        emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
1809                                          operands[2]));
1810        DONE;
1811     }
1812 }")
1813
1814 (define_insn "umulsidi3_media"
1815   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1816         (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
1817                  (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
1818   "TARGET_SHMEDIA"
1819   "mulu.l       %1, %2, %0"
1820   [(set_attr "type" "dmpy_media")])
1821
1822 (define_insn "umulsidi3_compact"
1823   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1824         (mult:DI
1825          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1826          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
1827    (clobber (reg:SI MACH_REG))
1828    (clobber (reg:SI MACL_REG))]
1829   "TARGET_SH2"
1830   "#")
1831
1832 (define_split
1833   [(set (match_operand:DI 0 "arith_reg_operand" "")
1834         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1835                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
1836    (clobber (reg:SI MACH_REG))
1837    (clobber (reg:SI MACL_REG))]
1838   "TARGET_SH2"
1839   [(const_int 0)]
1840   "
1841 {
1842   rtx low_dst = gen_lowpart (SImode, operands[0]);
1843   rtx high_dst = gen_highpart (SImode, operands[0]);
1844
1845   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
1846
1847   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
1848   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
1849   /* We need something to tag the possible REG_EQUAL notes on to.  */
1850   emit_move_insn (operands[0], operands[0]);
1851   DONE;
1852 }")
1853
1854 (define_insn "smulsi3_highpart_i"
1855   [(set (reg:SI MACH_REG)
1856         (truncate:SI
1857          (lshiftrt:DI
1858           (mult:DI
1859            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1860            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1861           (const_int 32))))
1862    (clobber (reg:SI MACL_REG))]
1863   "TARGET_SH2"
1864   "dmuls.l      %1,%0"
1865   [(set_attr "type" "dmpy")])
1866
1867 (define_expand "smulsi3_highpart"
1868   [(parallel
1869     [(set (reg:SI MACH_REG)
1870           (truncate:SI
1871            (lshiftrt:DI
1872             (mult:DI
1873              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1874              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
1875             (const_int 32))))
1876     (clobber (reg:SI MACL_REG))])
1877    (set (match_operand:SI 0 "arith_reg_operand" "")
1878         (reg:SI MACH_REG))]
1879   "TARGET_SH2"
1880   "
1881 {
1882   rtx first, last;
1883
1884   first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
1885   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
1886   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1887      invariant code motion can move it.  */
1888   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1889   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1890   /* expand_binop can't find a suitable code in mul_highpart_optab to
1891      make a REG_EQUAL note from, so make one here.
1892      See also {,u}mulhisi.
1893      ??? Alternatively, we could put this at the calling site of expand_binop,
1894      i.e. expand_mult_highpart.  */
1895   REG_NOTES (last)
1896     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1897                          REG_NOTES (last));
1898   DONE;
1899 }")
1900
1901 (define_insn "umulsi3_highpart_i"
1902   [(set (reg:SI MACH_REG)
1903         (truncate:SI
1904          (lshiftrt:DI
1905           (mult:DI
1906            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1907            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1908           (const_int 32))))
1909    (clobber (reg:SI MACL_REG))]
1910   "TARGET_SH2"
1911   "dmulu.l      %1,%0"
1912   [(set_attr "type" "dmpy")])
1913
1914 (define_expand "umulsi3_highpart"
1915   [(parallel
1916     [(set (reg:SI MACH_REG)
1917           (truncate:SI
1918            (lshiftrt:DI
1919             (mult:DI
1920              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1921              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
1922             (const_int 32))))
1923     (clobber (reg:SI MACL_REG))])
1924    (set (match_operand:SI 0 "arith_reg_operand" "")
1925         (reg:SI MACH_REG))]
1926   "TARGET_SH2"
1927   "
1928 {
1929   rtx first, last;
1930
1931   first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
1932   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
1933   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1934      invariant code motion can move it.  */
1935   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1936   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1937   DONE;
1938 }")
1939 \f
1940 ;; -------------------------------------------------------------------------
1941 ;; Logical operations
1942 ;; -------------------------------------------------------------------------
1943
1944 (define_insn "*andsi3_compact"
1945   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
1946         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1947                 (match_operand:SI 2 "logical_operand" "r,L")))]
1948   "TARGET_SH1"
1949   "and  %2,%0"
1950   [(set_attr "type" "arith")])
1951
1952 ;; If the constant is 255, then emit an extu.b instruction instead of an
1953 ;; and, since that will give better code.
1954
1955 (define_expand "andsi3"
1956   [(set (match_operand:SI 0 "arith_reg_operand" "")
1957         (and:SI (match_operand:SI 1 "arith_reg_operand" "")
1958                 (match_operand:SI 2 "logical_operand" "")))]
1959   "TARGET_SH1"
1960   "
1961 {
1962   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)
1963     {
1964       emit_insn (gen_zero_extendqisi2 (operands[0],
1965                                        gen_lowpart (QImode, operands[1])));
1966       DONE;
1967     }
1968 }")
1969
1970 (define_insn_and_split "anddi3"
1971   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r,r")
1972         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
1973                 (match_operand:DI 2 "and_operand" "r,P,n")))]
1974   "TARGET_SHMEDIA"
1975   "@
1976         and     %1, %2, %0
1977         andi    %1, %2, %0
1978         #"
1979   "reload_completed
1980    && ! logical_operand (operands[2], DImode)"
1981   [(const_int 0)]
1982   "
1983 {
1984   if (INTVAL (operands[2]) == (unsigned) 0xffffffff)
1985     emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
1986   else
1987     emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
1988   DONE;
1989 }"
1990   [(set_attr "type" "arith_media")])
1991
1992 (define_insn "andcdi3"
1993   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1994         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
1995                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
1996   "TARGET_SHMEDIA"
1997   "andc %1,%2,%0"
1998   [(set_attr "type" "arith_media")])
1999
2000 (define_insn "iorsi3"
2001   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
2002         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
2003                 (match_operand:SI 2 "logical_operand" "r,L")))]
2004   "TARGET_SH1"
2005   "or   %2,%0"
2006   [(set_attr "type" "arith")])
2007
2008 (define_insn "iordi3"
2009   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2010         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
2011                 (match_operand:DI 2 "logical_operand" "r,P")))]
2012   "TARGET_SHMEDIA"
2013   "@
2014         or      %1, %2, %0
2015         ori     %1, %2, %0"
2016   [(set_attr "type" "arith_media")])
2017
2018 (define_insn "xorsi3"
2019   [(set (match_operand:SI 0 "arith_reg_operand" "=z,r")
2020         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
2021                 (match_operand:SI 2 "logical_operand" "L,r")))]
2022   "TARGET_SH1"
2023   "xor  %2,%0"
2024   [(set_attr "type" "arith")])
2025
2026 (define_insn "xordi3"
2027   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2028         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
2029                 (match_operand:DI 2 "shmedia_6bit_operand" "r,O")))]
2030   "TARGET_SHMEDIA"
2031   "@
2032         xor     %1, %2, %0
2033         xori    %1, %2, %0"
2034   [(set_attr "type" "arith_media")])
2035
2036 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
2037 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
2038 (define_split
2039   [(set (match_operand:DI 0 "arith_reg_operand" "")
2040         (sign_extend:DI (match_operator 4 "binary_logical_operator"
2041                           [(match_operand 1 "any_register_operand" "")
2042                            (match_operand 2 "any_register_operand" "")])))]
2043   "TARGET_SHMEDIA"
2044   [(set (match_dup 5) (match_dup 4))
2045    (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
2046 "
2047 {
2048   enum machine_mode inmode = GET_MODE (operands[1]);
2049   int regno, offset = 0;
2050
2051   if (GET_CODE (operands[0]) == SUBREG)
2052     {
2053       offset = SUBREG_BYTE (operands[0]);
2054       operands[0] = SUBREG_REG (operands[0]);
2055     }
2056   if (GET_CODE (operands[0]) != REG)
2057     abort ();
2058   if (! TARGET_LITTLE_ENDIAN)
2059     offset += 8 - GET_MODE_SIZE (inmode);
2060   operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
2061 }")
2062 \f
2063 ;; -------------------------------------------------------------------------
2064 ;; Shifts and rotates
2065 ;; -------------------------------------------------------------------------
2066
2067 (define_expand "rotldi3"
2068   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2069         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
2070                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
2071   "TARGET_SHMEDIA"
2072   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
2073
2074 (define_insn "rotldi3_mextr"
2075   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2076         (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
2077                    (match_operand:HI 2 "mextr_bit_offset" "i")))]
2078   "TARGET_SHMEDIA"
2079   "*
2080 {
2081   static char templ[16];
2082
2083   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
2084            8 - (int) (INTVAL (operands[2]) >> 3));
2085   return templ;
2086 }"
2087   [(set_attr "type" "arith_media")])
2088
2089 (define_expand "rotrdi3"
2090   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2091         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
2092                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
2093   "TARGET_SHMEDIA"
2094   "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
2095
2096 (define_insn "rotrdi3_mextr"
2097   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2098         (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
2099                      (match_operand:HI 2 "mextr_bit_offset" "i")))]
2100   "TARGET_SHMEDIA"
2101   "*
2102 {
2103   static char templ[16];
2104
2105   sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
2106   return templ;
2107 }"
2108   [(set_attr "type" "arith_media")])
2109
2110 (define_insn "rotlsi3_1"
2111   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2112         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
2113                    (const_int 1)))
2114    (set (reg:SI T_REG)
2115         (lshiftrt:SI (match_dup 1) (const_int 31)))]
2116   "TARGET_SH1"
2117   "rotl %0"
2118   [(set_attr "type" "arith")])
2119
2120 (define_insn "rotlsi3_31"
2121   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2122         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
2123                    (const_int 31)))
2124    (clobber (reg:SI T_REG))]
2125   "TARGET_SH1"
2126   "rotr %0"
2127   [(set_attr "type" "arith")])
2128
2129 (define_insn "rotlsi3_16"
2130   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2131         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
2132                    (const_int 16)))]
2133   "TARGET_SH1"
2134   "swap.w       %1,%0"
2135   [(set_attr "type" "arith")])
2136
2137 (define_expand "rotlsi3"
2138   [(set (match_operand:SI 0 "arith_reg_operand" "")
2139         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
2140                    (match_operand:SI 2 "immediate_operand" "")))]
2141   "TARGET_SH1"
2142   "
2143 {
2144   static const char rot_tab[] = {
2145     000, 000, 000, 000, 000, 000, 010, 001,
2146     001, 001, 011, 013, 003, 003, 003, 003,
2147     003, 003, 003, 003, 003, 013, 012, 002,
2148     002, 002, 010, 000, 000, 000, 000, 000,
2149   };
2150
2151   int count, choice;
2152
2153   if (GET_CODE (operands[2]) != CONST_INT)
2154     FAIL;
2155   count = INTVAL (operands[2]);
2156   choice = rot_tab[count];
2157   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
2158     FAIL;
2159   choice &= 7;
2160   switch (choice)
2161     {
2162     case 0:
2163       emit_move_insn (operands[0], operands[1]);
2164       count -= (count & 16) * 2;
2165       break;
2166     case 3:
2167      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
2168      count -= 16;
2169      break;
2170     case 1:
2171     case 2:
2172       {
2173         rtx parts[2];
2174         parts[0] = gen_reg_rtx (SImode);
2175         parts[1] = gen_reg_rtx (SImode);
2176         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
2177         parts[choice-1] = operands[1];
2178         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
2179         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
2180         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
2181         count = (count & ~16) - 8;
2182       }
2183     }
2184
2185   for (; count > 0; count--)
2186     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
2187   for (; count < 0; count++)
2188     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
2189
2190   DONE;
2191 }")
2192
2193 (define_insn "*rotlhi3_8"
2194   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
2195         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
2196                    (const_int 8)))]
2197   "TARGET_SH1"
2198   "swap.b       %1,%0"
2199   [(set_attr "type" "arith")])
2200
2201 (define_expand "rotlhi3"
2202   [(set (match_operand:HI 0 "arith_reg_operand" "")
2203         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
2204                    (match_operand:HI 2 "immediate_operand" "")))]
2205   "TARGET_SH1"
2206   "
2207 {
2208   if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
2209     FAIL;
2210 }")
2211
2212 ;;
2213 ;; shift left
2214
2215 ;; This pattern is used by init_expmed for computing the costs of shift
2216 ;; insns.
2217
2218 (define_insn_and_split "ashlsi3_std"
2219   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r,r,r")
2220         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
2221                    (match_operand:SI 2 "nonmemory_operand" "r,M,K,?ri")))
2222    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
2223   "TARGET_SH3
2224    || (TARGET_SH1 && GET_CODE (operands[2]) == CONST_INT
2225        && CONST_OK_FOR_K (INTVAL (operands[2])))"
2226   "@
2227    shld %2,%0
2228    add  %0,%0
2229    shll%O2      %0
2230    #"
2231   "TARGET_SH3
2232    && reload_completed
2233    && GET_CODE (operands[2]) == CONST_INT
2234    && ! CONST_OK_FOR_K (INTVAL (operands[2]))"
2235   [(set (match_dup 3) (match_dup 2))
2236    (parallel
2237     [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
2238      (clobber (match_dup 4))])]
2239   "operands[4] = gen_rtx_SCRATCH (SImode);"
2240   [(set_attr "length" "*,*,*,4")
2241    (set_attr "type" "dyn_shift,arith,arith,arith")])
2242
2243 (define_insn "ashlhi3_k"
2244   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
2245         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
2246                    (match_operand:HI 2 "const_int_operand" "M,K")))]
2247   "TARGET_SH1 && CONST_OK_FOR_K (INTVAL (operands[2]))"
2248   "@
2249         add     %0,%0
2250         shll%O2 %0"
2251   [(set_attr "type" "arith")])
2252
2253 (define_insn "ashlsi3_n"
2254   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2255         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
2256                    (match_operand:SI 2 "const_int_operand" "n")))
2257    (clobber (reg:SI T_REG))]
2258   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
2259   "#"
2260   [(set (attr "length")
2261         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2262                (const_string "2")
2263                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2264                (const_string "4")
2265                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
2266                (const_string "6")]
2267               (const_string "8")))
2268    (set_attr "type" "arith")])
2269
2270 (define_split
2271   [(set (match_operand:SI 0 "arith_reg_operand" "")
2272         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
2273                    (match_operand:SI 2 "const_int_operand" "")))
2274    (clobber (reg:SI T_REG))]
2275   "TARGET_SH1 && reload_completed"
2276   [(use (reg:SI R0_REG))]
2277   "
2278 {
2279   gen_shifty_op (ASHIFT, operands);
2280   DONE;
2281 }")
2282
2283 (define_insn "ashlsi3_media"
2284   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2285         (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
2286                    (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2287   "TARGET_SHMEDIA"
2288   "@
2289         shlld.l %1, %2, %0
2290         shlli.l %1, %2, %0"
2291   [(set_attr "type" "arith_media")])
2292
2293 (define_expand "ashlsi3"
2294   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2295                    (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
2296                               (match_operand:SI 2 "nonmemory_operand" "")))
2297               (clobber (reg:SI T_REG))])]
2298   ""
2299   "
2300 {
2301   if (TARGET_SHMEDIA)
2302     {
2303       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
2304       DONE;
2305     }
2306   if (GET_CODE (operands[2]) == CONST_INT
2307       && sh_dynamicalize_shift_p (operands[2]))
2308     operands[2] = force_reg (SImode, operands[2]);
2309   if (TARGET_SH3)
2310     {
2311       emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
2312       DONE;
2313     }
2314   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
2315     FAIL;
2316 }")
2317
2318 (define_insn "ashlhi3"
2319   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
2320         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
2321                    (match_operand:HI 2 "const_int_operand" "n")))
2322    (clobber (reg:SI T_REG))]
2323   "TARGET_SH1"
2324   "#"
2325   [(set (attr "length")
2326         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2327                (const_string "2")
2328                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2329                (const_string "4")]
2330               (const_string "6")))
2331    (set_attr "type" "arith")])
2332
2333 (define_split
2334   [(set (match_operand:HI 0 "arith_reg_operand" "")
2335         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
2336                    (match_operand:HI 2 "const_int_operand" "")))
2337    (clobber (reg:SI T_REG))]
2338   "TARGET_SH1 && reload_completed"
2339   [(use (reg:SI R0_REG))]
2340   "
2341 {
2342   gen_shifty_hi_op (ASHIFT, operands);
2343   DONE;
2344 }")
2345
2346 ;
2347 ; arithmetic shift right
2348 ;
2349
2350 (define_insn "ashrsi3_k"
2351   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2352         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2353                      (match_operand:SI 2 "const_int_operand" "M")))
2354    (clobber (reg:SI T_REG))]
2355   "TARGET_SH1 && INTVAL (operands[2]) == 1"
2356   "shar %0"
2357   [(set_attr "type" "arith")])
2358
2359 ;; We can't do HImode right shifts correctly unless we start out with an
2360 ;; explicit zero / sign extension; doing that would result in worse overall
2361 ;; code, so just let the machine independent code widen the mode.
2362 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
2363
2364
2365 ;; ??? This should be a define expand.
2366
2367 (define_insn "ashrsi2_16"
2368   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2369         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
2370                      (const_int 16)))]
2371   "TARGET_SH1"
2372   "#"
2373   [(set_attr "length" "4")])
2374
2375 (define_split
2376   [(set (match_operand:SI 0 "arith_reg_operand" "")
2377         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2378                      (const_int 16)))]
2379   "TARGET_SH1"
2380   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
2381    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2382   "operands[2] = gen_lowpart (HImode, operands[0]);")
2383
2384 ;; ??? This should be a define expand.
2385
2386 (define_insn "ashrsi2_31"
2387   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2388         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2389                      (const_int 31)))
2390    (clobber (reg:SI T_REG))]
2391   "TARGET_SH1"
2392   "#"
2393   [(set_attr "length" "4")])
2394
2395 (define_split
2396   [(set (match_operand:SI 0 "arith_reg_operand" "")
2397         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2398                      (const_int 31)))
2399    (clobber (reg:SI T_REG))]
2400   "TARGET_SH1"
2401   [(const_int 0)]
2402   "
2403 {
2404   emit_insn (gen_ashlsi_c (operands[0], operands[1]));
2405   emit_insn (gen_subc1 (operands[0], operands[0], operands[0]));
2406   DONE;
2407 }")
2408
2409 (define_insn "ashlsi_c"
2410   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2411         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
2412    (set (reg:SI T_REG)
2413         (lt:SI (match_dup 1) (const_int 0)))]
2414   "TARGET_SH1"
2415   "shll %0"
2416   [(set_attr "type" "arith")])
2417
2418 (define_insn "ashrsi3_d"
2419   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2420         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2421                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2422   "TARGET_SH3"
2423   "shad %2,%0"
2424   [(set_attr "type" "dyn_shift")])
2425
2426 (define_insn "ashrsi3_n"
2427   [(set (reg:SI R4_REG)
2428         (ashiftrt:SI (reg:SI R4_REG)
2429                      (match_operand:SI 0 "const_int_operand" "i")))
2430    (clobber (reg:SI T_REG))
2431    (clobber (reg:SI PR_REG))
2432    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2433   "TARGET_SH1"
2434   "jsr  @%1%#"
2435   [(set_attr "type" "sfunc")
2436    (set_attr "needs_delay_slot" "yes")])
2437
2438 (define_insn "ashrsi3_media"
2439   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2440         (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
2441                      (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2442   "TARGET_SHMEDIA"
2443   "@
2444         shard.l %1, %2, %0
2445         shari.l %1, %2, %0"
2446   [(set_attr "type" "arith_media")])
2447
2448 (define_expand "ashrsi3"
2449   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2450                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2451                                 (match_operand:SI 2 "nonmemory_operand" "")))
2452               (clobber (reg:SI T_REG))])]
2453   ""
2454   "
2455 {
2456   if (TARGET_SHMEDIA)
2457     {
2458       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
2459       DONE;
2460     }
2461   if (expand_ashiftrt (operands))
2462     DONE;
2463   else
2464     FAIL;
2465 }")
2466
2467 ;; logical shift right
2468
2469 (define_insn "lshrsi3_d"
2470   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2471         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2472                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2473   "TARGET_SH3"
2474   "shld %2,%0"
2475   [(set_attr "type" "dyn_shift")])
2476
2477 ;;  Only the single bit shift clobbers the T bit.
2478
2479 (define_insn "lshrsi3_m"
2480   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2481         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2482                      (match_operand:SI 2 "const_int_operand" "M")))
2483    (clobber (reg:SI T_REG))]
2484   "TARGET_SH1 && CONST_OK_FOR_M (INTVAL (operands[2]))"
2485   "shlr %0"
2486   [(set_attr "type" "arith")])
2487
2488 (define_insn "lshrsi3_k"
2489   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2490         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2491                      (match_operand:SI 2 "const_int_operand" "K")))]
2492   "TARGET_SH1 && CONST_OK_FOR_K (INTVAL (operands[2]))
2493    && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
2494   "shlr%O2      %0"
2495   [(set_attr "type" "arith")])
2496
2497 (define_insn "lshrsi3_n"
2498   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2499         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2500                      (match_operand:SI 2 "const_int_operand" "n")))
2501    (clobber (reg:SI T_REG))]
2502   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
2503   "#"
2504   [(set (attr "length")
2505         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2506                (const_string "2")
2507                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2508                (const_string "4")
2509                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
2510                (const_string "6")]
2511               (const_string "8")))
2512    (set_attr "type" "arith")])
2513
2514 (define_split
2515   [(set (match_operand:SI 0 "arith_reg_operand" "")
2516         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2517                      (match_operand:SI 2 "const_int_operand" "")))
2518    (clobber (reg:SI T_REG))]
2519   "TARGET_SH1 && reload_completed"
2520   [(use (reg:SI R0_REG))]
2521   "
2522 {
2523   gen_shifty_op (LSHIFTRT, operands);
2524   DONE;
2525 }")
2526
2527 (define_insn "lshrsi3_media"
2528   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2529         (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
2530                      (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2531   "TARGET_SHMEDIA"
2532   "@
2533         shlrd.l %1, %2, %0
2534         shlri.l %1, %2, %0"
2535   [(set_attr "type" "arith_media")])
2536
2537 (define_expand "lshrsi3"
2538   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2539                    (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2540                                 (match_operand:SI 2 "nonmemory_operand" "")))
2541               (clobber (reg:SI T_REG))])]
2542   ""
2543   "
2544 {
2545   if (TARGET_SHMEDIA)
2546     {
2547       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
2548       DONE;
2549     }
2550   if (GET_CODE (operands[2]) == CONST_INT
2551       && sh_dynamicalize_shift_p (operands[2]))
2552     operands[2] = force_reg (SImode, operands[2]);
2553   if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
2554     {
2555       rtx count = copy_to_mode_reg (SImode, operands[2]);
2556       emit_insn (gen_negsi2 (count, count));
2557       emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
2558       DONE;
2559     }
2560   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
2561     FAIL;
2562 }")
2563
2564 ;; ??? This should be a define expand.
2565
2566 (define_insn "ashldi3_k"
2567   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2568         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
2569                    (const_int 1)))
2570    (clobber (reg:SI T_REG))]
2571   "TARGET_SH1"
2572   "shll %R0\;rotcl      %S0"
2573   [(set_attr "length" "4")
2574    (set_attr "type" "arith")])
2575
2576 (define_insn "ashldi3_media"
2577   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2578         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2579                    (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2580   "TARGET_SHMEDIA"
2581   "@
2582         shlld   %1, %2, %0
2583         shlli   %1, %2, %0"
2584   [(set_attr "type" "arith_media")])
2585
2586 (define_expand "ashldi3"
2587   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2588                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
2589                               (match_operand:DI 2 "immediate_operand" "")))
2590               (clobber (reg:SI T_REG))])]
2591   ""
2592   "
2593 {
2594   if (TARGET_SHMEDIA)
2595     {
2596       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
2597       DONE;
2598     }
2599   if (GET_CODE (operands[2]) != CONST_INT
2600       || INTVAL (operands[2]) != 1)
2601     FAIL;
2602 }")
2603
2604 ;; ??? This should be a define expand.
2605
2606 (define_insn "lshrdi3_k"
2607   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2608         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
2609                      (const_int 1)))
2610    (clobber (reg:SI T_REG))]
2611   "TARGET_SH1"
2612   "shlr %S0\;rotcr      %R0"
2613   [(set_attr "length" "4")
2614    (set_attr "type" "arith")])
2615
2616 (define_insn "lshrdi3_media"
2617   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2618         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2619                      (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2620   "TARGET_SHMEDIA"
2621   "@
2622         shlrd   %1, %2, %0
2623         shlri   %1, %2, %0"
2624   [(set_attr "type" "arith_media")])
2625
2626 (define_expand "lshrdi3"
2627   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2628                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
2629                                (match_operand:DI 2 "immediate_operand" "")))
2630              (clobber (reg:SI T_REG))])]
2631   ""
2632   "
2633 {
2634   if (TARGET_SHMEDIA)
2635     {
2636       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
2637       DONE;
2638     }
2639   if (GET_CODE (operands[2]) != CONST_INT
2640       || INTVAL (operands[2]) != 1)
2641     FAIL;
2642 }")
2643
2644 ;; ??? This should be a define expand.
2645
2646 (define_insn "ashrdi3_k"
2647   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2648         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
2649                      (const_int 1)))
2650    (clobber (reg:SI T_REG))]
2651   "TARGET_SH1"
2652   "shar %S0\;rotcr      %R0"
2653   [(set_attr "length" "4")
2654    (set_attr "type" "arith")])
2655
2656 (define_insn "ashrdi3_media"
2657   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2658         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2659                      (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2660   "TARGET_SHMEDIA"
2661   "@
2662         shard   %1, %2, %0
2663         shari   %1, %2, %0"
2664   [(set_attr "type" "arith_media")])
2665
2666 (define_expand "ashrdi3"
2667   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2668                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
2669                                 (match_operand:DI 2 "immediate_operand" "")))
2670               (clobber (reg:SI T_REG))])]
2671   ""
2672   "
2673 {
2674   if (TARGET_SHMEDIA)
2675     {
2676       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
2677       DONE;
2678     }
2679   if (GET_CODE (operands[2]) != CONST_INT
2680       || INTVAL (operands[2]) != 1)
2681     FAIL;
2682 }")
2683
2684 ;; combined left/right shift
2685
2686 (define_split
2687   [(set (match_operand:SI 0 "register_operand" "")
2688         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
2689                            (match_operand:SI 2 "const_int_operand" ""))
2690                 (match_operand:SI 3 "const_int_operand" "")))]
2691   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
2692   [(use (reg:SI R0_REG))]
2693   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
2694    DONE;")
2695
2696 (define_split
2697   [(set (match_operand:SI 0 "register_operand" "")
2698         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
2699                            (match_operand:SI 2 "const_int_operand" ""))
2700                 (match_operand:SI 3 "const_int_operand" "")))
2701    (clobber (reg:SI T_REG))]
2702   "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
2703   [(use (reg:SI R0_REG))]
2704   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
2705    DONE;")
2706
2707 (define_insn ""
2708   [(set (match_operand:SI 0 "register_operand" "=r")
2709         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2710                            (match_operand:SI 2 "const_int_operand" "n"))
2711                 (match_operand:SI 3 "const_int_operand" "n")))
2712    (clobber (reg:SI T_REG))]
2713   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
2714  "#"
2715   [(set (attr "length")
2716         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
2717                (const_string "4")
2718                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
2719                (const_string "6")
2720                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
2721                (const_string "8")
2722                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
2723                (const_string "10")
2724                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
2725                (const_string "12")
2726                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
2727                (const_string "14")
2728                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
2729                (const_string "16")]
2730               (const_string "18")))
2731    (set_attr "type" "arith")])
2732
2733 (define_insn ""
2734   [(set (match_operand:SI 0 "register_operand" "=z")
2735         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2736                            (match_operand:SI 2 "const_int_operand" "n"))
2737                 (match_operand:SI 3 "const_int_operand" "n")))
2738    (clobber (reg:SI T_REG))]
2739   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
2740  "#"
2741   [(set (attr "length")
2742         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
2743                (const_string "4")
2744                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
2745                (const_string "6")
2746                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
2747                (const_string "8")]
2748               (const_string "10")))
2749    (set_attr "type" "arith")])
2750
2751 ;; shift left / and combination with a scratch register: The combine pass
2752 ;; does not accept the individual instructions, even though they are
2753 ;; cheap.  But it needs a precise description so that it is usable after
2754 ;; reload.
2755 (define_insn "and_shl_scratch"
2756   [(set (match_operand:SI 0 "register_operand" "=r,&r")
2757         (lshiftrt:SI
2758          (ashift:SI
2759           (and:SI
2760            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
2761                         (match_operand:SI 2 "const_int_operand" "N,n"))
2762            (match_operand:SI 3 "" "0,r"))
2763           (match_operand:SI 4 "const_int_operand" "n,n"))
2764          (match_operand:SI 5 "const_int_operand" "n,n")))
2765    (clobber (reg:SI T_REG))]
2766   "TARGET_SH1"
2767   "#"
2768   [(set (attr "length")
2769         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
2770                (const_string "4")
2771                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
2772                (const_string "6")
2773                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
2774                (const_string "8")
2775                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
2776                (const_string "10")]
2777               (const_string "12")))
2778    (set_attr "type" "arith")])
2779
2780 (define_split
2781   [(set (match_operand:SI 0 "register_operand" "")
2782         (lshiftrt:SI
2783          (ashift:SI
2784           (and:SI
2785            (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
2786                         (match_operand:SI 2 "const_int_operand" ""))
2787            (match_operand:SI 3 "register_operand" ""))
2788           (match_operand:SI 4 "const_int_operand" ""))
2789          (match_operand:SI 5 "const_int_operand" "")))
2790    (clobber (reg:SI T_REG))]
2791   "TARGET_SH1"
2792   [(use (reg:SI R0_REG))]
2793   "
2794 {
2795   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
2796
2797   if (INTVAL (operands[2]))
2798     {
2799       gen_shifty_op (LSHIFTRT, operands);
2800     }
2801   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
2802   operands[2] = operands[4];
2803   gen_shifty_op (ASHIFT, operands);
2804   if (INTVAL (operands[5]))
2805     {
2806       operands[2] = operands[5];
2807       gen_shifty_op (LSHIFTRT, operands);
2808     }
2809   DONE;
2810 }")
2811
2812 ;; signed left/right shift combination.
2813 (define_split
2814   [(set (match_operand:SI 0 "register_operand" "")
2815         (sign_extract:SI
2816          (ashift:SI (match_operand:SI 1 "register_operand" "")
2817                     (match_operand:SI 2 "const_int_operand" ""))
2818          (match_operand:SI 3 "const_int_operand" "")
2819          (const_int 0)))
2820    (clobber (reg:SI T_REG))]
2821   "TARGET_SH1"
2822   [(use (reg:SI R0_REG))]
2823   "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
2824    DONE;")
2825
2826 (define_insn "shl_sext_ext"
2827   [(set (match_operand:SI 0 "register_operand" "=r")
2828         (sign_extract:SI
2829          (ashift:SI (match_operand:SI 1 "register_operand" "0")
2830                     (match_operand:SI 2 "const_int_operand" "n"))
2831          (match_operand:SI 3 "const_int_operand" "n")
2832          (const_int 0)))
2833    (clobber (reg:SI T_REG))]
2834   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
2835   "#"
2836   [(set (attr "length")
2837         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
2838                (const_string "2")
2839                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
2840                (const_string "4")
2841                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
2842                (const_string "6")
2843                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
2844                (const_string "8")
2845                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
2846                (const_string "10")
2847                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
2848                (const_string "12")
2849                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
2850                (const_string "14")
2851                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
2852                (const_string "16")]
2853               (const_string "18")))
2854     (set_attr "type" "arith")])
2855
2856 (define_insn "shl_sext_sub"
2857   [(set (match_operand:SI 0 "register_operand" "=z")
2858         (sign_extract:SI
2859          (ashift:SI (match_operand:SI 1 "register_operand" "0")
2860                     (match_operand:SI 2 "const_int_operand" "n"))
2861          (match_operand:SI 3 "const_int_operand" "n")
2862          (const_int 0)))
2863    (clobber (reg:SI T_REG))]
2864   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
2865   "#"
2866   [(set (attr "length")
2867         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
2868                (const_string "6")
2869                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
2870                (const_string "8")
2871                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
2872                (const_string "10")
2873                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
2874                (const_string "12")]
2875               (const_string "14")))
2876     (set_attr "type" "arith")])
2877
2878 ;; These patterns are found in expansions of DImode shifts by 16, and
2879 ;; allow the xtrct instruction to be generated from C source.
2880
2881 (define_insn "xtrct_left"
2882   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2883         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
2884                            (const_int 16))
2885                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
2886                              (const_int 16))))]
2887   "TARGET_SH1"
2888   "xtrct        %1,%0"
2889   [(set_attr "type" "arith")])
2890
2891 (define_insn "xtrct_right"
2892   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2893         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2894                              (const_int 16))
2895                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
2896                            (const_int 16))))]
2897   "TARGET_SH1"
2898   "xtrct        %2,%0"
2899   [(set_attr "type" "arith")])
2900
2901 ;; -------------------------------------------------------------------------
2902 ;; Unary arithmetic
2903 ;; -------------------------------------------------------------------------
2904
2905 (define_insn "negc"
2906   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2907         (neg:SI (plus:SI (reg:SI T_REG)
2908                          (match_operand:SI 1 "arith_reg_operand" "r"))))
2909    (set (reg:SI T_REG)
2910         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
2911                (const_int 0)))]
2912   "TARGET_SH1"
2913   "negc %1,%0"
2914   [(set_attr "type" "arith")])
2915
2916 (define_insn "*negdi_media"
2917   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2918         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
2919   "TARGET_SHMEDIA"
2920   "sub  r63, %1, %0"
2921   [(set_attr "type" "arith_media")])
2922
2923 (define_expand "negdi2"
2924   [(set (match_operand:DI 0 "arith_reg_operand" "")
2925         (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
2926   ""
2927   "
2928 {
2929   if (TARGET_SH1)
2930     {
2931       int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
2932       int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
2933
2934       rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
2935       rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
2936
2937       rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
2938       rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
2939
2940       emit_insn (gen_clrt ());
2941       emit_insn (gen_negc (low_dst, low_src));
2942       emit_insn (gen_negc (high_dst, high_src));
2943       DONE;
2944     }
2945 }")
2946
2947 (define_insn "negsi2"
2948   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2949         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
2950   "TARGET_SH1"
2951   "neg  %1,%0"
2952   [(set_attr "type" "arith")])
2953
2954 (define_insn "one_cmplsi2"
2955   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2956         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
2957   "TARGET_SH1"
2958   "not  %1,%0"
2959   [(set_attr "type" "arith")])
2960
2961 (define_expand "one_cmpldi2"
2962   [(set (match_operand:DI 0 "arith_reg_operand" "")
2963         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
2964                 (const_int -1)))]
2965   "TARGET_SHMEDIA" "")
2966 \f
2967 ;; -------------------------------------------------------------------------
2968 ;; Zero extension instructions
2969 ;; -------------------------------------------------------------------------
2970
2971 (define_insn "zero_extendsidi2"
2972   [(set (match_operand:DI 0 "register_operand" "=r")
2973         (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
2974   "TARGET_SHMEDIA"
2975   "addz.l       %1, r63, %0"
2976   [(set_attr "type" "arith_media")])
2977
2978 (define_insn "zero_extendhidi2"
2979   [(set (match_operand:DI 0 "register_operand" "=r,r")
2980         (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
2981   "TARGET_SHMEDIA"
2982   "@
2983         #
2984         ld%M1.uw        %m1, %0"
2985   [(set_attr "type" "*,load_media")])
2986
2987 (define_split
2988   [(set (match_operand:DI 0 "register_operand" "")
2989         (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
2990   "TARGET_SHMEDIA && reload_completed"
2991   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
2992    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
2993   "
2994 {
2995   if (GET_CODE (operands[1]) == TRUNCATE)
2996     operands[1] = XEXP (operands[1], 0);
2997 }")
2998
2999 ;; ??? when a truncated input to a zero_extrend is reloaded, reload will
3000 ;; reload the entrire truncate expression.
3001 (define_insn_and_split "*loaddi_trunc"
3002   [(set (match_operand 0 "int_gpr_dest" "=r")
3003         (truncate (match_operand:DI 1 "memory_operand" "m")))]
3004   "TARGET_SHMEDIA && reload_completed"
3005   "#"
3006   "TARGET_SHMEDIA && reload_completed"
3007   [(set (match_dup 0) (match_dup 1))]
3008   "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
3009
3010 (define_insn "zero_extendqidi2"
3011   [(set (match_operand:DI 0 "register_operand" "=r,r")
3012         (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3013   "TARGET_SHMEDIA"
3014   "@
3015         andi    %1, 255, %0
3016         ld%M1.ub        %m1, %0"
3017   [(set_attr "type" "arith_media,load_media")])
3018
3019 (define_expand "zero_extendhisi2"
3020   [(set (match_operand:SI 0 "arith_reg_operand" "")
3021         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
3022   ""
3023   "
3024 {
3025   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
3026     operands[1] = copy_to_mode_reg (HImode, operands[1]);
3027 }")
3028
3029 (define_insn "*zero_extendhisi2_compact"
3030   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
3031         (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
3032   "TARGET_SH1"
3033   "extu.w       %1,%0"
3034   [(set_attr "type" "arith")])
3035
3036 (define_insn "*zero_extendhisi2_media"
3037   [(set (match_operand:SI 0 "register_operand" "=r,r")
3038         (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3039   "TARGET_SHMEDIA"
3040   "@
3041         #
3042         ld%M1.uw        %m1, %0"
3043   [(set_attr "type" "arith_media,load_media")])
3044
3045 (define_split
3046   [(set (match_operand:SI 0 "register_operand" "")
3047         (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
3048   "TARGET_SHMEDIA && reload_completed"
3049   [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 16)))
3050    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
3051   "
3052 {
3053   if (GET_CODE (operands[1]) == TRUNCATE)
3054     operands[1] = XEXP (operands[1], 0);
3055 }")
3056
3057 (define_expand "zero_extendqisi2"
3058   [(set (match_operand:SI 0 "arith_reg_operand" "")
3059         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
3060   ""
3061   "
3062 {
3063   if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
3064     operands[1] = copy_to_mode_reg (QImode, operands[1]);
3065 }")
3066
3067 (define_insn "*zero_extendqisi2_compact"
3068   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
3069         (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
3070   "TARGET_SH1"
3071   "extu.b       %1,%0"
3072   [(set_attr "type" "arith")])
3073
3074 (define_insn "*zero_extendqisi2_media"
3075   [(set (match_operand:SI 0 "register_operand" "=r,r")
3076         (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3077   "TARGET_SHMEDIA"
3078   "@
3079         andi    %1, 255, %0
3080         ld%M1.ub        %m1, %0"
3081   [(set_attr "type" "arith_media,load_media")])
3082
3083 (define_insn "zero_extendqihi2"
3084   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
3085         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
3086   "TARGET_SH1"
3087   "extu.b       %1,%0"
3088   [(set_attr "type" "arith")])
3089
3090 ;; -------------------------------------------------------------------------
3091 ;; Sign extension instructions
3092 ;; -------------------------------------------------------------------------
3093
3094 ;; ??? This should be a define expand.
3095 ;; ??? Or perhaps it should be dropped?
3096
3097 ;; convert_move generates good code for SH[1-4].
3098 (define_insn "extendsidi2"
3099   [(set (match_operand:DI 0 "register_operand" "=r,r")
3100         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
3101   "TARGET_SHMEDIA"
3102   "@
3103         add.l   %1, r63, %0
3104         ld%M1.l %m1, %0"
3105   [(set_attr "type" "arith_media,load_media")])
3106
3107 (define_insn "extendhidi2"
3108   [(set (match_operand:DI 0 "register_operand" "=r,r")
3109         (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3110   "TARGET_SHMEDIA"
3111   "@
3112         #
3113         ld%M1.w %m1, %0"
3114   [(set_attr "type" "*,load_media")])
3115
3116 (define_split
3117   [(set (match_operand:DI 0 "register_operand" "")
3118         (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
3119   "TARGET_SHMEDIA && reload_completed"
3120   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
3121    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
3122   "
3123 {
3124   if (GET_CODE (operands[1]) == TRUNCATE)
3125     operands[1] = XEXP (operands[1], 0);
3126 }")
3127
3128 (define_insn "extendqidi2"
3129   [(set (match_operand:DI 0 "register_operand" "=r,r")
3130         (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3131   "TARGET_SHMEDIA"
3132   "@
3133         #
3134         ld%M1.b %m1, %0"
3135   [(set_attr "type" "*,load_media")])
3136
3137 (define_split
3138   [(set (match_operand:DI 0 "register_operand" "")
3139         (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
3140   "TARGET_SHMEDIA && reload_completed"
3141   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
3142    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
3143   "
3144 {
3145   if (GET_CODE (operands[1]) == TRUNCATE)
3146     operands[1] = XEXP (operands[1], 0);
3147 }")
3148
3149 (define_expand "extendhisi2"
3150   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3151        (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3152   ""
3153   "")
3154
3155 (define_insn "*extendhisi2_compact"
3156   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3157         (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
3158   "TARGET_SH1"
3159   "@
3160         exts.w  %1,%0
3161         mov.w   %1,%0"
3162   [(set_attr "type" "arith,load")])
3163
3164 (define_insn "*extendhisi2_media"
3165   [(set (match_operand:SI 0 "register_operand" "=r,r")
3166         (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
3167   "TARGET_SHMEDIA"
3168   "@
3169         #
3170         ld%M1.w %m1, %0"
3171   [(set_attr "type" "arith_media,load_media")])
3172
3173 (define_split
3174   [(set (match_operand:SI 0 "register_operand" "")
3175         (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
3176   "TARGET_SHMEDIA && reload_completed"
3177   [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 16)))
3178    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
3179   "
3180 {
3181   if (GET_CODE (operands[1]) == TRUNCATE)
3182     operands[1] = XEXP (operands[1], 0);
3183 }")
3184
3185 (define_expand "extendqisi2"
3186   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3187         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3188   ""
3189   "")
3190
3191 (define_insn "*extendqisi2_compact"
3192   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
3193         (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
3194   "TARGET_SH1"
3195   "@
3196         exts.b  %1,%0
3197         mov.b   %1,%0"
3198   [(set_attr "type" "arith,load")])
3199
3200 (define_insn "*extendqisi2_media"
3201   [(set (match_operand:SI 0 "register_operand" "=r,r")
3202         (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
3203   "TARGET_SHMEDIA"
3204   "@
3205         #
3206         ld%M1.b %m1, %0"
3207   [(set_attr "type" "arith_media,load_media")])
3208
3209 (define_split
3210   [(set (match_operand:SI 0 "register_operand" "")
3211         (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
3212   "TARGET_SHMEDIA && reload_completed"
3213   [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 24)))
3214    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
3215    "
3216 {
3217   if (GET_CODE (operands[1]) == TRUNCATE)
3218     operands[1] = XEXP (operands[1], 0);
3219 }")
3220
3221 (define_insn "extendqihi2"
3222   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
3223         (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
3224   "TARGET_SH1"
3225   "@
3226         exts.b  %1,%0
3227         mov.b   %1,%0"
3228   [(set_attr "type" "arith,load")])
3229
3230 /* It would seem useful to combine the truncXi patterns into the movXi
3231    patterns, but unary operators are ignored when matching constraints,
3232    so we need separate patterns.  */
3233 (define_insn "truncdisi2"
3234   [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
3235         (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
3236   "TARGET_SHMEDIA"
3237   "@
3238         add.l   %1, r63, %0
3239         st%M0.l %m0, %1
3240         fst%M0.s        %m0, %T1
3241         fmov.ls %1, %0
3242         fmov.sl %T1, %0
3243         fmov.s  %T1, %0"
3244   [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")])
3245
3246
3247 (define_insn "truncdihi2"
3248   [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
3249         (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
3250   "TARGET_SHMEDIA"
3251   "@
3252         shlli\\t%1,48,%0\;shlri\\t%0,48,%0
3253         st%M0.w %m0, %1"
3254   [(set_attr "type"   "arith_media,store_media")
3255    (set_attr "length" "8,4")])
3256
3257 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
3258 ; Because we use zero extension, we can't provide signed QImode compares
3259 ; using a simple compare or conditional banch insn.
3260 (define_insn "truncdiqi2"
3261   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
3262         (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
3263   "TARGET_SHMEDIA"
3264   "@
3265         and     %1, 255, %0
3266         st%M0.b %m0, %1"
3267   [(set_attr "type"   "arith_media,store")])
3268
3269 ;; -------------------------------------------------------------------------
3270 ;; Move instructions
3271 ;; -------------------------------------------------------------------------
3272
3273 ;; define push and pop so it is easy for sh.c
3274 ;; We can't use push and pop on SHcompact because the stack must always
3275 ;; be 8-byte aligned.
3276
3277 (define_expand "push"
3278   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
3279         (match_operand:SI 0 "register_operand" "r,l,x"))]
3280   "TARGET_SH1 && ! TARGET_SH5"
3281   "")
3282
3283 (define_expand "pop"
3284   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
3285         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
3286   "TARGET_SH1 && ! TARGET_SH5"
3287   "")
3288
3289 (define_expand "push_e"
3290   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
3291                    (match_operand:SF 0 "" ""))
3292               (use (reg:PSI FPSCR_REG))
3293               (clobber (scratch:SI))])]
3294   "TARGET_SH1 && ! TARGET_SH5"
3295   "")
3296
3297 (define_insn "push_fpul"
3298   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
3299   "TARGET_SH3E && ! TARGET_SH5"
3300   "sts.l        fpul,@-r15"
3301   [(set_attr "type" "store")
3302    (set_attr "late_fp_use" "yes")
3303    (set_attr "hit_stack" "yes")])
3304
3305 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
3306 ;; so use that.
3307 (define_expand "push_4"
3308   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
3309                    (match_operand:DF 0 "" ""))
3310               (use (reg:PSI FPSCR_REG))
3311               (clobber (scratch:SI))])]
3312   "TARGET_SH1 && ! TARGET_SH5"
3313   "")
3314
3315 (define_expand "pop_e"
3316   [(parallel [(set (match_operand:SF 0 "" "")
3317               (mem:SF (post_inc:SI (reg:SI SP_REG))))
3318               (use (reg:PSI FPSCR_REG))
3319               (clobber (scratch:SI))])]
3320   "TARGET_SH1 && ! TARGET_SH5"
3321   "")
3322
3323 (define_insn "pop_fpul"
3324   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
3325   "TARGET_SH3E && ! TARGET_SH5"
3326   "lds.l        @r15+,fpul"
3327   [(set_attr "type" "load")
3328    (set_attr "hit_stack" "yes")])
3329
3330 (define_expand "pop_4"
3331   [(parallel [(set (match_operand:DF 0 "" "")
3332                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
3333               (use (reg:PSI FPSCR_REG))
3334               (clobber (scratch:SI))])]
3335   "TARGET_SH1 && ! TARGET_SH5"
3336   "")
3337
3338 (define_expand "push_fpscr"
3339   [(const_int 0)]
3340   "TARGET_SH3E"
3341   "
3342 {
3343   rtx insn = emit_insn (gen_fpu_switch (gen_rtx (MEM, PSImode,
3344                                                  gen_rtx (PRE_DEC, Pmode,
3345                                                           stack_pointer_rtx)),
3346                                         get_fpscr_rtx ()));
3347   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
3348   DONE;
3349 }")
3350
3351 (define_expand "pop_fpscr"
3352   [(const_int 0)]
3353   "TARGET_SH3E"
3354   "
3355 {
3356   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
3357                                         gen_rtx (MEM, PSImode,
3358                                                  gen_rtx (POST_INC, Pmode,
3359                                                           stack_pointer_rtx))));
3360   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
3361   DONE;
3362 }")
3363
3364 ;; These two patterns can happen as the result of optimization, when
3365 ;; comparisons get simplified to a move of zero or 1 into the T reg.
3366 ;; They don't disappear completely, because the T reg is a fixed hard reg.
3367
3368 (define_insn "clrt"
3369   [(set (reg:SI T_REG) (const_int 0))]
3370   "TARGET_SH1"
3371   "clrt")
3372
3373 (define_insn "sett"
3374   [(set (reg:SI T_REG) (const_int 1))]
3375   "TARGET_SH1"
3376   "sett")
3377
3378 ;; t/r must come after r/r, lest reload will try to reload stuff like
3379 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
3380 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
3381 (define_insn "movsi_i"
3382   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
3383         (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
3384   "TARGET_SH1
3385    && ! TARGET_SH3E
3386    && (register_operand (operands[0], SImode)
3387        || register_operand (operands[1], SImode))"
3388   "@
3389         mov.l   %1,%0
3390         mov     %1,%0
3391         cmp/pl  %1
3392         mov.l   %1,%0
3393         sts     %1,%0
3394         sts     %1,%0
3395         movt    %0
3396         mov.l   %1,%0
3397         sts.l   %1,%0
3398         sts.l   %1,%0
3399         lds     %1,%0
3400         lds     %1,%0
3401         lds.l   %1,%0
3402         lds.l   %1,%0
3403         fake    %1,%0"
3404   [(set_attr "type" "pcload_si,move,mt_group,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,pcload_si")
3405    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
3406
3407 ;; t/r must come after r/r, lest reload will try to reload stuff like
3408 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
3409 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
3410 ;; will require a reload.
3411 (define_insn "movsi_ie"
3412   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,y")
3413         (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y"))]
3414   "TARGET_SH3E
3415    && (register_operand (operands[0], SImode)
3416        || register_operand (operands[1], SImode))"
3417   "@
3418         mov.l   %1,%0
3419         mov     %1,%0
3420         cmp/pl  %1
3421         mov.l   %1,%0
3422         sts     %1,%0
3423         sts     %1,%0
3424         movt    %0
3425         mov.l   %1,%0
3426         sts.l   %1,%0
3427         sts.l   %1,%0
3428         lds     %1,%0
3429         lds     %1,%0
3430         lds.l   %1,%0
3431         lds.l   %1,%0
3432         lds.l   %1,%0
3433         sts.l   %1,%0
3434         fake    %1,%0
3435         lds     %1,%0
3436         sts     %1,%0
3437         ! move optimized away"
3438   [(set_attr "type" "pcload_si,move,*,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,load,store,pcload_si,gp_fpul,fpul_gp,nil")
3439    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*")
3440    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
3441
3442 (define_insn "movsi_i_lowpart"
3443   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
3444         (match_operand:SI 1 "general_movsrc_operand" "Q,rI,mr,x,l,t,r,i"))]
3445    "TARGET_SH1
3446     && (register_operand (operands[0], SImode)
3447         || register_operand (operands[1], SImode))"
3448   "@
3449         mov.l   %1,%0
3450         mov     %1,%0
3451         mov.l   %1,%0
3452         sts     %1,%0
3453         sts     %1,%0
3454         movt    %0
3455         mov.l   %1,%0
3456         fake    %1,%0"
3457   [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
3458
3459 (define_insn "*movsi_media"
3460   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,m,f,m,f,r,f,*b,r,b")
3461         (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,m,f,rU,f,f,r,*b,T"))]
3462   "TARGET_SHMEDIA_FPU
3463    && (register_operand (operands[0], SImode)
3464        || register_operand (operands[1], SImode))"
3465   "@
3466         add.l   %1, r63, %0
3467         movi    %1, %0
3468         #
3469         ld%M1.l %m1, %0
3470         st%M0.l %m0, %1
3471         fld%M1.s        %m1, %0
3472         fst%M0.s        %m0, %1
3473         fmov.ls %N1, %0
3474         fmov.sl %1, %0
3475         fmov.s  %1, %0
3476         ptabs   %1, %0
3477         gettr   %1, %0
3478         pt      %1, %0"
3479   [(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")
3480    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")])
3481
3482 (define_insn "*movsi_media_nofpu"
3483   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,m,*b,r,b")
3484         (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,r,*b,T"))]
3485   "TARGET_SHMEDIA
3486    && (register_operand (operands[0], SImode)
3487        || register_operand (operands[1], SImode))"
3488   "@
3489         add.l   %1, r63, %0
3490         movi    %1, %0
3491         #
3492         ld%M1.l %m1, %0
3493         st%M0.l %m0, %1
3494         ptabs   %1, %0
3495         gettr   %1, %0
3496         pt      %1, %0"
3497   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
3498    (set_attr "length" "4,4,8,4,4,4,4,12")])
3499
3500 (define_split
3501   [(set (match_operand:SI 0 "arith_reg_operand" "")
3502         (match_operand:SI 1 "immediate_operand" ""))]
3503   "TARGET_SHMEDIA && reload_completed
3504    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3505   [(set (subreg:DI (match_dup 0) 0) (match_dup 2))]
3506   "
3507 {
3508   operands[2] = shallow_copy_rtx (operands[1]);
3509   PUT_MODE (operands[2], DImode);
3510 }")
3511
3512 (define_split
3513   [(set (match_operand:SI 0 "register_operand" "")
3514         (match_operand:SI 1 "immediate_operand" ""))]
3515   "TARGET_SHMEDIA && reload_completed
3516    && ((GET_CODE (operands[1]) == CONST_INT
3517         && ! CONST_OK_FOR_J (INTVAL (operands[1])))
3518        || GET_CODE (operands[1]) == CONST_DOUBLE)"
3519   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3520
3521 (define_expand "movsi"
3522   [(set (match_operand:SI 0 "general_movdst_operand" "")
3523         (match_operand:SI 1 "general_movsrc_operand" ""))]
3524   ""
3525   "{ if (prepare_move_operands (operands, SImode)) DONE; }")
3526
3527 (define_expand "ic_invalidate_line"
3528   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
3529                                 (match_dup 1)] UNSPEC_ICACHE)
3530               (clobber (scratch:SI))])]
3531   "TARGET_HARD_SH4 || TARGET_SH5"
3532   "
3533 {
3534   if (TARGET_SHMEDIA)
3535     {
3536       emit_insn (gen_ic_invalidate_line_media (operands[0]));
3537       DONE;
3538     }
3539   else if (TARGET_SHCOMPACT)
3540     {
3541       operands[1] = gen_rtx_SYMBOL_REF (Pmode, \"__ic_invalidate\");
3542       operands[1] = force_reg (Pmode, operands[1]);
3543       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
3544       DONE;
3545     }
3546   operands[0] = force_reg (Pmode, operands[0]);
3547   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
3548                                                                Pmode)));
3549 }")
3550
3551 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
3552 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
3553 ;; the requirement *1*00 for associative address writes.  The alignment of
3554 ;; %0 implies that its least significant bit is cleared,
3555 ;; thus we clear the V bit of a matching entry if there is one.
3556 (define_insn "ic_invalidate_line_i"
3557   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
3558                      (match_operand:SI 1 "register_operand" "r")]
3559                      UNSPEC_ICACHE)
3560    (clobber (match_scratch:SI 2 "=&r"))]
3561   "TARGET_HARD_SH4"
3562   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
3563   [(set_attr "length" "8")
3564    (set_attr "type" "cwb")])
3565
3566 ;; ??? could make arg 0 an offsettable memory operand to allow to save
3567 ;; an add in the code that calculates the address.
3568 (define_insn "ic_invalidate_line_media"
3569   [(unspec_volatile [(match_operand 0 "register_operand" "r")]
3570                     UNSPEC_ICACHE)]
3571   "TARGET_SHMEDIA"
3572   "ocbwb        %0,0\;synco\;icbi       %0, 0\;synci"
3573   [(set_attr "length" "16")
3574    (set_attr "type" "invalidate_line_media")])
3575
3576 (define_insn "ic_invalidate_line_compact"
3577   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
3578                      (match_operand:SI 1 "register_operand" "r")]
3579                     UNSPEC_ICACHE)
3580    (clobber (reg:SI PR_REG))]
3581   "TARGET_SHCOMPACT"
3582   "jsr @%1%#"
3583   [(set_attr "type" "sfunc")
3584    (set_attr "needs_delay_slot" "yes")])
3585
3586 (define_expand "initialize_trampoline"
3587   [(match_operand:SI 0 "" "")
3588    (match_operand:SI 1 "" "")
3589    (match_operand:SI 2 "" "")]
3590   "TARGET_SHCOMPACT"
3591   "
3592 {
3593   rtx sfun, tramp;
3594
3595   tramp = force_reg (Pmode, operands[0]);
3596   sfun = force_reg (Pmode, gen_rtx_SYMBOL_REF (Pmode, \"__init_trampoline\"));
3597   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
3598   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
3599
3600   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
3601   DONE;
3602 }")
3603
3604 (define_insn "initialize_trampoline_compact"
3605   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
3606                      (match_operand:SI 1 "register_operand" "r")
3607                      (reg:SI R2_REG) (reg:SI R3_REG)]
3608                     UNSPEC_INIT_TRAMP)
3609
3610    (clobber (reg:SI PR_REG))]
3611   "TARGET_SHCOMPACT"
3612   "jsr @%1%#"
3613   [(set_attr "type" "sfunc")
3614    (set_attr "needs_delay_slot" "yes")])
3615
3616 (define_insn "movqi_i"
3617   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l")
3618         (match_operand:QI 1 "general_movsrc_operand"  "ri,m,r,t,l,r"))]
3619   "TARGET_SH1
3620    && (arith_reg_operand (operands[0], QImode)
3621        || arith_reg_operand (operands[1], QImode))"
3622   "@
3623         mov     %1,%0
3624         mov.b   %1,%0
3625         mov.b   %1,%0
3626         movt    %0
3627         sts     %1,%0
3628         lds     %1,%0"
3629  [(set_attr "type" "move,load,store,move,move,move")])
3630
3631 (define_insn "*movqi_media"
3632   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
3633         (match_operand:QI 1 "general_movsrc_operand" "r,JS,m,r"))]
3634   "TARGET_SHMEDIA
3635    && (arith_reg_operand (operands[0], QImode)
3636        || arith_reg_operand (operands[1], QImode))"
3637   "@
3638         add.l   %1, r63, %0
3639         movi    %1, %0
3640         ld%M1.ub        %m1, %0
3641         st%M0.b %m0, %1"
3642   [(set_attr "type" "arith_media,arith_media,load_media,store_media")])
3643
3644 (define_expand "movqi"
3645   [(set (match_operand:QI 0 "general_operand" "")
3646         (match_operand:QI 1 "general_operand"  ""))]
3647   ""
3648   "{ if (prepare_move_operands (operands, QImode)) DONE; }")
3649
3650 (define_expand "reload_inqi"
3651   [(set (match_operand:SI 2 "" "=&r")
3652         (match_operand:QI 1 "inqhi_operand" ""))
3653    (set (match_operand:QI 0 "arith_reg_operand" "=r")
3654         (truncate:HI (match_dup 3)))]
3655   "TARGET_SHMEDIA"
3656   "
3657 {
3658   rtx inner = XEXP (operands[1], 0);
3659   int regno = REGNO (inner);
3660
3661   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
3662   operands[1] = gen_rtx_REG (SImode, regno);
3663   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
3664 }")
3665
3666 (define_insn "movhi_i"
3667   [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r")
3668         (match_operand:HI 1 "general_movsrc_operand" "Q,rI,m,t,r,l,r,i"))]
3669   "TARGET_SH1
3670    && (arith_reg_operand (operands[0], HImode)
3671        || arith_reg_operand (operands[1], HImode))"
3672   "@
3673         mov.w   %1,%0
3674         mov     %1,%0
3675         mov.w   %1,%0
3676         movt    %0
3677         mov.w   %1,%0
3678         sts     %1,%0
3679         lds     %1,%0
3680         fake    %1,%0"
3681   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
3682
3683 (define_insn "*movhi_media"
3684   [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
3685         (match_operand:HI 1 "general_movsrc_operand" "r,JS,n,m,r"))]
3686   "TARGET_SHMEDIA
3687    && (arith_reg_operand (operands[0], HImode)
3688        || arith_reg_operand (operands[1], HImode))"
3689   "@
3690         add.l   %1, r63, %0
3691         movi    %1, %0
3692         #
3693         ld%M1.w %m1, %0
3694         st%M0.w %m0, %1"
3695   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")])
3696
3697 (define_split
3698   [(set (match_operand:HI 0 "register_operand" "")
3699         (match_operand:HI 1 "immediate_operand" ""))]
3700   "TARGET_SHMEDIA && reload_completed
3701    && ! CONST_OK_FOR_J (INTVAL (operands[1]))"
3702   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3703
3704 (define_expand "movhi"
3705   [(set (match_operand:HI 0 "general_movdst_operand" "")
3706         (match_operand:HI 1 "general_movsrc_operand"  ""))]
3707   ""
3708   "{ if (prepare_move_operands (operands, HImode)) DONE; }")
3709
3710 (define_expand "reload_inhi"
3711   [(set (match_operand:SI 2 "" "=&r")
3712         (match_operand:HI 1 "inqhi_operand" ""))
3713    (set (match_operand:HI 0 "arith_reg_operand" "=r")
3714         (truncate:HI (match_dup 3)))]
3715   "TARGET_SHMEDIA"
3716   "
3717 {
3718   rtx inner = XEXP (operands[1], 0);
3719   int regno = REGNO (inner);
3720
3721   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
3722   operands[1] = gen_rtx_REG (SImode, regno);
3723   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
3724 }")
3725
3726 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
3727 ;; compiled with -m2 -ml -O3 -funroll-loops
3728 (define_insn "*movdi_i"
3729   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
3730         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I,i,x,r"))]
3731   "TARGET_SH1
3732    && (arith_reg_operand (operands[0], DImode)
3733        || arith_reg_operand (operands[1], DImode))"
3734   "* return output_movedouble (insn, operands, DImode);"
3735   [(set_attr "length" "4")
3736    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
3737
3738 ;; If the output is a register and the input is memory or a register, we have
3739 ;; to be careful and see which word needs to be loaded first.
3740
3741 (define_split
3742   [(set (match_operand:DI 0 "general_movdst_operand" "")
3743         (match_operand:DI 1 "general_movsrc_operand" ""))]
3744   "TARGET_SH1 && reload_completed"
3745   [(set (match_dup 2) (match_dup 3))
3746    (set (match_dup 4) (match_dup 5))]
3747   "
3748 {
3749   int regno;
3750
3751   if ((GET_CODE (operands[0]) == MEM
3752        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
3753       || (GET_CODE (operands[1]) == MEM
3754           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
3755     FAIL;
3756
3757   if (GET_CODE (operands[0]) == REG)
3758     regno = REGNO (operands[0]);
3759   else if (GET_CODE (operands[0]) == SUBREG)
3760     regno = subreg_regno (operands[0]);
3761   else if (GET_CODE (operands[0]) == MEM)
3762     regno = -1;
3763   else
3764     abort ();
3765
3766   if (regno == -1
3767       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
3768     {
3769       operands[2] = operand_subword (operands[0], 0, 0, DImode);
3770       operands[3] = operand_subword (operands[1], 0, 0, DImode);
3771       operands[4] = operand_subword (operands[0], 1, 0, DImode);
3772       operands[5] = operand_subword (operands[1], 1, 0, DImode);
3773     }
3774   else
3775     {
3776       operands[2] = operand_subword (operands[0], 1, 0, DImode);
3777       operands[3] = operand_subword (operands[1], 1, 0, DImode);
3778       operands[4] = operand_subword (operands[0], 0, 0, DImode);
3779       operands[5] = operand_subword (operands[1], 0, 0, DImode);
3780     }
3781
3782   if (operands[2] == 0 || operands[3] == 0
3783       || operands[4] == 0 || operands[5] == 0)
3784     FAIL;
3785 }")
3786
3787 (define_insn "*movdi_media"
3788   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,f,m,f,r,f,*b,r,b")
3789         (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,m,f,rU,f,f,r,*b,T"))]
3790   "TARGET_SHMEDIA_FPU
3791    && (register_operand (operands[0], DImode)
3792        || register_operand (operands[1], DImode))"
3793   "@
3794         add     %1, r63, %0
3795         movi    %1, %0
3796         #
3797         ld%M1.q %m1, %0
3798         st%M0.q %m0, %1
3799         fld%M1.d        %m1, %0
3800         fst%M0.d        %m0, %1
3801         fmov.qd %N1, %0
3802         fmov.dq %1, %0
3803         fmov.d  %1, %0
3804         ptabs   %1, %0
3805         gettr   %1, %0
3806         pt      %1, %0"
3807   [(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")
3808    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
3809
3810 (define_insn "*movdi_media_nofpu"
3811   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,b")
3812         (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,r,*b,T"))]
3813   "TARGET_SHMEDIA
3814    && (register_operand (operands[0], DImode)
3815        || register_operand (operands[1], DImode))"
3816   "@
3817         add     %1, r63, %0
3818         movi    %1, %0
3819         #
3820         ld%M1.q %m1, %0
3821         st%M0.q %m0, %1
3822         ptabs   %1, %0
3823         gettr   %1, %0
3824         pt      %1, %0"
3825   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
3826    (set_attr "length" "4,4,16,4,4,4,4,*")])
3827
3828 (define_split
3829   [(set (match_operand:DI 0 "arith_reg_operand" "")
3830         (match_operand:DI 1 "immediate_operand" ""))]
3831   "TARGET_SHMEDIA && reload_completed
3832    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3833   [(set (match_dup 0) (match_dup 1))]
3834   "
3835 {
3836   rtx insn;
3837
3838   if (TARGET_SHMEDIA64)
3839     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
3840   else
3841     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
3842
3843   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
3844                                         REG_NOTES (insn));
3845
3846   DONE;
3847 }")
3848
3849 (define_expand "movdi_const"
3850   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3851         (const:DI (sign_extend:DI
3852                    (truncate:HI
3853                     (ashiftrt:DI
3854                      (match_operand:DI 1 "immediate_operand" "s")
3855                      (const_int 48))))))
3856    (set (match_dup 0)
3857         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3858                 (zero_extend:DI
3859                  (truncate:HI
3860                   (const:DI
3861                    (sign_extend:DI
3862                     (truncate:HI
3863                      (ashiftrt:SI
3864                       (match_dup 1)
3865                       (const_int 32)))))))))
3866    (set (match_dup 0)
3867         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3868                 (zero_extend:DI
3869                  (truncate:HI
3870                   (const:DI
3871                    (sign_extend:DI
3872                     (truncate:HI
3873                      (ashiftrt:SI
3874                       (match_dup 1)
3875                       (const_int 16)))))))))
3876    (set (match_dup 0)
3877         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3878                 (zero_extend:DI
3879                  (truncate:HI
3880                   (const:DI
3881                    (sign_extend:DI
3882                     (truncate:HI
3883                      (match_dup 1))))))))]
3884   "TARGET_SHMEDIA64 && reload_completed
3885    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3886   "
3887 {
3888   sh_mark_label (operands[1], 4);
3889 }")
3890
3891 (define_expand "movdi_const_32bit"
3892   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3893         (const:DI (sign_extend:DI
3894                    (truncate:HI
3895                     (ashiftrt:DI
3896                      (match_operand:DI 1 "immediate_operand" "s")
3897                      (const_int 16))))))
3898    (set (match_dup 0)
3899         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3900                 (zero_extend:DI
3901                  (truncate:HI
3902                   (const:DI
3903                    (sign_extend:DI
3904                     (truncate:HI
3905                      (match_dup 1))))))))]
3906   "TARGET_SHMEDIA32 && reload_completed
3907    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3908   "
3909 {
3910   sh_mark_label (operands[1], 2);
3911 }")
3912
3913 (define_expand "movdi_const_16bit"
3914   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3915         (const:DI (sign_extend:DI
3916                    (truncate:HI
3917                     (match_operand:DI 1 "immediate_operand" "s")))))]
3918   "TARGET_SHMEDIA && flag_pic && reload_completed
3919    && GET_CODE (operands[1]) == SYMBOL_REF"
3920   "")
3921
3922 (define_split
3923   [(set (match_operand:DI 0 "arith_reg_operand" "")
3924         (match_operand:DI 1 "immediate_operand" ""))]
3925   "TARGET_SHMEDIA && reload_completed
3926    && GET_CODE (operands[1]) == CONST_INT
3927    && ! CONST_OK_FOR_J (INTVAL (operands[1]))"
3928   [(set (match_dup 0) (match_dup 2))
3929    (match_dup 1)]
3930   "
3931 {
3932   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3933   unsigned HOST_WIDE_INT low = val;
3934   unsigned HOST_WIDE_INT high = val;
3935   unsigned HOST_WIDE_INT sign;
3936   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
3937
3938   /* Sign-extend the 16 least-significant bits.  */
3939   low &= 0xffff;
3940   low ^= 0x8000;
3941   low -= 0x8000;
3942
3943   /* Arithmetic shift right the word by 16 bits.  */
3944   high >>= 16;
3945   sign = 1;
3946   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
3947   high ^= sign;
3948   high -= sign;
3949   do
3950     {
3951       /* If we can't generate the constant with a two-insn movi / shori
3952          sequence, try some other strategies.  */
3953       if (! CONST_OK_FOR_J (high))
3954         {
3955           /* Try constant load / left shift.  We know VAL != 0.  */
3956           val2 = val ^ (val-1);
3957           if (val2 > 0x1ffff)
3958             {
3959               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
3960
3961               if (CONST_OK_FOR_J (val >> trailing_zeroes)
3962                   || (! CONST_OK_FOR_J (high >> 16)
3963                       && CONST_OK_FOR_J (val >> (trailing_zeroes + 16))))
3964                 {
3965                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
3966                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
3967                                                    GEN_INT (trailing_zeroes));
3968                   break;
3969                 }
3970             }
3971           /* Try constant load / right shift.  */
3972           val2 = (val >> 15) + 1;
3973           if (val2 == (val2 & -val2))
3974             {
3975               int shift = 49 - exact_log2 (val2);
3976
3977               val2 = trunc_int_for_mode (val << shift, DImode);
3978               if (CONST_OK_FOR_J (val2))
3979                 {
3980                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
3981                                                    GEN_INT (shift));
3982                   break;
3983                 }
3984             }
3985           /* Try mperm.w .  */
3986           val2 = val & 0xffff;
3987           if ((val >> 16 & 0xffff) == val2
3988               && (val >> 32 & 0xffff) == val2
3989               && (val >> 48 & 0xffff) == val2)
3990             {
3991               val2 = (HOST_WIDE_INT) val >> 48;
3992               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
3993               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
3994               break;
3995             }
3996           /* Try movi / mshflo.l  */
3997           val2 = (HOST_WIDE_INT) val >> 32;
3998           if (val2 == trunc_int_for_mode (val, SImode))
3999             {
4000               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
4001                                              operands[0]);
4002               break;
4003             }
4004           /* Try movi / mshflo.l w/ r63.  */
4005           val2 = val + ((HOST_WIDE_INT) -1 << 32);
4006           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_J (val2))
4007             {
4008               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
4009                                              GEN_INT (0));
4010               break;
4011             }
4012         }
4013       val2 = high;
4014       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
4015     }
4016   while (0);
4017   operands[2] = GEN_INT (val2);
4018 }")
4019
4020 (define_split
4021   [(set (match_operand:DI 0 "arith_reg_operand" "")
4022         (match_operand:DI 1 "immediate_operand" ""))]
4023   "TARGET_SHMEDIA && reload_completed
4024    && GET_CODE (operands[1]) == CONST_DOUBLE"
4025   [(set (match_dup 0) (match_dup 2))
4026   (set (match_dup 0)
4027        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
4028                (zero_extend:DI (truncate:HI (match_dup 1)))))]
4029   "
4030 {
4031   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
4032   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
4033   unsigned HOST_WIDE_INT val = low;
4034   unsigned HOST_WIDE_INT sign;
4035
4036   /* Sign-extend the 16 least-significant bits.  */
4037   val &= 0xffff;
4038   val ^= 0x8000;
4039   val -= 0x8000;
4040   operands[1] = GEN_INT (val);
4041
4042   /* Arithmetic shift right the double-word by 16 bits.  */
4043   low >>= 16;
4044   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
4045   high >>= 16;
4046   sign = 1;
4047   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
4048   high ^= sign;
4049   high -= sign;
4050
4051   /* This will only be true if high is a sign-extension of low, i.e.,
4052      it must be either 0 or (unsigned)-1, and be zero iff the
4053      most-significant bit of low is set.  */
4054   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
4055     operands[2] = GEN_INT (low);
4056   else
4057     operands[2] = immed_double_const (low, high, DImode);
4058 }")
4059
4060 (define_insn "shori_media"
4061   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
4062         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
4063                            (const_int 16))
4064                 (zero_extend:DI
4065                  (truncate:HI
4066                   (match_operand:DI 2 "immediate_operand" "JS,nF")))))]
4067   "TARGET_SHMEDIA"
4068   "@
4069         shori   %u2, %0
4070         #"
4071   [(set_attr "type" "arith_media,*")])
4072
4073 (define_expand "movdi"
4074   [(set (match_operand:DI 0 "general_movdst_operand" "")
4075         (match_operand:DI 1 "general_movsrc_operand" ""))]
4076   ""
4077   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
4078
4079 (define_insn "movdf_media"
4080   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
4081         (match_operand:DF 1 "general_movsrc_operand" "f,rU,f,r,F,m,f,m,r"))]
4082   "TARGET_SHMEDIA_FPU
4083    && (register_operand (operands[0], DFmode)
4084        || register_operand (operands[1], DFmode))"
4085   "@
4086         fmov.d  %1, %0
4087         fmov.qd %N1, %0
4088         fmov.dq %1, %0
4089         add     %1, r63, %0
4090         #
4091         fld%M1.d        %m1, %0
4092         fst%M0.d        %m0, %1
4093         ld%M1.q %m1, %0
4094         st%M0.q %m0, %1"
4095   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
4096
4097 (define_insn "movdf_media_nofpu"
4098   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
4099         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,r"))]
4100   "TARGET_SHMEDIA
4101    && (register_operand (operands[0], DFmode)
4102        || register_operand (operands[1], DFmode))"
4103   "@
4104         add     %1, r63, %0
4105         #
4106         ld%M1.q %m1, %0
4107         st%M0.q %m0, %1"
4108   [(set_attr "type" "arith_media,*,load_media,store_media")])
4109
4110 (define_split
4111   [(set (match_operand:DF 0 "arith_reg_operand" "")
4112         (match_operand:DF 1 "immediate_operand" ""))]
4113   "TARGET_SHMEDIA && reload_completed"
4114   [(set (match_dup 3) (match_dup 2))]
4115   "
4116 {
4117   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
4118   long values[2];
4119   REAL_VALUE_TYPE value;
4120
4121   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
4122   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
4123
4124   if (HOST_BITS_PER_WIDE_INT >= 64)
4125     operands[2] = immed_double_const ((unsigned long) values[endian]
4126                                       | ((HOST_WIDE_INT) values[1 - endian]
4127                                          << 32), 0, DImode);
4128   else if (HOST_BITS_PER_WIDE_INT == 32)
4129     operands[2] = immed_double_const (values[endian], values[1 - endian],
4130                                       DImode);
4131   else
4132     abort ();
4133
4134   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4135 }")
4136
4137 ;; ??? This should be a define expand.
4138
4139 (define_insn "movdf_k"
4140   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
4141         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
4142   "TARGET_SH1
4143    && (! TARGET_SH4 || reload_completed
4144        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
4145        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
4146        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
4147    && (arith_reg_operand (operands[0], DFmode)
4148        || arith_reg_operand (operands[1], DFmode))"
4149   "* return output_movedouble (insn, operands, DFmode);"
4150   [(set_attr "length" "4")
4151    (set_attr "type" "move,pcload,load,store")])
4152
4153 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
4154 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
4155 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
4156 ;; the d/m/c/X alternative, which is split later into single-precision
4157 ;; instructions.  And when not optimizing, no splits are done before fixing
4158 ;; up pcloads, so we need usable length information for that.
4159 (define_insn "movdf_i4"
4160   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
4161         (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
4162    (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
4163    (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
4164   "TARGET_SH4
4165    && (arith_reg_operand (operands[0], DFmode)
4166        || arith_reg_operand (operands[1], DFmode))"
4167   "@
4168         fmov    %1,%0
4169         #
4170         #
4171         fmov.d  %1,%0
4172         fmov.d  %1,%0
4173         #
4174         #
4175         #
4176         #
4177         #"
4178   [(set_attr_alternative "length"
4179      [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
4180       (const_int 4)
4181       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
4182       (if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 6))
4183       (if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 6))
4184       (const_int 4)
4185       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
4186       ;; We can't use 4-byte push/pop on SHcompact, so we have to
4187       ;; increment or decrement r15 explicitly.
4188       (if_then_else
4189        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
4190        (const_int 10) (const_int 8))
4191       (if_then_else
4192        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
4193        (const_int 10) (const_int 8))])
4194    (set_attr "type" "fmove,move,pcfload,fload,store,pcload,load,store,load,fload")
4195    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
4196    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
4197                                            (const_string "double")
4198                                            (const_string "none")))])
4199
4200 ;; Moving DFmode between fp/general registers through memory
4201 ;; (the top of the stack) is faster than moving through fpul even for
4202 ;; little endian.  Because the type of an instruction is important for its
4203 ;; scheduling,  it is beneficial to split these operations, rather than
4204 ;; emitting them in one single chunk, even if this will expose a stack
4205 ;; use that will prevent scheduling of other stack accesses beyond this
4206 ;; instruction.
4207 (define_split
4208   [(set (match_operand:DF 0 "register_operand" "")
4209         (match_operand:DF 1 "register_operand" ""))
4210    (use (match_operand:PSI 2 "fpscr_operand" ""))
4211    (clobber (match_scratch:SI 3 "=X"))]
4212   "TARGET_SH4 && reload_completed
4213    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
4214   [(const_int 0)]
4215   "
4216 {
4217   rtx insn, tos;
4218
4219   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
4220     {
4221       emit_move_insn (stack_pointer_rtx,
4222                       plus_constant (stack_pointer_rtx, -8));
4223       tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
4224     }
4225   else
4226     tos = gen_rtx (MEM, DFmode, gen_rtx (PRE_DEC, Pmode, stack_pointer_rtx));
4227   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
4228   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
4229     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
4230   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
4231     tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
4232   else
4233     tos = gen_rtx (MEM, DFmode, gen_rtx (POST_INC, Pmode, stack_pointer_rtx));
4234   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
4235   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
4236     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
4237   else
4238     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
4239   DONE;
4240 }")
4241
4242 ;; local-alloc sometimes allocates scratch registers even when not required,
4243 ;; so we must be prepared to handle these.
4244
4245 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
4246 (define_split
4247   [(set (match_operand:DF 0 "general_movdst_operand" "")
4248         (match_operand:DF 1 "general_movsrc_operand"  ""))
4249    (use (match_operand:PSI 2 "fpscr_operand" ""))
4250    (clobber (match_scratch:SI 3 ""))]
4251   "TARGET_SH4
4252    && reload_completed
4253    && true_regnum (operands[0]) < 16
4254    && true_regnum (operands[1]) < 16"
4255   [(set (match_dup 0) (match_dup 1))]
4256   "
4257 {
4258   /* If this was a reg <-> mem operation with base + index reg addressing,
4259      we have to handle this in a special way.  */
4260   rtx mem = operands[0];
4261   int store_p = 1;
4262   if (! memory_operand (mem, DFmode))
4263     {
4264       mem = operands[1];
4265       store_p = 0;
4266     }
4267   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
4268     mem = SUBREG_REG (mem);
4269   if (GET_CODE (mem) == MEM)
4270     {
4271       rtx addr = XEXP (mem, 0);
4272       if (GET_CODE (addr) == PLUS
4273           && GET_CODE (XEXP (addr, 0)) == REG
4274           && GET_CODE (XEXP (addr, 1)) == REG)
4275         {
4276           int offset;
4277           rtx reg0 = gen_rtx (REG, Pmode, 0);
4278           rtx regop = operands[store_p], word0 ,word1;
4279
4280           if (GET_CODE (regop) == SUBREG)
4281             alter_subreg (&regop);
4282           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
4283             offset = 2;
4284           else
4285             offset = 4;
4286           mem = copy_rtx (mem);
4287           PUT_MODE (mem, SImode);
4288           word0 = gen_rtx (SUBREG, SImode, regop, 0);
4289           alter_subreg (&word0);
4290           word1 = gen_rtx (SUBREG, SImode, regop, 4);
4291           alter_subreg (&word1);
4292           if (store_p || ! refers_to_regno_p (REGNO (word0),
4293                                               REGNO (word0) + 1, addr, 0))
4294             {
4295               emit_insn (store_p
4296                          ? gen_movsi_ie (mem, word0)
4297                          : gen_movsi_ie (word0, mem));
4298               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
4299               mem = copy_rtx (mem);
4300               emit_insn (store_p
4301                          ? gen_movsi_ie (mem, word1)
4302                          : gen_movsi_ie (word1, mem));
4303               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
4304             }
4305           else
4306             {
4307               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
4308               emit_insn (gen_movsi_ie (word1, mem));
4309               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
4310               mem = copy_rtx (mem);
4311               emit_insn (gen_movsi_ie (word0, mem));
4312             }
4313           DONE;
4314         }
4315     }
4316 }")
4317
4318 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
4319 (define_split
4320   [(set (match_operand:DF 0 "register_operand" "")
4321         (match_operand:DF 1 "memory_operand"  ""))
4322    (use (match_operand:PSI 2 "fpscr_operand" ""))
4323    (clobber (reg:SI R0_REG))]
4324   "TARGET_SH4 && reload_completed"
4325   [(parallel [(set (match_dup 0) (match_dup 1))
4326               (use (match_dup 2))
4327               (clobber (scratch:SI))])]
4328   "")
4329
4330 (define_expand "reload_indf"
4331   [(parallel [(set (match_operand:DF 0 "register_operand" "=f")
4332                    (match_operand:DF 1 "immediate_operand" "FQ"))
4333               (use (reg:PSI FPSCR_REG))
4334               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4335   "TARGET_SH1"
4336   "")
4337
4338 (define_expand "reload_outdf"
4339   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
4340                    (match_operand:DF 1 "register_operand" "af,r"))
4341               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
4342   "TARGET_SH1"
4343   "")
4344
4345 ;; Simplify no-op moves.
4346 (define_split
4347   [(set (match_operand:SF 0 "register_operand" "")
4348         (match_operand:SF 1 "register_operand" ""))
4349    (use (match_operand:PSI 2 "fpscr_operand" ""))
4350    (clobber (match_scratch:SI 3 "X"))]
4351   "TARGET_SH3E && reload_completed
4352    && true_regnum (operands[0]) == true_regnum (operands[1])"
4353   [(set (match_dup 0) (match_dup 0))]
4354   "")
4355
4356 ;; fmovd substitute post-reload splits
4357 (define_split
4358   [(set (match_operand:DF 0 "register_operand" "")
4359         (match_operand:DF 1 "register_operand" ""))
4360    (use (match_operand:PSI 2 "fpscr_operand" ""))
4361    (clobber (match_scratch:SI 3 "X"))]
4362   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4363    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
4364    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
4365   [(const_int 0)]
4366   "
4367 {
4368   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
4369   emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, dst),
4370                            gen_rtx (REG, SFmode, src), operands[2]));
4371   emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, dst + 1),
4372                            gen_rtx (REG, SFmode, src + 1), operands[2]));
4373   DONE;
4374 }")
4375
4376 (define_split
4377   [(set (match_operand:DF 0 "register_operand" "")
4378         (mem:DF (match_operand:SI 1 "register_operand" "")))
4379    (use (match_operand:PSI 2 "fpscr_operand" ""))
4380    (clobber (match_scratch:SI 3 ""))]
4381   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4382    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
4383    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
4384   [(const_int 0)]
4385   "
4386 {
4387   int regno = true_regnum (operands[0]);
4388   rtx insn;
4389   rtx mem2 = gen_rtx (MEM, SFmode, gen_rtx (POST_INC, Pmode, operands[1]));
4390
4391   insn = emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode,
4392                                            regno + !! TARGET_LITTLE_ENDIAN),
4393                                   mem2, operands[2]));
4394   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[1], NULL_RTX);
4395   insn = emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode,
4396                                            regno + ! TARGET_LITTLE_ENDIAN),
4397                                   gen_rtx (MEM, SFmode, operands[1]),
4398                                   operands[2]));
4399   DONE;
4400 }")
4401
4402 (define_split
4403   [(set (match_operand:DF 0 "register_operand" "")
4404         (match_operand:DF 1 "memory_operand" ""))
4405    (use (match_operand:PSI 2 "fpscr_operand" ""))
4406    (clobber (match_scratch:SI 3 ""))]
4407   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4408    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
4409   [(const_int 0)]
4410   "
4411 {
4412   int regno = true_regnum (operands[0]);
4413   rtx addr, insn, adjust = NULL_RTX;
4414   rtx mem2 = copy_rtx (operands[1]);
4415   rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
4416   rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
4417
4418   PUT_MODE (mem2, SFmode);
4419   operands[1] = copy_rtx (mem2);
4420   addr = XEXP (mem2, 0);
4421   if (GET_CODE (addr) != POST_INC)
4422     {
4423       /* If we have to modify the stack pointer, the value that we have
4424          read with post-increment might be modified by an interrupt,
4425          so write it back.  */
4426       if (REGNO (addr) == STACK_POINTER_REGNUM)
4427         adjust = gen_push_e (reg0);
4428       else
4429         adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
4430       XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
4431     }
4432   addr = XEXP (addr, 0);
4433   insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
4434   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4435   insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
4436   if (adjust)
4437     emit_insn (adjust);
4438   else
4439     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4440   DONE;
4441 }")
4442
4443 (define_split
4444   [(set (match_operand:DF 0 "memory_operand" "")
4445         (match_operand:DF 1 "register_operand" ""))
4446    (use (match_operand:PSI 2 "fpscr_operand" ""))
4447    (clobber (match_scratch:SI 3 ""))]
4448   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4449    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
4450   [(const_int 0)]
4451   "
4452 {
4453   int regno = true_regnum (operands[1]);
4454   rtx insn, addr, adjust = NULL_RTX;
4455
4456   operands[0] = copy_rtx (operands[0]);
4457   PUT_MODE (operands[0], SFmode);
4458   insn = emit_insn (gen_movsf_ie (operands[0],
4459                                   gen_rtx (REG, SFmode,
4460                                            regno + ! TARGET_LITTLE_ENDIAN),
4461                                   operands[2]));
4462   operands[0] = copy_rtx (operands[0]);
4463   addr = XEXP (operands[0], 0);
4464   if (GET_CODE (addr) != PRE_DEC)
4465     {
4466       adjust = gen_addsi3 (addr, addr, GEN_INT (4));
4467       emit_insn_before (adjust, insn);
4468       XEXP (operands[0], 0) = addr = gen_rtx (PRE_DEC, SImode, addr);
4469     }
4470   addr = XEXP (addr, 0);
4471   if (! adjust)
4472     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, addr, NULL_RTX);
4473   insn = emit_insn (gen_movsf_ie (operands[0],
4474                                   gen_rtx (REG, SFmode,
4475                                            regno + !! TARGET_LITTLE_ENDIAN),
4476                                   operands[2]));
4477   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, addr, NULL_RTX);
4478   DONE;
4479 }")
4480
4481 ;; If the output is a register and the input is memory or a register, we have
4482 ;; to be careful and see which word needs to be loaded first.
4483
4484 (define_split
4485   [(set (match_operand:DF 0 "general_movdst_operand" "")
4486         (match_operand:DF 1 "general_movsrc_operand" ""))]
4487   "TARGET_SH1 && reload_completed"
4488   [(set (match_dup 2) (match_dup 3))
4489    (set (match_dup 4) (match_dup 5))]
4490   "
4491 {
4492   int regno;
4493
4494   if ((GET_CODE (operands[0]) == MEM
4495        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
4496       || (GET_CODE (operands[1]) == MEM
4497           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
4498     FAIL;
4499
4500   if (GET_CODE (operands[0]) == REG)
4501     regno = REGNO (operands[0]);
4502   else if (GET_CODE (operands[0]) == SUBREG)
4503     regno = subreg_regno (operands[0]);
4504   else if (GET_CODE (operands[0]) == MEM)
4505     regno = -1;
4506   else
4507     abort ();
4508
4509   if (regno == -1
4510       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
4511     {
4512       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
4513       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
4514       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
4515       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
4516     }
4517   else
4518     {
4519       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
4520       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
4521       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
4522       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
4523     }
4524
4525   if (operands[2] == 0 || operands[3] == 0
4526       || operands[4] == 0 || operands[5] == 0)
4527     FAIL;
4528 }")
4529
4530 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
4531 ;; used only once, let combine add in the index again.
4532
4533 (define_split
4534   [(set (match_operand:SI 0 "register_operand" "")
4535         (match_operand:SI 1 "" ""))
4536    (clobber (match_operand 2 "register_operand" ""))]
4537   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4538   [(use (reg:SI R0_REG))]
4539   "
4540 {
4541   rtx addr, reg, const_int;
4542
4543   if (GET_CODE (operands[1]) != MEM)
4544     FAIL;
4545   addr = XEXP (operands[1], 0);
4546   if (GET_CODE (addr) != PLUS)
4547     FAIL;
4548   reg = XEXP (addr, 0);
4549   const_int = XEXP (addr, 1);
4550   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4551          && GET_CODE (const_int) == CONST_INT))
4552     FAIL;
4553   emit_move_insn (operands[2], const_int);
4554   emit_move_insn (operands[0],
4555                   change_address (operands[1], VOIDmode,
4556                                   gen_rtx_PLUS (SImode, reg, operands[2])));
4557   DONE;
4558 }")
4559
4560 (define_split
4561   [(set (match_operand:SI 1 "" "")
4562         (match_operand:SI 0 "register_operand" ""))
4563    (clobber (match_operand 2 "register_operand" ""))]
4564   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4565   [(use (reg:SI R0_REG))]
4566   "
4567 {
4568   rtx addr, reg, const_int;
4569
4570   if (GET_CODE (operands[1]) != MEM)
4571     FAIL;
4572   addr = XEXP (operands[1], 0);
4573   if (GET_CODE (addr) != PLUS)
4574     FAIL;
4575   reg = XEXP (addr, 0);
4576   const_int = XEXP (addr, 1);
4577   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4578          && GET_CODE (const_int) == CONST_INT))
4579     FAIL;
4580   emit_move_insn (operands[2], const_int);
4581   emit_move_insn (change_address (operands[1], VOIDmode,
4582                                   gen_rtx_PLUS (SImode, reg, operands[2])),
4583                   operands[0]);
4584   DONE;
4585 }")
4586
4587 (define_expand "movdf"
4588   [(set (match_operand:DF 0 "general_movdst_operand" "")
4589         (match_operand:DF 1 "general_movsrc_operand" ""))]
4590   ""
4591   "
4592 {
4593   if (prepare_move_operands (operands, DFmode)) DONE;
4594   if (TARGET_SHMEDIA)
4595     {
4596       if (TARGET_SHMEDIA_FPU)
4597         emit_insn (gen_movdf_media (operands[0], operands[1]));
4598       else
4599         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
4600       DONE;
4601     }
4602   if (TARGET_SH4)
4603     {
4604       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
4605       DONE;
4606     }
4607 }")
4608
4609 ;;This is incompatible with the way gcc uses subregs.
4610 ;;(define_insn "movv2sf_i"
4611 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
4612 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
4613 ;;  "TARGET_SHMEDIA_FPU
4614 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
4615 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
4616 ;;  "@
4617 ;;      #
4618 ;;      fld%M1.p        %m1, %0
4619 ;;      fst%M0.p        %m0, %1"
4620 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
4621
4622 (define_insn_and_split "movv2sf_i"
4623   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
4624         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfU?"))]
4625   "TARGET_SHMEDIA_FPU"
4626   "#"
4627   "TARGET_SHMEDIA_FPU && reload_completed"
4628   [(set (match_dup 0) (match_dup 1))]
4629   "
4630 {
4631   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
4632   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
4633 }")
4634
4635 (define_expand "movv2sf"
4636   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
4637         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
4638   "TARGET_SHMEDIA_FPU"
4639   "
4640 {
4641   if (prepare_move_operands (operands, V2SFmode))
4642     DONE;
4643 }")
4644
4645 (define_expand "addv2sf3"
4646   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4647    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4648    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4649   "TARGET_SHMEDIA_FPU"
4650   "
4651 {
4652   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
4653   DONE;
4654 }")
4655
4656 (define_expand "subv2sf3"
4657   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4658    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4659    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4660   "TARGET_SHMEDIA_FPU"
4661   "
4662 {
4663   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
4664   DONE;
4665 }")
4666
4667 (define_expand "mulv2sf3"
4668   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4669    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4670    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4671   "TARGET_SHMEDIA_FPU"
4672   "
4673 {
4674   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
4675   DONE;
4676 }")
4677
4678 (define_expand "divv2sf3"
4679   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4680    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4681    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4682   "TARGET_SHMEDIA_FPU"
4683   "
4684 {
4685   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
4686   DONE;
4687 }")
4688
4689 (define_insn_and_split "*movv4sf_i"
4690   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
4691         (match_operand:V4SF 1 "general_operand" "fU,m,f"))]
4692   "TARGET_SHMEDIA_FPU"
4693   "#"
4694   "&& reload_completed"
4695   [(const_int 0)]
4696   "
4697 {
4698   int i;
4699
4700   for (i = 0; i < 4/2; i++)
4701     {
4702       rtx x, y;
4703
4704       if (GET_CODE (operands[0]) == MEM)
4705         x = gen_rtx_MEM (V2SFmode,
4706                          plus_constant (XEXP (operands[0], 0),
4707                                         i * GET_MODE_SIZE (V2SFmode)));
4708       else
4709         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
4710
4711       if (GET_CODE (operands[1]) == MEM)
4712         y = gen_rtx_MEM (V2SFmode,
4713                          plus_constant (XEXP (operands[1], 0),
4714                                         i * GET_MODE_SIZE (V2SFmode)));
4715       else
4716         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
4717
4718       emit_insn (gen_movv2sf_i (x, y));
4719     }
4720
4721   DONE;
4722 }"
4723   [(set_attr "length" "8")])
4724
4725 (define_expand "movv4sf"
4726   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
4727         (match_operand:V4SF 1 "general_operand" ""))]
4728   "TARGET_SHMEDIA_FPU"
4729   "
4730 {
4731   if (prepare_move_operands (operands, V4SFmode))
4732     DONE;
4733 }")
4734
4735 (define_insn_and_split "*movv16sf_i"
4736   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4737         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4738   "TARGET_SHMEDIA_FPU"
4739   "#"
4740   "&& reload_completed"
4741   [(const_int 0)]
4742   "
4743 {
4744   int i;
4745
4746   for (i = 0; i < 16/2; i++)
4747     {
4748       rtx x,y;
4749
4750       if (GET_CODE (operands[0]) == MEM)
4751         x = gen_rtx_MEM (V2SFmode,
4752                          plus_constant (XEXP (operands[0], 0),
4753                                         i * GET_MODE_SIZE (V2SFmode)));
4754       else
4755         {
4756           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 2);
4757           alter_subreg (&x);
4758         }
4759
4760       if (GET_CODE (operands[1]) == MEM)
4761         y = gen_rtx_MEM (V2SFmode,
4762                          plus_constant (XEXP (operands[1], 0),
4763                                         i * GET_MODE_SIZE (V2SFmode)));
4764       else
4765         {
4766           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 2);
4767           alter_subreg (&y);
4768         }
4769
4770       emit_insn (gen_movv2sf_i (x, y));
4771     }
4772
4773   DONE;
4774 }"
4775   [(set_attr "length" "32")])
4776
4777 (define_expand "movv16sf"
4778   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4779         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4780   "TARGET_SHMEDIA_FPU"
4781   "
4782 {
4783   if (prepare_move_operands (operands, V16SFmode))
4784     DONE;
4785 }")
4786
4787 (define_insn "movsf_media"
4788   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
4789         (match_operand:SF 1 "general_movsrc_operand" "f,rU,f,r,F,m,f,m,r"))]
4790   "TARGET_SHMEDIA_FPU
4791    && (register_operand (operands[0], SFmode)
4792        || register_operand (operands[1], SFmode))"
4793   "@
4794         fmov.s  %1, %0
4795         fmov.ls %N1, %0
4796         fmov.sl %1, %0
4797         add.l   %1, r63, %0
4798         #
4799         fld%M1.s        %m1, %0
4800         fst%M0.s        %m0, %1
4801         ld%M1.l %m1, %0
4802         st%M0.l %m0, %1"
4803   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
4804
4805 (define_insn "movsf_media_nofpu"
4806   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
4807         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,r"))]
4808   "TARGET_SHMEDIA
4809    && (register_operand (operands[0], SFmode)
4810        || register_operand (operands[1], SFmode))"
4811   "@
4812         add.l   %1, r63, %0
4813         #
4814         ld%M1.l %m1, %0
4815         st%M0.l %m0, %1"
4816   [(set_attr "type" "arith_media,*,load_media,store_media")])
4817
4818 (define_split
4819   [(set (match_operand:SF 0 "arith_reg_operand" "")
4820         (match_operand:SF 1 "immediate_operand" ""))]
4821   "TARGET_SHMEDIA && reload_completed
4822    && ! FP_REGISTER_P (true_regnum (operands[0]))"
4823   [(set (match_dup 3) (match_dup 2))]
4824   "
4825 {
4826   long values;
4827   REAL_VALUE_TYPE value;
4828
4829   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
4830   REAL_VALUE_TO_TARGET_SINGLE (value, values);
4831   operands[2] = GEN_INT (values);
4832
4833   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4834 }")
4835
4836 (define_insn "movsf_i"
4837   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
4838         (match_operand:SF 1 "general_movsrc_operand"  "r,I,FQ,mr,r,r,l"))]
4839   "TARGET_SH1
4840    && (! TARGET_SH3E
4841        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
4842        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
4843        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
4844    && (arith_reg_operand (operands[0], SFmode)
4845        || arith_reg_operand (operands[1], SFmode))"
4846   "@
4847         mov     %1,%0
4848         mov     %1,%0
4849         mov.l   %1,%0
4850         mov.l   %1,%0
4851         mov.l   %1,%0
4852         lds     %1,%0
4853         sts     %1,%0"
4854   [(set_attr "type" "move,move,pcload,load,store,move,move")])
4855
4856 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
4857 ;; update_flow_info would not know where to put REG_EQUAL notes
4858 ;; when the destination changes mode.
4859 (define_insn "movsf_ie"
4860   [(set (match_operand:SF 0 "general_movdst_operand"
4861          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
4862         (match_operand:SF 1 "general_movsrc_operand"
4863           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
4864    (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"))
4865    (clobber (match_scratch:SI 3 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
4866
4867   "TARGET_SH3E
4868    && (arith_reg_operand (operands[0], SFmode)
4869        || arith_reg_operand (operands[1], SFmode)
4870        || arith_reg_operand (operands[3], SImode)
4871        || (fpul_operand (operands[0], SFmode)
4872            && memory_operand (operands[1], SFmode)
4873            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
4874        || (fpul_operand (operands[1], SFmode)
4875            && memory_operand (operands[0], SFmode)
4876            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
4877   "@
4878         fmov    %1,%0
4879         mov     %1,%0
4880         fldi0   %0
4881         fldi1   %0
4882         #
4883         fmov.s  %1,%0
4884         fmov.s  %1,%0
4885         mov.l   %1,%0
4886         mov.l   %1,%0
4887         mov.l   %1,%0
4888         fsts    fpul,%0
4889         flds    %1,fpul
4890         lds.l   %1,%0
4891         #
4892         sts     %1,%0
4893         lds     %1,%0
4894         sts.l   %1,%0
4895         lds.l   %1,%0
4896         ! move optimized away"
4897   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,store,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,store,load,nil")
4898    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
4899    (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,4,2,2,2,2,0")
4900    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
4901                                            (const_string "single")
4902                                            (const_string "none")))])
4903
4904 (define_split
4905   [(set (match_operand:SF 0 "register_operand" "")
4906         (match_operand:SF 1 "register_operand" ""))
4907    (use (match_operand:PSI 2 "fpscr_operand" ""))
4908    (clobber (reg:SI FPUL_REG))]
4909   "TARGET_SH1"
4910   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
4911               (use (match_dup 2))
4912               (clobber (scratch:SI))])
4913    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
4914               (use (match_dup 2))
4915               (clobber (scratch:SI))])]
4916   "")
4917
4918 (define_expand "movsf"
4919   [(set (match_operand:SF 0 "general_movdst_operand" "")
4920         (match_operand:SF 1 "general_movsrc_operand" ""))]
4921   ""
4922   "
4923 {
4924   if (prepare_move_operands (operands, SFmode))
4925     DONE;
4926   if (TARGET_SHMEDIA)
4927     {
4928       if (TARGET_SHMEDIA_FPU)
4929         emit_insn (gen_movsf_media (operands[0], operands[1]));
4930       else
4931         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
4932       DONE;
4933     }
4934   if (TARGET_SH3E)
4935     {
4936       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
4937       DONE;
4938     }
4939 }")
4940
4941 (define_insn "mov_nop"
4942   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
4943   "TARGET_SH3E"
4944   ""
4945   [(set_attr "length" "0")
4946    (set_attr "type" "nil")])
4947
4948 (define_expand "reload_insf"
4949   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
4950                    (match_operand:SF 1 "immediate_operand" "FQ"))
4951               (use (reg:PSI FPSCR_REG))
4952               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4953   "TARGET_SH1"
4954   "")
4955
4956 (define_expand "reload_insi"
4957   [(parallel [(set (match_operand:SF 0 "register_operand" "=y")
4958                    (match_operand:SF 1 "immediate_operand" "FQ"))
4959               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4960   "TARGET_SH1"
4961   "")
4962
4963 (define_insn "*movsi_y"
4964   [(set (match_operand:SI 0 "register_operand" "=y,y")
4965         (match_operand:SI 1 "immediate_operand" "Qi,I"))
4966    (clobber (match_scratch:SI 2 "=&z,r"))]
4967   "TARGET_SH3E
4968    && (reload_in_progress || reload_completed)"
4969   "#"
4970   [(set_attr "length" "4")
4971    (set_attr "type" "pcload,move")])
4972
4973 (define_split
4974   [(set (match_operand:SI 0 "register_operand" "")
4975         (match_operand:SI 1 "immediate_operand" ""))
4976    (clobber (match_operand:SI 2 "register_operand" ""))]
4977   "TARGET_SH1"
4978   [(set (match_dup 2) (match_dup 1))
4979    (set (match_dup 0) (match_dup 2))]
4980   "")
4981
4982 (define_split
4983   [(set (match_operand:SI 0 "register_operand" "")
4984         (match_operand:SI 1 "memory_operand" ""))
4985    (clobber (reg:SI R0_REG))]
4986   "TARGET_SH1"
4987   [(set (match_dup 0) (match_dup 1))]
4988   "")
4989 \f
4990 ;; ------------------------------------------------------------------------
4991 ;; Define the real conditional branch instructions.
4992 ;; ------------------------------------------------------------------------
4993
4994 (define_insn "branch_true"
4995   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
4996                            (label_ref (match_operand 0 "" ""))
4997                            (pc)))]
4998   "TARGET_SH1"
4999   "* return output_branch (1, insn, operands);"
5000   [(set_attr "type" "cbranch")])
5001
5002 (define_insn "branch_false"
5003   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
5004                            (label_ref (match_operand 0 "" ""))
5005                            (pc)))]
5006   "TARGET_SH1"
5007   "* return output_branch (0, insn, operands);"
5008   [(set_attr "type" "cbranch")])
5009
5010 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
5011 ;; which destination is too far away.
5012 ;; The const_int_operand is distinct for each branch target; it avoids
5013 ;; unwanted matches with redundant_insn.
5014 (define_insn "block_branch_redirect"
5015   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
5016   "TARGET_SH1"
5017   ""
5018   [(set_attr "length" "0")])
5019
5020 ;; This one has the additional purpose to record a possible scratch register
5021 ;; for the following branch.
5022 (define_insn "indirect_jump_scratch"
5023   [(set (match_operand:SI 0 "register_operand" "=r")
5024         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))]
5025   "TARGET_SH1"
5026   ""
5027   [(set_attr "length" "0")])
5028
5029 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
5030 ;; being pulled into the delay slot of a condbranch that has been made to
5031 ;; jump around the unconditional jump because it was out of range.
5032 (define_insn "stuff_delay_slot"
5033   [(set (pc)
5034         (unspec [(match_operand 0 "const_int_operand" "") (pc)] UNSPEC_BBR))
5035    (set (reg:SI T_REG) (match_operand 1 "const_int_operand" ""))]
5036   "TARGET_SH1"
5037   ""
5038   [(set_attr "length" "0")
5039    (set_attr "cond_delay_slot" "yes")])
5040 \f
5041 ;; Conditional branch insns
5042
5043 (define_expand "beq_media"
5044   [(set (pc)
5045         (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
5046                           (match_operand:DI 2 "arith_operand" "r,O"))
5047                       (label_ref:DI (match_operand 0 "" ""))
5048                       (pc)))]
5049   "TARGET_SHMEDIA"
5050   "")
5051
5052 (define_insn "*beq_media_i"
5053   [(set (pc)
5054         (if_then_else (match_operator 3 "equality_comparison_operator"
5055                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
5056                          (match_operand:DI 2 "arith_operand" "r,O")])
5057                       (match_operand:DI 0 "target_operand" "b,b")
5058                       (pc)))]
5059   "TARGET_SHMEDIA"
5060   "@
5061         b%o3%'  %1, %2, %0
5062         b%o3i%' %1, %2, %0"
5063   [(set_attr "type" "cbranch_media")])
5064
5065 (define_expand "bne_media"
5066   [(set (pc)
5067         (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
5068                           (match_operand:DI 2 "arith_operand" "r,O"))
5069                       (label_ref:DI (match_operand 0 "" ""))
5070                       (pc)))]
5071   "TARGET_SHMEDIA"
5072   "")
5073
5074 (define_expand "bgt_media"
5075   [(set (pc)
5076         (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5077                           (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5078                       (label_ref:DI (match_operand 0 "" ""))
5079                       (pc)))]
5080   "TARGET_SHMEDIA"
5081   "")
5082
5083 (define_expand "bge_media"
5084   [(set (pc)
5085         (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5086                           (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5087                       (label_ref:DI (match_operand 0 "" ""))
5088                       (pc)))]
5089   "TARGET_SHMEDIA"
5090   "")
5091
5092 (define_expand "bgtu_media"
5093   [(set (pc)
5094         (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5095                            (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5096                       (label_ref:DI (match_operand 0 "" ""))
5097                       (pc)))]
5098   "TARGET_SHMEDIA"
5099   "")
5100
5101 (define_expand "bgeu_media"
5102   [(set (pc)
5103         (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5104                            (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5105                       (label_ref:DI (match_operand 0 "" ""))
5106                       (pc)))]
5107   "TARGET_SHMEDIA"
5108   "")
5109
5110 (define_insn "*bgt_media_i"
5111   [(set (pc)
5112         (if_then_else (match_operator 3 "greater_comparison_operator"
5113                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
5114                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
5115                       (match_operand:DI 0 "target_operand" "b")
5116                       (pc)))]
5117   "TARGET_SHMEDIA"
5118   "b%o3%'       %N1, %N2, %0"
5119   [(set_attr "type" "cbranch_media")])
5120
5121 ;; These are only needed to make invert_jump() happy.
5122 (define_insn "*blt_media_i"
5123   [(set (pc)
5124         (if_then_else (match_operator 3 "less_comparison_operator"
5125                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
5126                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
5127                       (match_operand:DI 0 "target_operand" "b")
5128                       (pc)))]
5129   "TARGET_SHMEDIA"
5130   "b%o3%'       %N2, %N1, %0"
5131   [(set_attr "type" "cbranch_media")])
5132
5133 (define_expand "beq"
5134   [(set (pc)
5135         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5136                       (label_ref (match_operand 0 "" ""))
5137                       (pc)))]
5138   ""
5139   "
5140 {
5141   if (TARGET_SHMEDIA)
5142     {
5143       if (GET_MODE (sh_compare_op0) != DImode)
5144         {
5145           rtx tmp = gen_reg_rtx (DImode);
5146
5147           emit_insn (gen_seq (tmp));
5148           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5149           DONE;
5150         }
5151
5152       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5153       emit_jump_insn (gen_beq_media (operands[0],
5154                                      sh_compare_op0, sh_compare_op1));
5155       DONE;
5156     }
5157
5158   from_compare (operands, EQ);
5159 }")
5160
5161 (define_expand "bne"
5162   [(set (pc)
5163         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5164                       (label_ref (match_operand 0 "" ""))
5165                       (pc)))]
5166   ""
5167   "
5168 {
5169   if (TARGET_SHMEDIA)
5170     {
5171       if (GET_MODE (sh_compare_op0) != DImode)
5172         {
5173           rtx tmp = gen_reg_rtx (DImode);
5174
5175           emit_insn (gen_seq (tmp));
5176           emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
5177           DONE;
5178         }
5179
5180       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5181       emit_jump_insn (gen_bne_media (operands[0],
5182                                      sh_compare_op0, sh_compare_op1));
5183       DONE;
5184     }
5185
5186   from_compare (operands, EQ);
5187 }")
5188
5189 (define_expand "bgt"
5190   [(set (pc)
5191         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5192                       (label_ref (match_operand 0 "" ""))
5193                       (pc)))]
5194   ""
5195   "
5196 {
5197   if (TARGET_SHMEDIA)
5198     {
5199       if (GET_MODE (sh_compare_op0) != DImode)
5200         {
5201           rtx tmp = gen_reg_rtx (DImode);
5202
5203           emit_insn (gen_sgt (tmp));
5204           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5205           DONE;
5206         }
5207
5208       if (sh_compare_op0 != const0_rtx)
5209         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5210       if (sh_compare_op1 != const0_rtx)
5211         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5212       emit_jump_insn (gen_bgt_media (operands[0],
5213                                      sh_compare_op0, sh_compare_op1));
5214       DONE;
5215     }
5216
5217   from_compare (operands, GT);
5218 }")
5219
5220 (define_expand "blt"
5221   [(set (pc)
5222         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5223                       (label_ref (match_operand 0 "" ""))
5224                       (pc)))]
5225   ""
5226   "
5227 {
5228   if (TARGET_SHMEDIA)
5229     {
5230       if (GET_MODE (sh_compare_op0) != DImode)
5231         {
5232           rtx tmp = gen_reg_rtx (DImode);
5233
5234           emit_insn (gen_slt (tmp));
5235           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5236           DONE;
5237         }
5238
5239       if (sh_compare_op0 != const0_rtx)
5240         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5241       if (sh_compare_op1 != const0_rtx)
5242         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5243       emit_jump_insn (gen_bgt_media (operands[0],
5244                                      sh_compare_op1, sh_compare_op0));
5245       DONE;
5246     }
5247
5248   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5249     {
5250       rtx tmp = sh_compare_op0;
5251       sh_compare_op0 = sh_compare_op1;
5252       sh_compare_op1 = tmp;
5253       emit_insn (gen_bgt (operands[0]));
5254       DONE;
5255     }
5256   from_compare (operands, GE);
5257 }")
5258
5259 (define_expand "ble"
5260   [(set (pc)
5261         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5262                       (label_ref (match_operand 0 "" ""))
5263                       (pc)))]
5264   ""
5265   "
5266 {
5267   if (TARGET_SHMEDIA)
5268     {
5269       if (GET_MODE (sh_compare_op0) != DImode)
5270         {
5271           rtx tmp = gen_reg_rtx (DImode);
5272
5273           emit_insn (gen_sle (tmp));
5274           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5275           DONE;
5276         }
5277
5278       if (sh_compare_op0 != const0_rtx)
5279         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5280       if (sh_compare_op1 != const0_rtx)
5281         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5282       emit_jump_insn (gen_bge_media (operands[0],
5283                                      sh_compare_op1, sh_compare_op0));
5284       DONE;
5285     }
5286
5287   if (TARGET_SH3E
5288       && TARGET_IEEE
5289       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5290     {
5291       rtx tmp = sh_compare_op0;
5292       sh_compare_op0 = sh_compare_op1;
5293       sh_compare_op1 = tmp;
5294       emit_insn (gen_bge (operands[0]));
5295       DONE;
5296     }
5297   from_compare (operands, GT);
5298 }")
5299
5300 (define_expand "bge"
5301   [(set (pc)
5302         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5303                       (label_ref (match_operand 0 "" ""))
5304                       (pc)))]
5305   ""
5306   "
5307 {
5308   if (TARGET_SHMEDIA)
5309     {
5310       if (GET_MODE (sh_compare_op0) != DImode)
5311         {
5312           rtx tmp = gen_reg_rtx (DImode);
5313
5314           emit_insn (gen_sge (tmp));
5315           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5316           DONE;
5317         }
5318
5319       if (sh_compare_op0 != const0_rtx)
5320         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5321       if (sh_compare_op1 != const0_rtx)
5322         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5323       emit_jump_insn (gen_bge_media (operands[0],
5324                                      sh_compare_op0, sh_compare_op1));
5325       DONE;
5326     }
5327
5328   if (TARGET_SH3E
5329       && ! TARGET_IEEE
5330       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5331     {
5332       rtx tmp = sh_compare_op0;
5333       sh_compare_op0 = sh_compare_op1;
5334       sh_compare_op1 = tmp;
5335       emit_insn (gen_ble (operands[0]));
5336       DONE;
5337     }
5338   from_compare (operands, GE);
5339 }")
5340
5341 (define_expand "bgtu"
5342   [(set (pc)
5343         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5344                       (label_ref (match_operand 0 "" ""))
5345                       (pc)))]
5346   ""
5347   "
5348 {
5349   if (TARGET_SHMEDIA)
5350     {
5351       if (sh_compare_op0 != const0_rtx)
5352         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5353       if (sh_compare_op1 != const0_rtx)
5354         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5355       emit_jump_insn (gen_bgtu_media (operands[0],
5356                                       sh_compare_op0, sh_compare_op1));
5357       DONE;
5358     }
5359
5360   from_compare (operands, GTU);
5361 }")
5362
5363 (define_expand "bltu"
5364   [(set (pc)
5365         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5366                       (label_ref (match_operand 0 "" ""))
5367                       (pc)))]
5368   ""
5369   "
5370 {
5371   if (TARGET_SHMEDIA)
5372     {
5373       if (sh_compare_op0 != const0_rtx)
5374         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5375       if (sh_compare_op1 != const0_rtx)
5376         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5377       emit_jump_insn (gen_bgtu_media (operands[0],
5378                                       sh_compare_op1, sh_compare_op0));
5379       DONE;
5380     }
5381
5382   from_compare (operands, GEU);
5383 }")
5384
5385 (define_expand "bgeu"
5386   [(set (pc)
5387         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5388                       (label_ref (match_operand 0 "" ""))
5389                       (pc)))]
5390   ""
5391   "
5392 {
5393   if (TARGET_SHMEDIA)
5394     {
5395       if (sh_compare_op0 != const0_rtx)
5396         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5397       if (sh_compare_op1 != const0_rtx)
5398         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5399       emit_jump_insn (gen_bgeu_media (operands[0],
5400                                       sh_compare_op0, sh_compare_op1));
5401       DONE;
5402     }
5403
5404   from_compare (operands, GEU);
5405 }")
5406
5407 (define_expand "bleu"
5408   [(set (pc)
5409         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5410                       (label_ref (match_operand 0 "" ""))
5411                       (pc)))]
5412   ""
5413   "
5414 {
5415   if (TARGET_SHMEDIA)
5416     {
5417       if (sh_compare_op0 != const0_rtx)
5418         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5419       if (sh_compare_op1 != const0_rtx)
5420         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5421       emit_jump_insn (gen_bgeu_media (operands[0],
5422                                       sh_compare_op1, sh_compare_op0));
5423       DONE;
5424     }
5425
5426   from_compare (operands, GTU);
5427 }")
5428
5429 (define_expand "bunordered"
5430   [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3)))
5431    (set (pc)
5432         (if_then_else (ne (match_dup 1) (const_int 0))
5433                       (label_ref:DI (match_operand 0 "" ""))
5434                       (pc)))]
5435   "TARGET_SHMEDIA"
5436   "
5437 {
5438   operands[1] = gen_reg_rtx (DImode);
5439   operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
5440   operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
5441 }")
5442 \f
5443 ;; ------------------------------------------------------------------------
5444 ;; Jump and linkage insns
5445 ;; ------------------------------------------------------------------------
5446
5447 (define_insn "jump_compact"
5448   [(set (pc)
5449         (label_ref (match_operand 0 "" "")))]
5450   "TARGET_SH1"
5451   "*
5452 {
5453   /* The length is 16 if the delay slot is unfilled.  */
5454   if (get_attr_length(insn) > 4)
5455     return output_far_jump(insn, operands[0]);
5456   else
5457     return   \"bra      %l0%#\";
5458 }"
5459   [(set_attr "type" "jump")
5460    (set_attr "needs_delay_slot" "yes")])
5461
5462 (define_insn "jump_media"
5463   [(set (pc)
5464         (match_operand:DI 0 "target_operand" "b"))]
5465   "TARGET_SHMEDIA"
5466   "blink        %0, r63"
5467   [(set_attr "type" "jump_media")])
5468
5469 (define_expand "jump"
5470   [(set (pc)
5471         (label_ref (match_operand 0 "" "")))]
5472   ""
5473   "
5474 {
5475   if (TARGET_SH1)
5476     emit_jump_insn (gen_jump_compact (operands[0]));
5477   else if (TARGET_SHMEDIA)
5478     {
5479       if (reload_in_progress || reload_completed)
5480         FAIL;
5481       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (DImode,
5482                                                          operands[0])));
5483     }
5484   DONE;
5485 }")
5486
5487 (define_insn "force_mode_for_call"
5488   [(use (reg:PSI FPSCR_REG))]
5489   "TARGET_SHCOMPACT"
5490   ""
5491   [(set_attr "length" "0")
5492    (set (attr "fp_mode")
5493         (if_then_else (eq_attr "fpu_single" "yes")
5494                       (const_string "single") (const_string "double")))])
5495
5496 (define_insn "calli"
5497   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5498          (match_operand 1 "" ""))
5499    (use (reg:PSI FPSCR_REG))
5500    (clobber (reg:SI PR_REG))]
5501   "TARGET_SH1"
5502   "jsr  @%0%#"
5503   [(set_attr "type" "call")
5504    (set (attr "fp_mode")
5505         (if_then_else (eq_attr "fpu_single" "yes")
5506                       (const_string "single") (const_string "double")))
5507    (set_attr "needs_delay_slot" "yes")])
5508
5509 ;; This is a pc-rel call, using bsrf, for use with PIC.
5510
5511 (define_insn "calli_pcrel"
5512   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5513          (match_operand 1 "" ""))
5514    (use (reg:PSI FPSCR_REG))
5515    (use (reg:SI PIC_REG))
5516    (use (match_operand 2 "" ""))
5517    (clobber (reg:SI PR_REG))]
5518   "TARGET_SH2"
5519   "bsrf %0\\n%O2:%#"
5520   [(set_attr "type" "call")
5521    (set (attr "fp_mode")
5522         (if_then_else (eq_attr "fpu_single" "yes")
5523                       (const_string "single") (const_string "double")))
5524    (set_attr "needs_delay_slot" "yes")])
5525
5526 (define_insn_and_split "call_pcrel"
5527   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
5528          (match_operand 1 "" ""))
5529    (use (reg:PSI FPSCR_REG))
5530    (use (reg:SI PIC_REG))
5531    (clobber (reg:SI PR_REG))
5532    (clobber (match_scratch:SI 2 "=r"))]
5533   "TARGET_SH2"
5534   "#"
5535   "reload_completed"
5536   [(const_int 0)]
5537   "
5538 {
5539   rtx lab = PATTERN (gen_call_site ());
5540
5541   if (SYMBOL_REF_FLAG (operands[0]))
5542     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
5543   else
5544     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
5545   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], lab));
5546   DONE;
5547 }"
5548   [(set_attr "type" "call")
5549    (set (attr "fp_mode")
5550         (if_then_else (eq_attr "fpu_single" "yes")
5551                       (const_string "single") (const_string "double")))
5552    (set_attr "needs_delay_slot" "yes")])
5553
5554 (define_insn "call_compact"
5555   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5556          (match_operand 1 "" ""))
5557    (match_operand 2 "immediate_operand" "n")
5558    (use (reg:SI R0_REG))
5559    (use (reg:SI R1_REG))
5560    (use (reg:PSI FPSCR_REG))
5561    (clobber (reg:SI PR_REG))]
5562   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5563   "jsr  @%0%#"
5564   [(set_attr "type" "call")
5565    (set (attr "fp_mode")
5566         (if_then_else (eq_attr "fpu_single" "yes")
5567                       (const_string "single") (const_string "double")))
5568    (set_attr "needs_delay_slot" "yes")])
5569
5570 (define_insn "call_compact_rettramp"
5571   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5572          (match_operand 1 "" ""))
5573    (match_operand 2 "immediate_operand" "n")
5574    (use (reg:SI R0_REG))
5575    (use (reg:SI R1_REG))
5576    (use (reg:PSI FPSCR_REG))
5577    (clobber (reg:SI R10_REG))
5578    (clobber (reg:SI PR_REG))]
5579   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5580   "jsr  @%0%#"
5581   [(set_attr "type" "call")
5582    (set (attr "fp_mode")
5583         (if_then_else (eq_attr "fpu_single" "yes")
5584                       (const_string "single") (const_string "double")))
5585    (set_attr "needs_delay_slot" "yes")])
5586
5587 (define_insn "call_media"
5588   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "b"))
5589          (match_operand 1 "" ""))
5590    (clobber (reg:DI PR_MEDIA_REG))]
5591   "TARGET_SHMEDIA"
5592   "blink        %0, r18"
5593   [(set_attr "type" "jump_media")])
5594
5595 (define_insn "call_valuei"
5596   [(set (match_operand 0 "" "=rf")
5597         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5598               (match_operand 2 "" "")))
5599    (use (reg:PSI FPSCR_REG))
5600    (clobber (reg:SI PR_REG))]
5601   "TARGET_SH1"
5602   "jsr  @%1%#"
5603   [(set_attr "type" "call")
5604    (set (attr "fp_mode")
5605         (if_then_else (eq_attr "fpu_single" "yes")
5606                       (const_string "single") (const_string "double")))
5607    (set_attr "needs_delay_slot" "yes")])
5608
5609 (define_insn "call_valuei_pcrel"
5610   [(set (match_operand 0 "" "=rf")
5611         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5612               (match_operand 2 "" "")))
5613    (use (reg:PSI FPSCR_REG))
5614    (use (reg:SI PIC_REG))
5615    (use (match_operand 3 "" ""))
5616    (clobber (reg:SI PR_REG))]
5617   "TARGET_SH2"
5618   "bsrf %1\\n%O3:%#"
5619   [(set_attr "type" "call")
5620    (set (attr "fp_mode")
5621         (if_then_else (eq_attr "fpu_single" "yes")
5622                       (const_string "single") (const_string "double")))
5623    (set_attr "needs_delay_slot" "yes")])
5624
5625 (define_insn_and_split "call_value_pcrel"
5626   [(set (match_operand 0 "" "=rf")
5627         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
5628               (match_operand 2 "" "")))
5629    (use (reg:PSI FPSCR_REG))
5630    (use (reg:SI PIC_REG))
5631    (clobber (reg:SI PR_REG))
5632    (clobber (match_scratch:SI 3 "=r"))]
5633   "TARGET_SH2"
5634   "#"
5635   "reload_completed"
5636   [(const_int 0)]
5637   "
5638 {
5639   rtx lab = PATTERN (gen_call_site ());
5640
5641   if (SYMBOL_REF_FLAG (operands[1]))
5642     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
5643   else
5644     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
5645   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
5646                                          operands[2], lab));
5647   DONE;
5648 }"
5649   [(set_attr "type" "call")
5650    (set (attr "fp_mode")
5651         (if_then_else (eq_attr "fpu_single" "yes")
5652                       (const_string "single") (const_string "double")))
5653    (set_attr "needs_delay_slot" "yes")])
5654
5655 (define_insn "call_value_compact"
5656   [(set (match_operand 0 "" "=rf")
5657         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5658               (match_operand 2 "" "")))
5659    (match_operand 3 "immediate_operand" "n")
5660    (use (reg:SI R0_REG))
5661    (use (reg:SI R1_REG))
5662    (use (reg:PSI FPSCR_REG))
5663    (clobber (reg:SI PR_REG))]
5664   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5665   "jsr  @%1%#"
5666   [(set_attr "type" "call")
5667    (set (attr "fp_mode")
5668         (if_then_else (eq_attr "fpu_single" "yes")
5669                       (const_string "single") (const_string "double")))
5670    (set_attr "needs_delay_slot" "yes")])
5671
5672 (define_insn "call_value_compact_rettramp"
5673   [(set (match_operand 0 "" "=rf")
5674         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5675               (match_operand 2 "" "")))
5676    (match_operand 3 "immediate_operand" "n")
5677    (use (reg:SI R0_REG))
5678    (use (reg:SI R1_REG))
5679    (use (reg:PSI FPSCR_REG))
5680    (clobber (reg:SI R10_REG))
5681    (clobber (reg:SI PR_REG))]
5682   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5683   "jsr  @%1%#"
5684   [(set_attr "type" "call")
5685    (set (attr "fp_mode")
5686         (if_then_else (eq_attr "fpu_single" "yes")
5687                       (const_string "single") (const_string "double")))
5688    (set_attr "needs_delay_slot" "yes")])
5689
5690 (define_insn "call_value_media"
5691   [(set (match_operand 0 "" "=rf")
5692         (call (mem:DI (match_operand:DI 1 "target_reg_operand" "b"))
5693               (match_operand 2 "" "")))
5694    (clobber (reg:DI PR_MEDIA_REG))]
5695   "TARGET_SHMEDIA"
5696   "blink        %1, r18"
5697   [(set_attr "type" "jump_media")])
5698
5699 (define_expand "call"
5700   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5701                             (match_operand 1 "" ""))
5702               (match_operand 2 "" "")
5703               (use (reg:PSI FPSCR_REG))
5704               (clobber (reg:SI PR_REG))])]
5705   ""
5706   "
5707 {
5708   if (TARGET_SHMEDIA)
5709     {
5710       operands[0] = XEXP (operands[0], 0);
5711       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
5712         {
5713           if (! SYMBOL_REF_FLAG (operands[0]))
5714             {
5715               rtx reg = gen_reg_rtx (Pmode);
5716
5717               emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5718               operands[0] = reg;
5719             }
5720           else
5721             {
5722               operands[0] = gen_sym2PIC (operands[0]);
5723               PUT_MODE (operands[0], Pmode);
5724             }
5725         }
5726       if (GET_MODE (operands[0]) == SImode)
5727         {
5728           if (GET_CODE (operands[0]) == REG)
5729             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5730           else if (GET_CODE (operands[0]) == SUBREG)
5731             {
5732               operands[0] = SUBREG_REG (operands[0]);
5733               if (GET_MODE (operands[0]) != DImode)
5734                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5735             }
5736           else
5737             {
5738               operands[0] = shallow_copy_rtx (operands[0]);
5739               PUT_MODE (operands[0], DImode);
5740             }
5741         }
5742       if (! target_reg_operand (operands[0], DImode))
5743         operands[0] = copy_to_mode_reg (DImode, operands[0]);
5744       emit_call_insn (gen_call_media (operands[0], operands[1]));
5745       DONE;
5746     }
5747   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
5748     {
5749       rtx cookie_rtx = operands[2];
5750       long cookie = INTVAL (cookie_rtx);
5751       rtx func = XEXP (operands[0], 0);
5752       rtx r0, r1;
5753
5754       if (flag_pic)
5755         {
5756           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5757             {
5758               rtx reg = gen_reg_rtx (Pmode);
5759
5760               emit_insn (gen_symGOTPLT2reg (reg, func));
5761               func = reg;
5762             }
5763           else
5764             func = legitimize_pic_address (func, Pmode, 0);
5765         }
5766
5767       r0 = gen_rtx_REG (SImode, R0_REG);
5768       r1 = gen_rtx_REG (SImode, R1_REG);
5769
5770       /* Since such a call function may use all call-clobbered
5771          registers, we force a mode switch earlier, so that we don't
5772          run out of registers when adjusting fpscr for the call.  */
5773       emit_insn (gen_force_mode_for_call ());
5774
5775       operands[0] = gen_rtx_SYMBOL_REF (SImode,
5776                                         \"__GCC_shcompact_call_trampoline\");
5777       if (flag_pic)
5778         {
5779           rtx reg = gen_reg_rtx (Pmode);
5780
5781           emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5782           operands[0] = reg;
5783         }
5784       operands[0] = force_reg (SImode, operands[0]);
5785
5786       emit_move_insn (r0, func);
5787       emit_move_insn (r1, cookie_rtx);
5788
5789       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5790         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
5791                                                    operands[2]));
5792       else
5793         emit_call_insn (gen_call_compact (operands[0], operands[1],
5794                                           operands[2]));
5795
5796       DONE;
5797     }
5798   else if (TARGET_SHCOMPACT && flag_pic
5799            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
5800            && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
5801     {
5802       rtx reg = gen_reg_rtx (Pmode);
5803
5804       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
5805       XEXP (operands[0], 0) = reg;
5806     }
5807   if (flag_pic && TARGET_SH2
5808       && GET_CODE (operands[0]) == MEM
5809       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
5810     {
5811       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
5812       DONE;
5813     }
5814   else
5815     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
5816
5817   emit_call_insn (gen_calli (operands[0], operands[1]));
5818   DONE;
5819 }")
5820
5821 (define_insn "call_pop_compact"
5822   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5823          (match_operand 1 "" ""))
5824    (match_operand 2 "immediate_operand" "n")
5825    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5826                                  (match_operand 3 "immediate_operand" "n")))
5827    (use (reg:SI R0_REG))
5828    (use (reg:SI R1_REG))
5829    (use (reg:PSI FPSCR_REG))
5830    (clobber (reg:SI PR_REG))]
5831   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5832   "jsr  @%0%#"
5833   [(set_attr "type" "call")
5834    (set (attr "fp_mode")
5835         (if_then_else (eq_attr "fpu_single" "yes")
5836                       (const_string "single") (const_string "double")))
5837    (set_attr "needs_delay_slot" "yes")])
5838
5839 (define_insn "call_pop_compact_rettramp"
5840   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5841          (match_operand 1 "" ""))
5842    (match_operand 2 "immediate_operand" "n")
5843    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5844                                  (match_operand 3 "immediate_operand" "n")))
5845    (use (reg:SI R0_REG))
5846    (use (reg:SI R1_REG))
5847    (use (reg:PSI FPSCR_REG))
5848    (clobber (reg:SI R10_REG))
5849    (clobber (reg:SI PR_REG))]
5850   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5851   "jsr  @%0%#"
5852   [(set_attr "type" "call")
5853    (set (attr "fp_mode")
5854         (if_then_else (eq_attr "fpu_single" "yes")
5855                       (const_string "single") (const_string "double")))
5856    (set_attr "needs_delay_slot" "yes")])
5857
5858 (define_expand "call_pop"
5859   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5860                     (match_operand 1 "" ""))
5861              (match_operand 2 "" "")
5862              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5863                                            (match_operand 3 "" "")))])]
5864   "TARGET_SHCOMPACT"
5865   "
5866 {
5867   if (operands[2] && INTVAL (operands[2]))
5868     {
5869       rtx cookie_rtx = operands[2];
5870       long cookie = INTVAL (cookie_rtx);
5871       rtx func = XEXP (operands[0], 0);
5872       rtx r0, r1;
5873
5874       if (flag_pic)
5875         {
5876           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5877             {
5878               rtx reg = gen_reg_rtx (Pmode);
5879
5880               emit_insn (gen_symGOTPLT2reg (reg, func));
5881               func = reg;
5882             }
5883           else
5884             func = legitimize_pic_address (func, Pmode, 0);
5885         }
5886
5887       r0 = gen_rtx_REG (SImode, R0_REG);
5888       r1 = gen_rtx_REG (SImode, R1_REG);
5889
5890       /* Since such a call function may use all call-clobbered
5891          registers, we force a mode switch earlier, so that we don't
5892          run out of registers when adjusting fpscr for the call.  */
5893       emit_insn (gen_force_mode_for_call ());
5894
5895       operands[0] = gen_rtx_SYMBOL_REF (SImode,
5896                                         \"__GCC_shcompact_call_trampoline\");
5897       if (flag_pic)
5898         {
5899           rtx reg = gen_reg_rtx (Pmode);
5900
5901           emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5902           operands[0] = reg;
5903         }
5904       operands[0] = force_reg (SImode, operands[0]);
5905
5906       emit_move_insn (r0, func);
5907       emit_move_insn (r1, cookie_rtx);
5908
5909       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5910         emit_call_insn (gen_call_pop_compact_rettramp
5911                         (operands[0], operands[1], operands[2], operands[3]));
5912       else
5913         emit_call_insn (gen_call_pop_compact
5914                         (operands[0], operands[1], operands[2], operands[3]));
5915
5916       DONE;
5917     }
5918
5919   abort ();
5920 }")
5921
5922 (define_expand "call_value"
5923   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
5924                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
5925                                  (match_operand 2 "" "")))
5926               (match_operand 3 "" "")
5927               (use (reg:PSI FPSCR_REG))
5928               (clobber (reg:SI PR_REG))])]
5929   ""
5930   "
5931 {
5932   if (TARGET_SHMEDIA)
5933     {
5934       operands[1] = XEXP (operands[1], 0);
5935       if (flag_pic && GET_CODE (operands[1]) == SYMBOL_REF)
5936         {
5937           if (! SYMBOL_REF_FLAG (operands[1]))
5938             {
5939               rtx reg = gen_reg_rtx (Pmode);
5940
5941               emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
5942               operands[1] = reg;
5943             }
5944           else
5945             {
5946               operands[1] = gen_sym2PIC (operands[1]);
5947               PUT_MODE (operands[1], Pmode);
5948             }
5949         }
5950       if (GET_MODE (operands[1]) == SImode)
5951         {
5952           if (GET_CODE (operands[1]) == REG)
5953             operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5954           else if (GET_CODE (operands[1]) == SUBREG)
5955             {
5956               operands[1] = SUBREG_REG (operands[1]);
5957               if (GET_MODE (operands[1]) != DImode)
5958                 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5959             }
5960           else
5961             {
5962               operands[1] = shallow_copy_rtx (operands[1]);
5963               PUT_MODE (operands[1], DImode);
5964             }
5965         }
5966       if (! target_reg_operand (operands[1], DImode))
5967         operands[1] = copy_to_mode_reg (DImode, operands[1]);
5968       emit_call_insn (gen_call_value_media (operands[0], operands[1],
5969                                             operands[2]));
5970       DONE;
5971     }
5972   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
5973     {
5974       rtx cookie_rtx = operands[3];
5975       long cookie = INTVAL (cookie_rtx);
5976       rtx func = XEXP (operands[1], 0);
5977       rtx r0, r1;
5978
5979       if (flag_pic)
5980         {
5981           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5982             {
5983               rtx reg = gen_reg_rtx (Pmode);
5984
5985               emit_insn (gen_symGOTPLT2reg (reg, func));
5986               func = reg;
5987             }
5988           else
5989             func = legitimize_pic_address (func, Pmode, 0);
5990         }
5991
5992       r0 = gen_rtx_REG (SImode, R0_REG);
5993       r1 = gen_rtx_REG (SImode, R1_REG);
5994
5995       /* Since such a call function may use all call-clobbered
5996          registers, we force a mode switch earlier, so that we don't
5997          run out of registers when adjusting fpscr for the call.  */
5998       emit_insn (gen_force_mode_for_call ());
5999
6000       operands[1] = gen_rtx_SYMBOL_REF (SImode,
6001                                         \"__GCC_shcompact_call_trampoline\");
6002       if (flag_pic)
6003         {
6004           rtx reg = gen_reg_rtx (Pmode);
6005
6006           emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6007           operands[1] = reg;
6008         }
6009       operands[1] = force_reg (SImode, operands[1]);
6010
6011       emit_move_insn (r0, func);
6012       emit_move_insn (r1, cookie_rtx);
6013
6014       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6015         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
6016                                                          operands[1],
6017                                                          operands[2],
6018                                                          operands[3]));
6019       else
6020         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
6021                                                 operands[2], operands[3]));
6022
6023       DONE;
6024     }
6025   else if (TARGET_SHCOMPACT && flag_pic
6026            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
6027            && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
6028     {
6029       rtx reg = gen_reg_rtx (Pmode);
6030
6031       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
6032       XEXP (operands[1], 0) = reg;
6033     }
6034   if (flag_pic && TARGET_SH2
6035       && GET_CODE (operands[1]) == MEM
6036       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6037     {
6038       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
6039                                             operands[2]));
6040       DONE;
6041     }
6042   else
6043     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
6044
6045   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
6046   DONE;
6047 }")
6048
6049 (define_insn "sibcalli"
6050   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
6051          (match_operand 1 "" ""))
6052    (use (reg:PSI FPSCR_REG))
6053    (return)]
6054   "TARGET_SH1"
6055   "jmp  @%0%#"
6056   [(set_attr "needs_delay_slot" "yes")
6057    (set (attr "fp_mode")
6058         (if_then_else (eq_attr "fpu_single" "yes")
6059                       (const_string "single") (const_string "double")))
6060    (set_attr "type" "jump_ind")])
6061
6062 (define_insn "sibcalli_pcrel"
6063   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
6064          (match_operand 1 "" ""))
6065    (use (match_operand 2 "" ""))
6066    (use (reg:PSI FPSCR_REG))
6067    (return)]
6068   "TARGET_SH2"
6069   "braf %0\\n%O2:%#"
6070   [(set_attr "needs_delay_slot" "yes")
6071    (set (attr "fp_mode")
6072         (if_then_else (eq_attr "fpu_single" "yes")
6073                       (const_string "single") (const_string "double")))
6074    (set_attr "type" "jump_ind")])
6075
6076 (define_insn_and_split "sibcall_pcrel"
6077   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
6078          (match_operand 1 "" ""))
6079    (use (reg:PSI FPSCR_REG))
6080    (clobber (match_scratch:SI 2 "=k"))
6081    (return)]
6082   "TARGET_SH2"
6083   "#"
6084   "reload_completed"
6085   [(const_int 0)]
6086   "
6087 {
6088   rtx lab = PATTERN (gen_call_site ());
6089   rtx call_insn;
6090
6091   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
6092   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
6093                                                   lab));
6094   SIBLING_CALL_P (call_insn) = 1;
6095   DONE;
6096 }"
6097   [(set_attr "needs_delay_slot" "yes")
6098    (set (attr "fp_mode")
6099         (if_then_else (eq_attr "fpu_single" "yes")
6100                       (const_string "single") (const_string "double")))
6101    (set_attr "type" "jump_ind")])
6102
6103 (define_insn "sibcall_compact"
6104   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
6105          (match_operand 1 "" ""))
6106    (return)
6107    (use (match_operand:SI 2 "register_operand" "z,x"))
6108    (use (reg:SI R1_REG))
6109    (use (reg:PSI FPSCR_REG))
6110    ;; We want to make sure the `x' above will only match MACH_REG
6111    ;; because sibcall_epilogue may clobber MACL_REG.
6112    (clobber (reg:SI MACL_REG))]
6113   "TARGET_SHCOMPACT"
6114   "@
6115         jmp     @%0%#
6116         jmp     @%0\\n  sts     %2, r0"
6117   [(set_attr "needs_delay_slot" "yes,no")
6118    (set_attr "length" "2,4")
6119    (set (attr "fp_mode") (const_string "single"))
6120    (set_attr "type" "jump_ind")])
6121
6122 (define_insn "sibcall_media"
6123   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k"))
6124          (match_operand 1 "" ""))
6125    (return)]
6126   "TARGET_SHMEDIA"
6127   "blink        %0, r63"
6128   [(set_attr "type" "jump_media")])
6129
6130 (define_expand "sibcall"
6131   [(parallel
6132     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
6133            (match_operand 1 "" ""))
6134      (match_operand 2 "" "")
6135      (use (reg:PSI FPSCR_REG))
6136      (return)])]
6137   ""
6138   "
6139 {
6140   if (TARGET_SHMEDIA)
6141     {
6142       operands[0] = XEXP (operands[0], 0);
6143       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
6144         {
6145           if (! SYMBOL_REF_FLAG (operands[0]))
6146             {
6147               rtx reg = gen_reg_rtx (Pmode);
6148
6149               /* We must not use GOTPLT for sibcalls, because PIC_REG
6150                  must be restored before the PLT code gets to run.  */
6151               emit_insn (gen_symGOT2reg (reg, operands[0]));
6152               operands[0] = reg;
6153             }
6154           else
6155             {
6156               operands[0] = gen_sym2PIC (operands[0]);
6157               PUT_MODE (operands[0], Pmode);
6158             }
6159         }
6160       if (GET_MODE (operands[0]) == SImode)
6161         {
6162           if (GET_CODE (operands[0]) == REG)
6163             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6164           else if (GET_CODE (operands[0]) == SUBREG)
6165             {
6166               operands[0] = SUBREG_REG (operands[0]);
6167               if (GET_MODE (operands[0]) != DImode)
6168                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6169             }
6170           else
6171             {
6172               operands[0] = shallow_copy_rtx (operands[0]);
6173               PUT_MODE (operands[0], DImode);
6174             }
6175         }
6176       if (! target_reg_operand (operands[0], DImode))
6177         operands[0] = copy_to_mode_reg (DImode, operands[0]);
6178       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
6179       DONE;
6180     }
6181   else if (TARGET_SHCOMPACT && operands[2]
6182            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
6183     {
6184       rtx cookie_rtx = operands[2];
6185       long cookie = INTVAL (cookie_rtx);
6186       rtx func = XEXP (operands[0], 0);
6187       rtx mach, r1;
6188
6189       if (flag_pic)
6190         {
6191           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
6192             {
6193               rtx reg = gen_reg_rtx (Pmode);
6194
6195               emit_insn (gen_symGOT2reg (reg, func));
6196               func = reg;
6197             }
6198           else
6199             func = legitimize_pic_address (func, Pmode, 0);
6200         }
6201
6202       /* FIXME: if we could tell whether all argument registers are
6203          already taken, we could decide whether to force the use of
6204          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
6205          simple way to tell.  We could use the CALL_COOKIE, but we
6206          can't currently tell a register used for regular argument
6207          passing from one that is unused.  If we leave it up to reload
6208          to decide which register to use, it seems to always choose
6209          R0_REG, which leaves no available registers in SIBCALL_REGS
6210          to hold the address of the trampoline.  */
6211       mach = gen_rtx_REG (SImode, MACH_REG);
6212       r1 = gen_rtx_REG (SImode, R1_REG);
6213
6214       /* Since such a call function may use all call-clobbered
6215          registers, we force a mode switch earlier, so that we don't
6216          run out of registers when adjusting fpscr for the call.  */
6217       emit_insn (gen_force_mode_for_call ());
6218
6219       operands[0] = gen_rtx_SYMBOL_REF (SImode,
6220                                         \"__GCC_shcompact_call_trampoline\");
6221       if (flag_pic)
6222         {
6223           rtx reg = gen_reg_rtx (Pmode);
6224
6225           emit_insn (gen_symGOT2reg (reg, operands[0]));
6226           operands[0] = reg;
6227         }
6228       operands[0] = force_reg (SImode, operands[0]);
6229
6230       /* We don't need a return trampoline, since the callee will
6231          return directly to the upper caller.  */
6232       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6233         {
6234           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
6235           cookie_rtx = GEN_INT (cookie);
6236         }
6237
6238       emit_move_insn (mach, func);
6239       emit_move_insn (r1, cookie_rtx);
6240
6241       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
6242       DONE;
6243     }
6244   else if (TARGET_SHCOMPACT && flag_pic
6245            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
6246            && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
6247     {
6248       rtx reg = gen_reg_rtx (Pmode);
6249
6250       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
6251       XEXP (operands[0], 0) = reg;
6252     }
6253   if (flag_pic && TARGET_SH2
6254       && GET_CODE (operands[0]) == MEM
6255       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
6256       /* The PLT needs the PIC register, but the epilogue would have
6257          to restore it, so we can only use PC-relative PIC calls for
6258          static functions.  */
6259       && SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
6260     {
6261       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
6262       DONE;
6263     }
6264   else
6265     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
6266
6267   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
6268   DONE;
6269 }")
6270
6271 (define_expand "sibcall_value"
6272   [(set (match_operand 0 "" "")
6273         (call (match_operand 1 "" "")
6274               (match_operand 2 "" "")))
6275    (match_operand 3 "" "")]
6276   ""
6277   "
6278 {
6279   emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
6280   DONE;
6281 }")
6282
6283 (define_insn "call_value_pop_compact"
6284   [(set (match_operand 0 "" "=rf")
6285         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
6286               (match_operand 2 "" "")))
6287    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6288                                  (match_operand 4 "immediate_operand" "n")))
6289    (match_operand 3 "immediate_operand" "n")
6290    (use (reg:SI R0_REG))
6291    (use (reg:SI R1_REG))
6292    (use (reg:PSI FPSCR_REG))
6293    (clobber (reg:SI PR_REG))]
6294   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
6295   "jsr  @%1%#"
6296   [(set_attr "type" "call")
6297    (set (attr "fp_mode")
6298         (if_then_else (eq_attr "fpu_single" "yes")
6299                       (const_string "single") (const_string "double")))
6300    (set_attr "needs_delay_slot" "yes")])
6301
6302 (define_insn "call_value_pop_compact_rettramp"
6303   [(set (match_operand 0 "" "=rf")
6304         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
6305               (match_operand 2 "" "")))
6306    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6307                                  (match_operand 4 "immediate_operand" "n")))
6308    (match_operand 3 "immediate_operand" "n")
6309    (use (reg:SI R0_REG))
6310    (use (reg:SI R1_REG))
6311    (use (reg:PSI FPSCR_REG))
6312    (clobber (reg:SI R10_REG))
6313    (clobber (reg:SI PR_REG))]
6314   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
6315   "jsr  @%1%#"
6316   [(set_attr "type" "call")
6317    (set (attr "fp_mode")
6318         (if_then_else (eq_attr "fpu_single" "yes")
6319                       (const_string "single") (const_string "double")))
6320    (set_attr "needs_delay_slot" "yes")])
6321
6322 (define_expand "call_value_pop"
6323   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
6324                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
6325                                  (match_operand 2 "" "")))
6326               (match_operand 3 "" "")
6327               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6328                                             (match_operand 4 "" "")))])]
6329   "TARGET_SHCOMPACT"
6330   "
6331 {
6332   if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
6333     {
6334       rtx cookie_rtx = operands[3];
6335       long cookie = INTVAL (cookie_rtx);
6336       rtx func = XEXP (operands[1], 0);
6337       rtx r0, r1;
6338
6339       if (flag_pic)
6340         {
6341           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
6342             {
6343               rtx reg = gen_reg_rtx (Pmode);
6344
6345               emit_insn (gen_symGOTPLT2reg (reg, func));
6346               func = reg;
6347             }
6348           else
6349             func = legitimize_pic_address (func, Pmode, 0);
6350         }
6351
6352       r0 = gen_rtx_REG (SImode, R0_REG);
6353       r1 = gen_rtx_REG (SImode, R1_REG);
6354
6355       /* Since such a call function may use all call-clobbered
6356          registers, we force a mode switch earlier, so that we don't
6357          run out of registers when adjusting fpscr for the call.  */
6358       emit_insn (gen_force_mode_for_call ());
6359
6360       operands[1] = gen_rtx_SYMBOL_REF (SImode,
6361                                         \"__GCC_shcompact_call_trampoline\");
6362       if (flag_pic)
6363         {
6364           rtx reg = gen_reg_rtx (Pmode);
6365
6366           emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6367           operands[1] = reg;
6368         }
6369       operands[1] = force_reg (SImode, operands[1]);
6370
6371       emit_move_insn (r0, func);
6372       emit_move_insn (r1, cookie_rtx);
6373
6374       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6375         emit_call_insn (gen_call_value_pop_compact_rettramp
6376                         (operands[0], operands[1], operands[2],
6377                          operands[3], operands[4]));
6378       else
6379         emit_call_insn (gen_call_value_pop_compact
6380                         (operands[0], operands[1], operands[2],
6381                          operands[3], operands[4]));
6382
6383       DONE;
6384     }
6385
6386   abort ();
6387 }")
6388
6389 (define_expand "sibcall_epilogue"
6390   [(return)]
6391   ""
6392   "
6393 {
6394   sh_expand_epilogue ();
6395   if (TARGET_SHCOMPACT)
6396     {
6397       rtx insn, set;
6398
6399       /* If epilogue clobbers r0, preserve it in macl.  */
6400       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
6401         if ((set = single_set (insn))
6402             && GET_CODE (SET_DEST (set)) == REG
6403             && REGNO (SET_DEST (set)) == R0_REG)
6404           {
6405             rtx r0 = gen_rtx_REG (SImode, R0_REG);
6406             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
6407             rtx i;
6408
6409             /* We can't tell at this point whether the sibcall is a
6410                sibcall_compact and, if it is, whether it uses r0 or
6411                mach as operand 2, so let the instructions that
6412                preserve r0 be optimized away if r0 turns out to be
6413                dead.  */
6414             i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
6415             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
6416                                                REG_NOTES (i));
6417             i = emit_move_insn (r0, tmp);
6418             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
6419                                                REG_NOTES (i));
6420             break;
6421           }
6422     }
6423   DONE;
6424 }")
6425
6426 (define_insn "indirect_jump_compact"
6427   [(set (pc)
6428         (match_operand:SI 0 "arith_reg_operand" "r"))]
6429   "TARGET_SH1"
6430   "jmp  @%0%#"
6431   [(set_attr "needs_delay_slot" "yes")
6432    (set_attr "type" "jump_ind")])
6433
6434 (define_expand "indirect_jump"
6435   [(set (pc)
6436         (match_operand 0 "register_operand" ""))]
6437   ""
6438   "
6439 {
6440   if (TARGET_SHMEDIA && GET_MODE (operands[0]) == SImode)
6441     operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6442 }")
6443
6444 ;; The use of operand 1 / 2 helps us distinguish case table jumps
6445 ;; which can be present in structured code from indirect jumps which can not
6446 ;; be present in structured code.  This allows -fprofile-arcs to work.
6447
6448 ;; For SH1 processors.
6449 (define_insn "casesi_jump_1"
6450   [(set (pc)
6451         (match_operand:SI 0 "register_operand" "r"))
6452    (use (label_ref (match_operand 1 "" "")))]
6453   "TARGET_SH1"
6454   "jmp  @%0%#"
6455   [(set_attr "needs_delay_slot" "yes")
6456    (set_attr "type" "jump_ind")])
6457
6458 ;; For all later processors.
6459 (define_insn "casesi_jump_2"
6460   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
6461                       (label_ref (match_operand 1 "" ""))))
6462    (use (label_ref (match_operand 2 "" "")))]
6463   "TARGET_SH2
6464    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
6465   "braf %0%#"
6466   [(set_attr "needs_delay_slot" "yes")
6467    (set_attr "type" "jump_ind")])
6468
6469 (define_insn "casesi_jump_media"
6470   [(set (pc) (match_operand:DI 0 "target_reg_operand" "b"))
6471    (use (label_ref (match_operand 1 "" "")))]
6472   "TARGET_SHMEDIA"
6473   "blink        %0, r63"
6474   [(set_attr "type" "jump_media")])
6475
6476 ;; Call subroutine returning any type.
6477 ;; ??? This probably doesn't work.
6478
6479 (define_expand "untyped_call"
6480   [(parallel [(call (match_operand 0 "" "")
6481                     (const_int 0))
6482               (match_operand 1 "" "")
6483               (match_operand 2 "" "")])]
6484   "TARGET_SH3E || TARGET_SHMEDIA"
6485   "
6486 {
6487   int i;
6488
6489   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
6490
6491   for (i = 0; i < XVECLEN (operands[2], 0); i++)
6492     {
6493       rtx set = XVECEXP (operands[2], 0, i);
6494       emit_move_insn (SET_DEST (set), SET_SRC (set));
6495     }
6496
6497   /* The optimizer does not know that the call sets the function value
6498      registers we stored in the result block.  We avoid problems by
6499      claiming that all hard registers are used and clobbered at this
6500      point.  */
6501   emit_insn (gen_blockage ());
6502
6503   DONE;
6504 }")
6505 \f
6506 ;; ------------------------------------------------------------------------
6507 ;; Misc insns
6508 ;; ------------------------------------------------------------------------
6509
6510 (define_insn "dect"
6511   [(set (reg:SI T_REG)
6512         (eq:SI (match_operand:SI 0 "arith_reg_operand" "+r") (const_int 1)))
6513    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
6514   "TARGET_SH2"
6515   "dt   %0"
6516   [(set_attr "type" "arith")])
6517
6518 (define_insn "nop"
6519   [(const_int 0)]
6520   ""
6521   "nop")
6522
6523 ;; Load address of a label. This is only generated by the casesi expand,
6524 ;; and by machine_dependent_reorg (fixing up fp moves).
6525 ;; This must use unspec, because this only works for labels that are
6526 ;; within range,
6527
6528 (define_insn "mova"
6529   [(set (reg:SI R0_REG)
6530         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
6531   "TARGET_SH1"
6532   "mova %O0,r0"
6533   [(set_attr "in_delay_slot" "no")
6534    (set_attr "type" "arith")])
6535
6536 ;; machine_dependent_reorg() will make this a `mova'.
6537 (define_insn "mova_const"
6538   [(set (reg:SI R0_REG)
6539         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
6540   "TARGET_SH1"
6541   "#"
6542   [(set_attr "in_delay_slot" "no")
6543    (set_attr "type" "arith")])
6544
6545 (define_expand "GOTaddr2picreg"
6546   [(set (reg:SI R0_REG)
6547         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
6548                    UNSPEC_MOVA))
6549    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
6550    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
6551   "" "
6552 {
6553   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
6554   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
6555
6556   if (TARGET_SH5)
6557     operands[1] = gen_datalabel_ref (operands[1]);
6558
6559   if (TARGET_SHMEDIA)
6560     {
6561       rtx tr = gen_rtx_REG (DImode, TR0_REG);
6562       rtx dipic = operands[0];
6563       rtx lab = PATTERN (gen_call_site ());
6564       rtx insn, equiv;
6565
6566       equiv = operands[1];
6567       operands[1] = gen_rtx_MINUS (DImode,
6568                                    operands[1],
6569                                    gen_rtx_CONST
6570                                    (DImode,
6571                                     gen_rtx_MINUS (DImode,
6572                                                    gen_rtx_CONST (DImode,
6573                                                                   lab),
6574                                                    pc_rtx)));
6575       operands[1] = gen_sym2PIC (operands[1]);
6576       PUT_MODE (operands[1], DImode);
6577
6578       if (GET_MODE (dipic) != DImode)
6579         dipic = gen_rtx_SUBREG (DImode, dipic, 0);
6580
6581       if (TARGET_SHMEDIA64)
6582         emit_insn (gen_movdi_const (dipic, operands[1]));
6583       else
6584         emit_insn (gen_movdi_const_32bit (dipic, operands[1]));
6585
6586       emit_insn (gen_ptrel (tr, dipic, lab));
6587
6588       if (GET_MODE (operands[0]) != GET_MODE (tr))
6589         tr = gen_rtx_SUBREG (GET_MODE (operands[0]), tr, 0);
6590
6591       insn = emit_move_insn (operands[0], tr);
6592
6593       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
6594                                             REG_NOTES (insn));
6595
6596       DONE;
6597     }
6598 }
6599 ")
6600
6601 ;; When generating PIC, we must match label_refs especially, because
6602 ;; they do not satisfy LEGITIMATE_PIC_OPERAND_P(), and we don't want
6603 ;; them to do, because they can't be loaded directly into
6604 ;; non-branch-target registers.
6605 (define_insn "*pt"
6606   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6607         (match_operand:DI 1 "" "T"))]
6608   "TARGET_SHMEDIA && flag_pic
6609    && EXTRA_CONSTRAINT_T (operands[1])"
6610   "pt   %1, %0"
6611   [(set_attr "type" "pt_media")
6612    (set_attr "length" "*")])
6613
6614 (define_insn "*ptb"
6615   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6616         (const:DI (unspec:DI [(match_operand:DI 1 "" "T")]
6617                              UNSPEC_DATALABEL)))]
6618   "TARGET_SHMEDIA && flag_pic
6619    && EXTRA_CONSTRAINT_T (operands[1])"
6620   "ptb/u        datalabel %1, %0"
6621   [(set_attr "type" "pt_media")
6622    (set_attr "length" "*")])
6623
6624 (define_insn "ptrel"
6625   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6626         (plus:DI (match_operand:DI 1 "register_operand" "r")
6627               (pc)))
6628    (match_operand:DI 2 "" "")]
6629   "TARGET_SHMEDIA"
6630   "%O2: ptrel/u %1, %0"
6631   [(set_attr "type" "ptabs_media")])
6632
6633 (define_expand "builtin_setjmp_receiver"
6634   [(match_operand 0 "" "")]
6635   "flag_pic"
6636   "
6637 {
6638   emit_insn (gen_GOTaddr2picreg ());
6639   DONE;
6640 }")
6641
6642 (define_expand "call_site"
6643   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
6644   "TARGET_SH1"
6645   "
6646 {
6647   static HOST_WIDE_INT i = 0;
6648   operands[0] = GEN_INT (i);
6649   i++;
6650 }")
6651
6652 (define_expand "sym_label2reg"
6653   [(set (match_operand:SI 0 "" "")
6654         (const:SI (minus:SI
6655                    (const:SI
6656                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
6657                    (const:SI
6658                     (plus:SI
6659                      (match_operand:SI 2 "" "")
6660                      (const_int 2))))))]
6661   "TARGET_SH1" "")
6662
6663 (define_expand "symGOT_load"
6664   [(set (match_dup 2) (match_operand 1 "" ""))
6665    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
6666    (set (match_operand 0 "" "") (mem (match_dup 3)))]
6667   ""
6668   "
6669 {
6670   rtx insn;
6671
6672   operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6673   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6674
6675   if (TARGET_SHMEDIA)
6676     {
6677       rtx reg = operands[2];
6678
6679       if (GET_MODE (reg) != DImode)
6680         reg = gen_rtx_SUBREG (DImode, reg, 0);
6681
6682       if (flag_pic > 1)
6683         emit_insn (gen_movdi_const_32bit (reg, operands[1]));
6684       else
6685         emit_insn (gen_movdi_const_16bit (reg, operands[1]));
6686     }
6687   else
6688     emit_move_insn (operands[2], operands[1]);
6689
6690   emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
6691                                              operands[2],
6692                                              gen_rtx_REG (Pmode, PIC_REG)));
6693
6694   insn = emit_move_insn (operands[0], gen_rtx_MEM (Pmode, operands[3]));
6695
6696   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, XVECEXP (XEXP (operands[1],
6697                                                                   0), 0, 0),
6698                                         REG_NOTES (insn));
6699
6700   DONE;
6701 }")
6702
6703 (define_expand "sym2GOT"
6704   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
6705   ""
6706   "")
6707
6708 (define_expand "symGOT2reg"
6709   [(match_operand 0 "" "") (match_operand 1 "" "")]
6710   ""
6711   "
6712 {
6713   rtx gotsym, insn;
6714
6715   gotsym = gen_sym2GOT (operands[1]);
6716   PUT_MODE (gotsym, Pmode);
6717   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
6718
6719   RTX_UNCHANGING_P (SET_SRC (PATTERN (insn))) = 1;
6720
6721   DONE;
6722 }")
6723
6724 (define_expand "sym2GOTPLT"
6725   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTPLT))]
6726   ""
6727   "")
6728
6729 (define_expand "symGOTPLT2reg"
6730   [(match_operand 0 "" "") (match_operand 1 "" "")]
6731   ""
6732   "
6733 {
6734   emit_insn (gen_symGOT_load (operands[0], gen_sym2GOTPLT (operands[1])));
6735   DONE;
6736 }")
6737
6738 (define_expand "sym2GOTOFF"
6739   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
6740   ""
6741   "")
6742
6743 (define_expand "symGOTOFF2reg"
6744   [(match_operand 0 "" "") (match_operand 1 "" "")]
6745   ""
6746   "
6747 {
6748   rtx gotoffsym, insn;
6749   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
6750
6751   gotoffsym = gen_sym2GOTOFF (operands[1]);
6752   PUT_MODE (gotoffsym, Pmode);
6753   emit_move_insn (t, gotoffsym);
6754   insn = emit_move_insn (operands[0],
6755                          gen_rtx_PLUS (Pmode, t,
6756                                        gen_rtx_REG (Pmode, PIC_REG)));
6757
6758   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
6759                                         REG_NOTES (insn));
6760
6761   DONE;
6762 }")
6763
6764 (define_expand "symPLT_label2reg"
6765   [(set (match_operand:SI 0 "" "")
6766         (const:SI (minus:SI
6767                    (const:SI
6768                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
6769                    (const:SI
6770                     (minus:SI
6771                      (const:SI (plus:SI
6772                                 (match_operand:SI 2 "" "")
6773                                 (const_int 2)))
6774                      (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
6775    ;; Even though the PIC register is not really used by the call
6776    ;; sequence in which this is expanded, the PLT code assumes the PIC
6777    ;; register is set, so we must not skip its initialization.  Since
6778    ;; we only use this expand as part of calling sequences, and never
6779    ;; to take the address of a function, this is the best point to
6780    ;; insert the (use).  Using the PLT to take the address of a
6781    ;; function would be wrong, not only because the PLT entry could
6782    ;; then be called from a function that doesn't initialize the PIC
6783    ;; register to the proper GOT, but also because pointers to the
6784    ;; same function might not compare equal, should they be set by
6785    ;; different shared libraries.
6786    (use (reg:SI PIC_REG))]
6787   "TARGET_SH1"
6788   "")
6789
6790 (define_expand "sym2PIC"
6791   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
6792   ""
6793   "")
6794
6795 ;; case instruction for switch statements.
6796
6797 ;; Operand 0 is index
6798 ;; operand 1 is the minimum bound
6799 ;; operand 2 is the maximum bound - minimum bound + 1
6800 ;; operand 3 is CODE_LABEL for the table;
6801 ;; operand 4 is the CODE_LABEL to go to if index out of range.
6802
6803 (define_expand "casesi"
6804   [(match_operand:SI 0 "arith_reg_operand" "")
6805    (match_operand:SI 1 "arith_reg_operand" "")
6806    (match_operand:SI 2 "arith_reg_operand" "")
6807    (match_operand 3 "" "") (match_operand 4 "" "")]
6808   ""
6809   "
6810 {
6811   rtx reg = gen_reg_rtx (SImode);
6812   rtx reg2 = gen_reg_rtx (SImode);
6813   if (TARGET_SHMEDIA)
6814     {
6815       rtx reg = gen_reg_rtx (DImode);
6816       rtx reg2 = gen_reg_rtx (DImode);
6817       rtx reg3 = gen_reg_rtx (DImode);
6818       rtx reg4 = gen_reg_rtx (DImode);
6819       rtx reg5 = gen_reg_rtx (DImode);
6820
6821       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
6822       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
6823       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
6824
6825       emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
6826       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
6827       emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
6828       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
6829       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
6830                                                (DImode, operands[3])));
6831       emit_insn (gen_casesi_load_media (reg4, reg3, reg2, operands[3]));
6832       emit_move_insn (reg5, gen_rtx_PLUS (DImode, reg3, reg4));
6833       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
6834       emit_barrier ();
6835       DONE;
6836     }
6837   operands[1] = copy_to_mode_reg (SImode, operands[1]);
6838   operands[2] = copy_to_mode_reg (SImode, operands[2]);
6839   /* If optimizing, casesi_worker depends on the mode of the instruction
6840      before label it 'uses' - operands[3].  */
6841   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
6842                            reg));
6843   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
6844   if (TARGET_SH2)
6845     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
6846   else
6847     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
6848   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
6849      operands[3], but to lab.  We will fix this up in
6850      machine_dependent_reorg.  */
6851   emit_barrier ();
6852   DONE;
6853 }")
6854
6855 (define_expand "casesi_0"
6856   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
6857    (set (match_dup 4) (minus:SI (match_dup 4)
6858                                 (match_operand:SI 1 "arith_operand" "")))
6859    (set (reg:SI T_REG)
6860         (gtu:SI (match_dup 4)
6861                 (match_operand:SI 2 "arith_reg_operand" "")))
6862    (set (pc)
6863         (if_then_else (ne (reg:SI T_REG)
6864                           (const_int 0))
6865                       (label_ref (match_operand 3 "" ""))
6866                       (pc)))]
6867   "TARGET_SH1"
6868   "")
6869
6870 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
6871 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
6872 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
6873
6874 (define_insn "casesi_worker_0"
6875   [(set (match_operand:SI 0 "register_operand" "=r,r")
6876         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
6877                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6878    (clobber (match_scratch:SI 3 "=X,1"))
6879    (clobber (match_scratch:SI 4 "=&z,z"))]
6880   "TARGET_SH1"
6881   "#")
6882
6883 (define_split
6884   [(set (match_operand:SI 0 "register_operand" "")
6885         (unspec:SI [(match_operand:SI 1 "register_operand" "")
6886                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6887    (clobber (match_scratch:SI 3 ""))
6888    (clobber (match_scratch:SI 4 ""))]
6889   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
6890   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
6891    (parallel [(set (match_dup 0)
6892               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
6893                           (label_ref (match_dup 2))] UNSPEC_CASESI))
6894               (clobber (match_dup 3))])
6895    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
6896   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
6897
6898 (define_split
6899   [(set (match_operand:SI 0 "register_operand" "")
6900         (unspec:SI [(match_operand:SI 1 "register_operand" "")
6901                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6902    (clobber (match_scratch:SI 3 ""))
6903    (clobber (match_scratch:SI 4 ""))]
6904   "TARGET_SH2 && reload_completed"
6905   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
6906    (parallel [(set (match_dup 0)
6907               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
6908                           (label_ref (match_dup 2))] UNSPEC_CASESI))
6909               (clobber (match_dup 3))])]
6910   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
6911
6912 (define_insn "*casesi_worker"
6913   [(set (match_operand:SI 0 "register_operand" "=r,r")
6914         (unspec:SI [(reg:SI R0_REG)
6915                     (match_operand:SI 1 "register_operand" "0,r")
6916                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6917    (clobber (match_scratch:SI 3 "=X,1"))]
6918   "TARGET_SH1"
6919   "*
6920 {
6921   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
6922
6923   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
6924     abort ();
6925
6926   switch (GET_MODE (diff_vec))
6927     {
6928     case SImode:
6929       return \"shll2    %1\;mov.l       @(r0,%1),%0\";
6930     case HImode:
6931       return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
6932     case QImode:
6933       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
6934         return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
6935       return \"mov.b    @(r0,%1),%0\";
6936     default:
6937       abort ();
6938     }
6939 }"
6940   [(set_attr "length" "4")])
6941
6942 (define_insn "casesi_shift_media"
6943   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
6944         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
6945                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
6946                     UNSPEC_CASESI)))]
6947   "TARGET_SHMEDIA"
6948   "*
6949 {
6950   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
6951
6952   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
6953     abort ();
6954
6955   switch (GET_MODE (diff_vec))
6956     {
6957     case SImode:
6958       return \"shlli    %1, 2, %0\";
6959     case HImode:
6960       return \"shlli    %1, 1, %0\";
6961     case QImode:
6962       if (rtx_equal_p (operands[0], operands[1]))
6963         return \"\";
6964       return \"add      %1, r63, %0\";
6965     default:
6966       abort ();
6967     }
6968 }"
6969   [(set_attr "type" "arith_media")])
6970
6971 (define_insn "casesi_load_media"
6972   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
6973         (mem:DI (unspec [(match_operand 1 "arith_reg_operand" "r")
6974                          (match_operand 2 "arith_reg_operand" "r")
6975                          (label_ref:DI (match_operand 3 "" ""))] 2)))]
6976   "TARGET_SHMEDIA"
6977   "*
6978 {
6979   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
6980
6981   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
6982     abort ();
6983
6984   switch (GET_MODE (diff_vec))
6985     {
6986     case SImode:
6987       return \"ldx.l    %1, %2, %0\";
6988     case HImode:
6989 #if 0
6990       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
6991         return \"ldx.uw %1, %2, %0\";
6992 #endif
6993       return \"ldx.w    %1, %2, %0\";
6994     case QImode:
6995       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
6996         return \"ldx.ub %1, %2, %0\";
6997       return \"ldx.b    %1, %2, %0\";
6998     default:
6999       abort ();
7000     }
7001 }"
7002   [(set_attr "type" "load_media")])
7003
7004 (define_expand "return"
7005   [(return)]
7006   "reload_completed && ! sh_need_epilogue ()"
7007   "
7008 {
7009   if (TARGET_SHMEDIA)
7010     {
7011       emit_jump_insn (gen_return_media ());
7012       DONE;
7013     }
7014
7015   if (TARGET_SHCOMPACT
7016       && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
7017     {
7018       emit_jump_insn (gen_shcompact_return_tramp ());
7019       DONE;
7020     }
7021 }")
7022
7023 (define_insn "*return_i"
7024   [(return)]
7025   "TARGET_SH1 && ! (TARGET_SHCOMPACT
7026                     && (current_function_args_info.call_cookie
7027                         & CALL_COOKIE_RET_TRAMP (1)))
7028    && reload_completed"
7029   "%@   %#"
7030   [(set_attr "type" "return")
7031    (set_attr "needs_delay_slot" "yes")])
7032
7033 (define_expand "shcompact_return_tramp"
7034   [(return)]
7035   "TARGET_SHCOMPACT
7036    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
7037   "
7038 {
7039   rtx reg = gen_rtx_REG (Pmode, R0_REG);
7040   rtx sym = gen_rtx_SYMBOL_REF (Pmode,
7041                                 \"__GCC_shcompact_return_trampoline\");
7042
7043   if (flag_pic)
7044     emit_insn (gen_symGOTPLT2reg (reg, sym));
7045   else
7046     emit_move_insn (reg, sym);
7047
7048   emit_jump_insn (gen_shcompact_return_tramp_i ());
7049   DONE;
7050 }")
7051
7052 (define_insn "shcompact_return_tramp_i"
7053   [(parallel [(return) (use (reg:SI R0_REG))])]
7054   "TARGET_SHCOMPACT
7055    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
7056   "jmp  @r0%#"
7057   [(set_attr "type" "jump_ind")
7058    (set_attr "needs_delay_slot" "yes")])
7059
7060 (define_insn "return_media_i"
7061   [(parallel [(return) (use (match_operand:DI 0 "target_reg_operand" "k"))])]
7062   "TARGET_SHMEDIA && reload_completed"
7063   "blink        %0, r63"
7064   [(set_attr "type" "jump_media")])
7065
7066 (define_expand "return_media"
7067   [(return)]
7068   "TARGET_SHMEDIA && reload_completed"
7069   "
7070 {
7071   int tr_regno = sh_media_register_for_return ();
7072   rtx tr;
7073
7074   if (tr_regno < 0)
7075     {
7076       rtx r18 = gen_rtx_REG (DImode, PR_MEDIA_REG);
7077
7078       tr_regno = TR0_REG;
7079       tr = gen_rtx_REG (DImode, tr_regno);
7080       emit_move_insn (tr, r18);
7081     }
7082   else
7083     tr = gen_rtx_REG (DImode, tr_regno);
7084
7085   emit_jump_insn (gen_return_media_i (tr));
7086   DONE;
7087 }")
7088
7089 (define_insn "shcompact_preserve_incoming_args"
7090   [(set (match_operand:SI 0 "register_operand" "+r")
7091         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
7092   "TARGET_SHCOMPACT"
7093   ""
7094   [(set_attr "length" "0")])
7095
7096 (define_insn "shcompact_incoming_args"
7097   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
7098    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
7099    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
7100    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
7101    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
7102    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
7103    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
7104    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
7105    (set (mem:BLK (reg:SI MACL_REG))
7106         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
7107    (use (reg:SI R0_REG))
7108    (clobber (reg:SI R0_REG))
7109    (clobber (reg:SI MACL_REG))
7110    (clobber (reg:SI MACH_REG))
7111    (clobber (reg:SI PR_REG))]
7112   "TARGET_SHCOMPACT"
7113   "jsr  @r0%#"
7114   [(set_attr "needs_delay_slot" "yes")])
7115
7116 (define_insn "shmedia_save_restore_regs_compact"
7117   [(set (reg:SI SP_REG)
7118         (plus:SI (reg:SI SP_REG)
7119                  (match_operand:SI 0 "immediate_operand" "i")))
7120    (use (reg:SI R0_REG))
7121    (clobber (reg:SI PR_REG))]
7122   "TARGET_SHCOMPACT
7123    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
7124        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
7125   "jsr @r0%#"
7126   [(set_attr "needs_delay_slot" "yes")])
7127
7128 (define_expand "prologue"
7129   [(const_int 0)]
7130   ""
7131   "sh_expand_prologue (); DONE;")
7132
7133 (define_expand "epilogue"
7134   [(return)]
7135   ""
7136   "
7137 {
7138   sh_expand_epilogue ();
7139   emit_jump_insn (gen_return ());
7140   DONE;
7141 }")
7142
7143 (define_insn "blockage"
7144   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
7145   ""
7146   ""
7147   [(set_attr "length" "0")])
7148 \f
7149 ;; ------------------------------------------------------------------------
7150 ;; Scc instructions
7151 ;; ------------------------------------------------------------------------
7152
7153 (define_insn "movt"
7154   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7155         (eq:SI (reg:SI T_REG) (const_int 1)))]
7156   "TARGET_SH1"
7157   "movt %0"
7158   [(set_attr "type" "arith")])
7159
7160 (define_expand "seq"
7161   [(set (match_operand:SI 0 "arith_reg_operand" "")
7162         (match_dup 1))]
7163   ""
7164   "
7165 {
7166   if (TARGET_SHMEDIA)
7167     {
7168       if (GET_MODE (operands[0]) != DImode)
7169         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7170       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7171       if (sh_compare_op1 != const0_rtx)
7172         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7173                                     ? GET_MODE (sh_compare_op0)
7174                                     : GET_MODE (sh_compare_op1),
7175                                     sh_compare_op1);
7176
7177       switch (GET_MODE (sh_compare_op0))
7178         {
7179         case DImode:
7180           emit_insn (gen_cmpeqdi_media (operands[0],
7181                                         sh_compare_op0, sh_compare_op1));
7182           break;
7183
7184         case SFmode:
7185           if (! TARGET_SHMEDIA_FPU)
7186             FAIL;
7187           emit_insn (gen_cmpeqsf_media (operands[0],
7188                                         sh_compare_op0, sh_compare_op1));
7189           break;
7190
7191         case DFmode:
7192           if (! TARGET_SHMEDIA_FPU)
7193             FAIL;
7194           emit_insn (gen_cmpeqdf_media (operands[0],
7195                                         sh_compare_op0, sh_compare_op1));
7196           break;
7197
7198         default:
7199           FAIL;
7200         }
7201       DONE;
7202     }
7203   operands[1] = prepare_scc_operands (EQ);
7204 }")
7205
7206 (define_expand "slt"
7207   [(set (match_operand:SI 0 "arith_reg_operand" "")
7208         (match_dup 1))]
7209   ""
7210   "
7211 {
7212   if (TARGET_SHMEDIA)
7213     {
7214       if (GET_MODE (operands[0]) != DImode)
7215         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7216       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7217       if (sh_compare_op1 != const0_rtx)
7218         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7219                                     ? GET_MODE (sh_compare_op0)
7220                                     : GET_MODE (sh_compare_op1),
7221                                     sh_compare_op1);
7222
7223       switch (GET_MODE (sh_compare_op0))
7224         {
7225         case DImode:
7226           emit_insn (gen_cmpgtdi_media (operands[0],
7227                                         sh_compare_op1, sh_compare_op0));
7228           break;
7229
7230         case SFmode:
7231           if (! TARGET_SHMEDIA_FPU)
7232             FAIL;
7233           emit_insn (gen_cmpgtsf_media (operands[0],
7234                                         sh_compare_op1, sh_compare_op0));
7235           break;
7236
7237         case DFmode:
7238           if (! TARGET_SHMEDIA_FPU)
7239             FAIL;
7240           emit_insn (gen_cmpgtdf_media (operands[0],
7241                                         sh_compare_op1, sh_compare_op0));
7242           break;
7243
7244         default:
7245           FAIL;
7246         }
7247       DONE;
7248     }
7249   operands[1] = prepare_scc_operands (LT);
7250 }")
7251
7252 (define_expand "sle"
7253   [(match_operand:SI 0 "arith_reg_operand" "")]
7254   ""
7255   "
7256 {
7257   rtx tmp = sh_compare_op0;
7258
7259   if (TARGET_SHMEDIA)
7260     {
7261       if (GET_MODE (operands[0]) != DImode)
7262         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7263       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7264       if (sh_compare_op1 != const0_rtx)
7265         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7266                                     ? GET_MODE (sh_compare_op0)
7267                                     : GET_MODE (sh_compare_op1),
7268                                     sh_compare_op1);
7269
7270       switch (GET_MODE (sh_compare_op0))
7271         {
7272         case DImode:
7273           {
7274             tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7275
7276             emit_insn (gen_cmpgtdi_media (tmp,
7277                                           sh_compare_op0, sh_compare_op1));
7278             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7279             break;
7280           }
7281
7282         case SFmode:
7283           if (! TARGET_SHMEDIA_FPU)
7284             FAIL;
7285           emit_insn (gen_cmpgesf_media (operands[0],
7286                                         sh_compare_op1, sh_compare_op0));
7287           break;
7288
7289         case DFmode:
7290           if (! TARGET_SHMEDIA_FPU)
7291             FAIL;
7292           emit_insn (gen_cmpgedf_media (operands[0],
7293                                         sh_compare_op1, sh_compare_op0));
7294           break;
7295
7296         default:
7297           FAIL;
7298         }
7299       DONE;
7300     }
7301
7302   sh_compare_op0 = sh_compare_op1;
7303   sh_compare_op1 = tmp;
7304   emit_insn (gen_sge (operands[0]));
7305   DONE;
7306 }")
7307
7308 (define_expand "sgt"
7309   [(set (match_operand:SI 0 "arith_reg_operand" "")
7310         (match_dup 1))]
7311   ""
7312   "
7313 {
7314   if (TARGET_SHMEDIA)
7315     {
7316       if (GET_MODE (operands[0]) != DImode)
7317         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7318       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7319       if (sh_compare_op1 != const0_rtx)
7320         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7321                                     ? GET_MODE (sh_compare_op0)
7322                                     : GET_MODE (sh_compare_op1),
7323                                     sh_compare_op1);
7324
7325       switch (GET_MODE (sh_compare_op0))
7326         {
7327         case DImode:
7328           emit_insn (gen_cmpgtdi_media (operands[0],
7329                                         sh_compare_op0, sh_compare_op1));
7330           break;
7331
7332         case SFmode:
7333           if (! TARGET_SHMEDIA_FPU)
7334             FAIL;
7335           emit_insn (gen_cmpgtsf_media (operands[0],
7336                                         sh_compare_op0, sh_compare_op1));
7337           break;
7338
7339         case DFmode:
7340           if (! TARGET_SHMEDIA_FPU)
7341             FAIL;
7342           emit_insn (gen_cmpgtdf_media (operands[0],
7343                                         sh_compare_op0, sh_compare_op1));
7344           break;
7345
7346         default:
7347           FAIL;
7348         }
7349       DONE;
7350     }
7351   operands[1] = prepare_scc_operands (GT);
7352 }")
7353
7354 (define_expand "sge"
7355   [(set (match_operand:SI 0 "arith_reg_operand" "")
7356         (match_dup 1))]
7357   ""
7358   "
7359 {
7360   if (TARGET_SHMEDIA)
7361     {
7362       if (GET_MODE (operands[0]) != DImode)
7363         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7364       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7365       if (sh_compare_op1 != const0_rtx)
7366         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7367                                     ? GET_MODE (sh_compare_op0)
7368                                     : GET_MODE (sh_compare_op1),
7369                                     sh_compare_op1);
7370
7371       switch (GET_MODE (sh_compare_op0))
7372         {
7373         case DImode:
7374           {
7375             rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7376
7377             emit_insn (gen_cmpgtdi_media (tmp,
7378                                           sh_compare_op1, sh_compare_op0));
7379             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7380             break;
7381           }
7382
7383         case SFmode:
7384           if (! TARGET_SHMEDIA_FPU)
7385             FAIL;
7386           emit_insn (gen_cmpgesf_media (operands[0],
7387                                         sh_compare_op0, sh_compare_op1));
7388           break;
7389
7390         case DFmode:
7391           if (! TARGET_SHMEDIA_FPU)
7392             FAIL;
7393           emit_insn (gen_cmpgedf_media (operands[0],
7394                                         sh_compare_op0, sh_compare_op1));
7395           break;
7396
7397         default:
7398           FAIL;
7399         }
7400       DONE;
7401     }
7402
7403   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7404     {
7405       if (TARGET_IEEE)
7406         {
7407           rtx lab = gen_label_rtx ();
7408           prepare_scc_operands (EQ);
7409           emit_jump_insn (gen_branch_true (lab));
7410           prepare_scc_operands (GT);
7411           emit_label (lab);
7412           emit_insn (gen_movt (operands[0]));
7413         }
7414       else
7415         emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
7416       DONE;
7417     }
7418   operands[1] = prepare_scc_operands (GE);
7419 }")
7420
7421 (define_expand "sgtu"
7422   [(set (match_operand:SI 0 "arith_reg_operand" "")
7423         (match_dup 1))]
7424   ""
7425   "
7426 {
7427   if (TARGET_SHMEDIA)
7428     {
7429       if (GET_MODE (operands[0]) != DImode)
7430         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7431       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7432       if (sh_compare_op1 != const0_rtx)
7433         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7434                                     ? GET_MODE (sh_compare_op0)
7435                                     : GET_MODE (sh_compare_op1),
7436                                     sh_compare_op1);
7437
7438       emit_insn (gen_cmpgtudi_media (operands[0],
7439                                      sh_compare_op0, sh_compare_op1));
7440       DONE;
7441     }
7442   operands[1] = prepare_scc_operands (GTU);
7443 }")
7444
7445 (define_expand "sltu"
7446   [(set (match_operand:SI 0 "arith_reg_operand" "")
7447         (match_dup 1))]
7448   ""
7449   "
7450 {
7451   if (TARGET_SHMEDIA)
7452     {
7453       if (GET_MODE (operands[0]) != DImode)
7454         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7455       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7456       if (sh_compare_op1 != const0_rtx)
7457         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7458                                     ? GET_MODE (sh_compare_op0)
7459                                     : GET_MODE (sh_compare_op1),
7460                                     sh_compare_op1);
7461
7462       emit_insn (gen_cmpgtudi_media (operands[0],
7463                                      sh_compare_op1, sh_compare_op0));
7464       DONE;
7465     }
7466   operands[1] = prepare_scc_operands (LTU);
7467 }")
7468
7469 (define_expand "sleu"
7470   [(set (match_operand:SI 0 "arith_reg_operand" "")
7471         (match_dup 1))]
7472   ""
7473   "
7474 {
7475   if (TARGET_SHMEDIA)
7476     {
7477       rtx tmp;
7478
7479       if (GET_MODE (operands[0]) != DImode)
7480         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7481       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7482       if (sh_compare_op1 != const0_rtx)
7483         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7484                                     ? GET_MODE (sh_compare_op0)
7485                                     : GET_MODE (sh_compare_op1),
7486                                     sh_compare_op1);
7487
7488       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7489
7490       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
7491       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7492
7493       DONE;
7494     }
7495   operands[1] = prepare_scc_operands (LEU);
7496 }")
7497
7498 (define_expand "sgeu"
7499   [(set (match_operand:SI 0 "arith_reg_operand" "")
7500         (match_dup 1))]
7501   ""
7502   "
7503 {
7504   if (TARGET_SHMEDIA)
7505     {
7506       rtx tmp;
7507
7508       if (GET_MODE (operands[0]) != DImode)
7509         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7510       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7511       if (sh_compare_op1 != const0_rtx)
7512         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7513                                     ? GET_MODE (sh_compare_op0)
7514                                     : GET_MODE (sh_compare_op1),
7515                                     sh_compare_op1);
7516
7517       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7518
7519       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
7520       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7521
7522       DONE;
7523     }
7524
7525   operands[1] = prepare_scc_operands (GEU);
7526 }")
7527
7528 ;; sne moves the complement of the T reg to DEST like this:
7529 ;;      cmp/eq ...
7530 ;;      mov    #-1,temp
7531 ;;      negc   temp,dest
7532 ;;   This is better than xoring compare result with 1 because it does
7533 ;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
7534 ;;   loop.
7535
7536 (define_expand "sne"
7537   [(set (match_dup 2) (const_int -1))
7538    (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
7539                    (neg:SI (plus:SI (match_dup 1)
7540                                     (match_dup 2))))
7541               (set (reg:SI T_REG)
7542                    (ne:SI (ior:SI (match_dup 1) (match_dup 2))
7543                           (const_int 0)))])]
7544   ""
7545   "
7546 {
7547   if (TARGET_SHMEDIA)
7548     {
7549       rtx tmp;
7550
7551       if (GET_MODE (operands[0]) != DImode)
7552         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7553
7554       if (! TARGET_SHMEDIA_FPU && GET_MODE (sh_compare_op0) != DImode)
7555         FAIL;
7556
7557       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7558       if (sh_compare_op1 != const0_rtx)
7559         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7560                                     ? GET_MODE (sh_compare_op0)
7561                                     : GET_MODE (sh_compare_op1),
7562                                     sh_compare_op1);
7563
7564       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7565
7566       emit_insn (gen_seq (tmp));
7567       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7568
7569       DONE;
7570     }
7571
7572    operands[1] = prepare_scc_operands (EQ);
7573    operands[2] = gen_reg_rtx (SImode);
7574 }")
7575
7576 (define_expand "sunordered"
7577   [(set (match_operand:DI 0 "arith_reg_operand" "")
7578         (unordered:DI (match_dup 1) (match_dup 2)))]
7579   "TARGET_SHMEDIA_FPU"
7580   "
7581 {
7582   operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7583   operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
7584 }")
7585
7586 ;; Use the same trick for FP sle / sge
7587 (define_expand "movnegt"
7588   [(set (match_dup 2) (const_int -1))
7589    (parallel [(set (match_operand 0 "" "")
7590                    (neg:SI (plus:SI (match_dup 1)
7591                                     (match_dup 2))))
7592               (set (reg:SI T_REG)
7593                    (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
7594                           (const_int 0)))])]
7595   "TARGET_SH1"
7596   "operands[2] = gen_reg_rtx (SImode);")
7597
7598 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
7599 ;; This prevents a regression that occurred when we switched from xor to
7600 ;; mov/neg for sne.
7601
7602 (define_split
7603   [(set (match_operand:SI 0 "arith_reg_operand" "")
7604         (plus:SI (reg:SI T_REG)
7605                  (const_int -1)))]
7606   "TARGET_SH1"
7607   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
7608    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
7609   "")
7610
7611 ;; -------------------------------------------------------------------------
7612 ;; Instructions to cope with inline literal tables
7613 ;; -------------------------------------------------------------------------
7614
7615 ; 2 byte integer in line
7616
7617 (define_insn "consttable_2"
7618  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7619                     (match_operand 1 "" "")]
7620                    UNSPECV_CONST2)]
7621  ""
7622  "*
7623 {
7624   if (operands[1] != const0_rtx)
7625     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
7626   return \"\";
7627 }"
7628  [(set_attr "length" "2")
7629  (set_attr "in_delay_slot" "no")])
7630
7631 ; 4 byte integer in line
7632
7633 (define_insn "consttable_4"
7634  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7635                     (match_operand 1 "" "")]
7636                    UNSPECV_CONST4)]
7637  ""
7638  "*
7639 {
7640   if (operands[1] != const0_rtx)
7641     assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
7642   return \"\";
7643 }"
7644  [(set_attr "length" "4")
7645   (set_attr "in_delay_slot" "no")])
7646
7647 ; 8 byte integer in line
7648
7649 (define_insn "consttable_8"
7650  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7651                     (match_operand 1 "" "")]
7652                    UNSPECV_CONST8)]
7653  ""
7654  "*
7655 {
7656   if (operands[1] != const0_rtx)
7657     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
7658   return \"\";
7659 }"
7660  [(set_attr "length" "8")
7661   (set_attr "in_delay_slot" "no")])
7662
7663 ; 4 byte floating point
7664
7665 (define_insn "consttable_sf"
7666  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
7667                     (match_operand 1 "" "")]
7668                    UNSPECV_CONST4)]
7669  ""
7670  "*
7671 {
7672   if (operands[1] != const0_rtx)
7673     {
7674       REAL_VALUE_TYPE d;
7675       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
7676       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
7677     }
7678   return \"\";
7679 }"
7680  [(set_attr "length" "4")
7681   (set_attr "in_delay_slot" "no")])
7682
7683 ; 8 byte floating point
7684
7685 (define_insn "consttable_df"
7686  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
7687                     (match_operand 1 "" "")]
7688                    UNSPECV_CONST8)]
7689  ""
7690  "*
7691 {
7692   if (operands[1] != const0_rtx)
7693     {
7694       REAL_VALUE_TYPE d;
7695       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
7696       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
7697     }
7698   return \"\";
7699 }"
7700  [(set_attr "length" "8")
7701   (set_attr "in_delay_slot" "no")])
7702
7703 ;; Alignment is needed for some constant tables; it may also be added for
7704 ;; Instructions at the start of loops, or after unconditional branches.
7705 ;; ??? We would get more accurate lengths if we did instruction
7706 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
7707 ;; here is too conservative.
7708
7709 ; align to a two byte boundary
7710
7711 (define_expand "align_2"
7712  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
7713  ""
7714  "")
7715
7716 ; align to a four byte boundary
7717 ;; align_4 and align_log are instructions for the starts of loops, or
7718 ;; after unconditional branches, which may take up extra room.
7719
7720 (define_expand "align_4"
7721  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
7722  ""
7723  "")
7724
7725 ; align to a cache line boundary
7726
7727 (define_insn "align_log"
7728  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
7729  ""
7730  ""
7731  [(set_attr "length" "0")
7732   (set_attr "in_delay_slot" "no")])
7733
7734 ; emitted at the end of the literal table, used to emit the
7735 ; 32bit branch labels if needed.
7736
7737 (define_insn "consttable_end"
7738   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
7739   ""
7740   "* return output_jump_label_table ();"
7741   [(set_attr "in_delay_slot" "no")])
7742
7743 ; emitted at the end of the window in the literal table.
7744
7745 (define_insn "consttable_window_end"
7746   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
7747   ""
7748   ""
7749   [(set_attr "length" "0")
7750    (set_attr "in_delay_slot" "no")])
7751
7752 ;; -------------------------------------------------------------------------
7753 ;; Misc
7754 ;; -------------------------------------------------------------------------
7755
7756 ;; String/block move insn.
7757
7758 (define_expand "movstrsi"
7759   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
7760                    (mem:BLK (match_operand:BLK 1 "" "")))
7761               (use (match_operand:SI 2 "nonmemory_operand" ""))
7762               (use (match_operand:SI 3 "immediate_operand" ""))
7763               (clobber (reg:SI PR_REG))
7764               (clobber (reg:SI R4_REG))
7765               (clobber (reg:SI R5_REG))
7766               (clobber (reg:SI R0_REG))])]
7767   "TARGET_SH1 && ! TARGET_SH5"
7768   "
7769 {
7770   if(expand_block_move (operands))
7771      DONE;
7772   else FAIL;
7773 }")
7774
7775 (define_insn "block_move_real"
7776   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7777                    (mem:BLK (reg:SI R5_REG)))
7778               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7779               (clobber (reg:SI PR_REG))
7780               (clobber (reg:SI R0_REG))])]
7781   "TARGET_SH1 && ! TARGET_HARD_SH4"
7782   "jsr  @%0%#"
7783   [(set_attr "type" "sfunc")
7784    (set_attr "needs_delay_slot" "yes")])
7785
7786 (define_insn "block_lump_real"
7787   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7788                    (mem:BLK (reg:SI R5_REG)))
7789               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7790               (use (reg:SI R6_REG))
7791               (clobber (reg:SI PR_REG))
7792               (clobber (reg:SI T_REG))
7793               (clobber (reg:SI R4_REG))
7794               (clobber (reg:SI R5_REG))
7795               (clobber (reg:SI R6_REG))
7796               (clobber (reg:SI R0_REG))])]
7797   "TARGET_SH1 && ! TARGET_HARD_SH4"
7798   "jsr  @%0%#"
7799   [(set_attr "type" "sfunc")
7800    (set_attr "needs_delay_slot" "yes")])
7801
7802 (define_insn "block_move_real_i4"
7803   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7804                    (mem:BLK (reg:SI R5_REG)))
7805               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7806               (clobber (reg:SI PR_REG))
7807               (clobber (reg:SI R0_REG))
7808               (clobber (reg:SI R1_REG))
7809               (clobber (reg:SI R2_REG))])]
7810   "TARGET_HARD_SH4"
7811   "jsr  @%0%#"
7812   [(set_attr "type" "sfunc")
7813    (set_attr "needs_delay_slot" "yes")])
7814
7815 (define_insn "block_lump_real_i4"
7816   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7817                    (mem:BLK (reg:SI R5_REG)))
7818               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7819               (use (reg:SI R6_REG))
7820               (clobber (reg:SI PR_REG))
7821               (clobber (reg:SI T_REG))
7822               (clobber (reg:SI R4_REG))
7823               (clobber (reg:SI R5_REG))
7824               (clobber (reg:SI R6_REG))
7825               (clobber (reg:SI R0_REG))
7826               (clobber (reg:SI R1_REG))
7827               (clobber (reg:SI R2_REG))
7828               (clobber (reg:SI R3_REG))])]
7829   "TARGET_HARD_SH4"
7830   "jsr  @%0%#"
7831   [(set_attr "type" "sfunc")
7832    (set_attr "needs_delay_slot" "yes")])
7833 \f
7834 ;; -------------------------------------------------------------------------
7835 ;; Floating point instructions.
7836 ;; -------------------------------------------------------------------------
7837
7838 ;; ??? All patterns should have a type attribute.
7839
7840 (define_expand "fpu_switch0"
7841   [(set (match_operand:SI 0 "" "") (match_dup 2))
7842    (set (match_dup 1) (mem:PSI (match_dup 0)))]
7843   "TARGET_SH4"
7844   "
7845 {
7846   operands[1] = get_fpscr_rtx ();
7847   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
7848   if (flag_pic)
7849     operands[2] = legitimize_pic_address (operands[2], SImode,
7850                                           no_new_pseudos ? operands[0] : 0);
7851 }")
7852
7853 (define_expand "fpu_switch1"
7854   [(set (match_operand:SI 0 "" "") (match_dup 2))
7855    (set (match_dup 3) (plus:SI (match_dup 0) (const_int 4)))
7856    (set (match_dup 1) (mem:PSI (match_dup 3)))]
7857   "TARGET_SH4"
7858   "
7859 {
7860   operands[1] = get_fpscr_rtx ();
7861   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
7862   if (flag_pic)
7863     operands[2] = legitimize_pic_address (operands[2], SImode,
7864                                           no_new_pseudos ? operands[0] : 0);
7865   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
7866 }")
7867
7868 (define_expand "movpsi"
7869   [(set (match_operand:PSI 0 "register_operand" "")
7870         (match_operand:PSI 1 "general_movsrc_operand" ""))]
7871   "TARGET_SH4"
7872   "")
7873
7874 ;; The c / m alternative is a fake to guide reload to load directly into
7875 ;; fpscr, since reload doesn't know how to use post-increment.
7876 ;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
7877 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
7878 ;; predicate after reload.
7879 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
7880 ;; like a mac -> gpr move.
7881 (define_insn "fpu_switch"
7882   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
7883         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
7884   "TARGET_SH3E
7885    && (! reload_completed
7886        || true_regnum (operands[0]) != FPSCR_REG
7887        || GET_CODE (operands[1]) != MEM
7888        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
7889   "@
7890         ! precision stays the same
7891         lds.l   %1,fpscr
7892         mov.l   %1,%0
7893         #
7894         lds     %1,fpscr
7895         mov     %1,%0
7896         mov.l   %1,%0
7897         sts     fpscr,%0
7898         sts.l   fpscr,%0"
7899   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
7900    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,store")])
7901
7902 (define_split
7903   [(set (reg:PSI FPSCR_REG)
7904         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
7905   "TARGET_SH4 && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
7906   [(set (match_dup 0) (match_dup 0))]
7907   "
7908 {
7909   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
7910                                         gen_rtx (MEM, PSImode,
7911                                                  gen_rtx (POST_INC, Pmode,
7912                                                           operands[0]))));
7913   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[0], NULL_RTX);
7914 }")
7915
7916 (define_split
7917   [(set (reg:PSI FPSCR_REG)
7918         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
7919   "TARGET_SH4"
7920   [(set (match_dup 0) (plus:SI (match_dup 0) (const_int -4)))]
7921   "
7922 {
7923   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
7924                                         gen_rtx (MEM, PSImode,
7925                                                  gen_rtx (POST_INC, Pmode,
7926                                                           operands[0]))));
7927   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[0], NULL_RTX);
7928 }")
7929
7930 ;; ??? This uses the fp unit, but has no type indicating that.
7931 ;; If we did that, this would either give a bogus latency or introduce
7932 ;; a bogus FIFO constraint.
7933 ;; Since this insn is currently only used for prologues/epilogues,
7934 ;; it is probably best to claim no function unit, which matches the
7935 ;; current setting.
7936 (define_insn "toggle_sz"
7937   [(set (reg:PSI FPSCR_REG)
7938         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
7939   "TARGET_SH4"
7940   "fschg")
7941
7942 (define_expand "addsf3"
7943   [(set (match_operand:SF 0 "arith_reg_operand" "")
7944         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
7945                  (match_operand:SF 2 "arith_reg_operand" "")))]
7946   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7947   "
7948 {
7949   if (TARGET_SH3E)
7950     {
7951       expand_sf_binop (&gen_addsf3_i, operands);
7952       DONE;
7953     }
7954 }")
7955
7956 (define_insn "*addsf3_media"
7957   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7958         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
7959                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7960   "TARGET_SHMEDIA_FPU"
7961   "fadd.s       %1, %2, %0"
7962   [(set_attr "type" "fparith_media")])
7963
7964 (define_insn_and_split "unary_sf_op"
7965   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
7966         (vec_select:V2SF
7967          (vec_concat:V2SF
7968           (vec_select:SF
7969            (match_dup 0)
7970            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
7971           (match_operator:SF 2 "unary_float_operator"
7972             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
7973                             (parallel [(match_operand 4
7974                                         "const_int_operand" "n")]))]))
7975          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
7976   "TARGET_SHMEDIA_FPU"
7977   "#"
7978   "TARGET_SHMEDIA_FPU && reload_completed"
7979   [(set (match_dup 5) (match_dup 6))]
7980   "
7981 {
7982   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
7983   rtx op1 = gen_rtx_REG (SFmode,
7984                          (true_regnum (operands[1])
7985                           + (INTVAL (operands[4]) ^ endian)));
7986
7987   operands[7] = gen_rtx_REG (SFmode,
7988                              (true_regnum (operands[0])
7989                               + (INTVAL (operands[3]) ^ endian)));
7990   operands[6] = gen_rtx (GET_CODE (operands[2]), SFmode, op1);
7991 }"
7992   [(set_attr "type" "fparith_media")])
7993
7994 (define_insn_and_split "binary_sf_op"
7995   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
7996         (vec_select:V2SF
7997          (vec_concat:V2SF
7998           (vec_select:SF
7999            (match_dup 0)
8000            (parallel [(not:BI (match_operand 4 "const_int_operand" "n"))]))
8001           (match_operator:SF 3 "binary_float_operator"
8002             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
8003                             (parallel [(match_operand 5
8004                                         "const_int_operand" "n")]))
8005              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
8006                             (parallel [(match_operand 6
8007                                         "const_int_operand" "n")]))]))
8008          (parallel [(not:BI (match_dup 4)) (match_dup 4)])))]
8009   "TARGET_SHMEDIA_FPU"
8010   "#"
8011   "TARGET_SHMEDIA_FPU && reload_completed"
8012   [(set (match_dup 7) (match_dup 8))]
8013   "
8014 {
8015   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
8016   rtx op1 = gen_rtx_REG (SFmode,
8017                          (true_regnum (operands[1])
8018                           + (INTVAL (operands[5]) ^ endian)));
8019   rtx op2 = gen_rtx_REG (SFmode,
8020                          (true_regnum (operands[2])
8021                           + (INTVAL (operands[6]) ^ endian)));
8022
8023   operands[7] = gen_rtx_REG (SFmode,
8024                              (true_regnum (operands[0])
8025                               + (INTVAL (operands[4]) ^ endian)));
8026   operands[8] = gen_rtx (GET_CODE (operands[3]), SFmode, op1, op2);
8027 }"
8028   [(set_attr "type" "fparith_media")])
8029
8030 (define_insn "addsf3_i"
8031   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
8032         (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0")
8033                  (match_operand:SF 2 "arith_reg_operand" "f")))
8034    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8035   "TARGET_SH3E"
8036   "fadd %2,%0"
8037   [(set_attr "type" "fp")
8038    (set_attr "fp_mode" "single")])
8039
8040 (define_expand "subsf3"
8041   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8042         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
8043                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
8044   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8045   "
8046 {
8047   if (TARGET_SH3E)
8048     {
8049       expand_sf_binop (&gen_subsf3_i, operands);
8050       DONE;
8051     }
8052 }")
8053
8054 (define_insn "*subsf3_media"
8055   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8056         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
8057                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8058   "TARGET_SHMEDIA_FPU"
8059   "fsub.s       %1, %2, %0"
8060   [(set_attr "type" "fparith_media")])
8061
8062 (define_insn "subsf3_i"
8063   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8064         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
8065                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
8066    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8067   "TARGET_SH3E"
8068   "fsub %2,%0"
8069   [(set_attr "type" "fp")
8070    (set_attr "fp_mode" "single")])
8071
8072 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
8073 ;; register in feeding fp instructions.  Thus, we cannot generate fmac for
8074 ;; mixed-precision SH4 targets.  To allow it to be still generated for the
8075 ;; SH3E, we use a separate insn for SH3E mulsf3.
8076
8077 (define_expand "mulsf3"
8078   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8079         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
8080                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
8081   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8082   "
8083 {
8084   if (TARGET_SH4)
8085     expand_sf_binop (&gen_mulsf3_i4, operands);
8086   else if (TARGET_SH3E)
8087     emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2]));
8088   if (! TARGET_SHMEDIA)
8089     DONE;
8090 }")
8091
8092 (define_insn "*mulsf3_media"
8093   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8094         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8095                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8096   "TARGET_SHMEDIA_FPU"
8097   "fmul.s       %1, %2, %0"
8098   [(set_attr "type" "fparith_media")])
8099
8100 (define_insn "mulsf3_i4"
8101   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8102         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
8103                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
8104    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8105   "TARGET_SH3E"
8106   "fmul %2,%0"
8107   [(set_attr "type" "fp")
8108    (set_attr "fp_mode" "single")])
8109
8110 (define_insn "mulsf3_ie"
8111   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8112         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
8113                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8114   "TARGET_SH3E && ! TARGET_SH4"
8115   "fmul %2,%0"
8116   [(set_attr "type" "fp")])
8117
8118 (define_insn "*mac_media"
8119   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8120         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8121                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
8122                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
8123   "TARGET_SHMEDIA_FPU"
8124   "fmac.s %1, %2, %0"
8125   [(set_attr "type" "fparith_media")])
8126
8127 (define_insn "*macsf3"
8128   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8129         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
8130                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
8131                  (match_operand:SF 3 "arith_reg_operand" "0")))
8132    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
8133   "TARGET_SH3E && ! TARGET_SH4"
8134   "fmac fr0,%2,%0"
8135   [(set_attr "type" "fp")
8136    (set_attr "fp_mode" "single")])
8137
8138 (define_expand "divsf3"
8139   [(set (match_operand:SF 0 "arith_reg_operand" "")
8140         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
8141                 (match_operand:SF 2 "arith_reg_operand" "")))]
8142   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8143   "
8144 {
8145   if (TARGET_SH3E)
8146     {
8147       expand_sf_binop (&gen_divsf3_i, operands);
8148       DONE;
8149     }
8150 }")
8151
8152 (define_insn "*divsf3_media"
8153   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8154         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
8155                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8156   "TARGET_SHMEDIA_FPU"
8157   "fdiv.s       %1, %2, %0"
8158   [(set_attr "type" "fdiv_media")])
8159
8160 (define_insn "divsf3_i"
8161   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
8162         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
8163                  (match_operand:SF 2 "arith_reg_operand" "f")))
8164    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8165   "TARGET_SH3E"
8166   "fdiv %2,%0"
8167   [(set_attr "type" "fdiv")
8168    (set_attr "fp_mode" "single")])
8169
8170 (define_insn "floatdisf2"
8171   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8172         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
8173   "TARGET_SHMEDIA_FPU"
8174   "float.qs %1, %0"
8175   [(set_attr "type" "fpconv_media")])
8176
8177 (define_expand "floatsisf2"
8178   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8179         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
8180   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8181   "
8182 {
8183   if (TARGET_SH4)
8184     {
8185       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8186       DONE;
8187     }
8188 }")
8189
8190 (define_insn "*floatsisf2_media"
8191   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8192         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
8193   "TARGET_SHMEDIA_FPU"
8194   "float.ls     %1, %0"
8195   [(set_attr "type" "fpconv_media")])
8196
8197 (define_insn "floatsisf2_i4"
8198   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8199         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
8200    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8201   "TARGET_SH4"
8202   "float        %1,%0"
8203   [(set_attr "type" "fp")
8204    (set_attr "fp_mode" "single")])
8205
8206 (define_insn "*floatsisf2_ie"
8207   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8208         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
8209   "TARGET_SH3E && ! TARGET_SH4"
8210   "float        %1,%0"
8211   [(set_attr "type" "fp")])
8212
8213 (define_insn "fix_truncsfdi2"
8214   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
8215         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8216   "TARGET_SHMEDIA_FPU"
8217   "ftrc.sq %1, %0"
8218   [(set_attr "type" "fpconv_media")])
8219
8220 (define_expand "fix_truncsfsi2"
8221   [(set (match_operand:SI 0 "fpul_operand" "=y")
8222         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8223   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8224   "
8225 {
8226   if (TARGET_SH4)
8227     {
8228       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8229       DONE;
8230     }
8231 }")
8232
8233 (define_insn "*fix_truncsfsi2_media"
8234   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
8235         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8236   "TARGET_SHMEDIA_FPU"
8237   "ftrc.sl      %1, %0"
8238   [(set_attr "type" "fpconv_media")])
8239
8240 (define_insn "fix_truncsfsi2_i4"
8241   [(set (match_operand:SI 0 "fpul_operand" "=y")
8242         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8243    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8244   "TARGET_SH4"
8245   "ftrc %1,%0"
8246   [(set_attr "type" "ftrc_s")
8247    (set_attr "fp_mode" "single")])
8248
8249 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
8250 ;; fix_truncsfsi2_i4.
8251 ;; (define_insn "fix_truncsfsi2_i4_2"
8252 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8253 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
8254 ;;   (use (reg:PSI FPSCR_REG))
8255 ;;   (clobber (reg:SI FPUL_REG))]
8256 ;;  "TARGET_SH4"
8257 ;;  "#"
8258 ;;  [(set_attr "length" "4")
8259 ;;   (set_attr "fp_mode" "single")])
8260
8261 ;;(define_split
8262 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8263 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
8264 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
8265 ;;   (clobber (reg:SI FPUL_REG))]
8266 ;;  "TARGET_SH4"
8267 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
8268 ;;            (use (match_dup 2))])
8269 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
8270
8271 (define_insn "*fixsfsi"
8272   [(set (match_operand:SI 0 "fpul_operand" "=y")
8273         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8274   "TARGET_SH3E && ! TARGET_SH4"
8275   "ftrc %1,%0"
8276   [(set_attr "type" "fp")])
8277
8278 (define_insn "cmpgtsf_t"
8279   [(set (reg:SI T_REG)
8280         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8281                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8282   "TARGET_SH3E && ! TARGET_SH4"
8283   "fcmp/gt      %1,%0"
8284   [(set_attr "type" "fp")
8285    (set_attr "fp_mode" "single")])
8286
8287 (define_insn "cmpeqsf_t"
8288   [(set (reg:SI T_REG)
8289         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8290                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8291   "TARGET_SH3E && ! TARGET_SH4"
8292   "fcmp/eq      %1,%0"
8293   [(set_attr "type" "fp")
8294    (set_attr "fp_mode" "single")])
8295
8296 (define_insn "ieee_ccmpeqsf_t"
8297   [(set (reg:SI T_REG)
8298         (ior:SI (reg:SI T_REG)
8299                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8300                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
8301   "TARGET_SH3E && TARGET_IEEE && ! TARGET_SH4"
8302   "* return output_ieee_ccmpeq (insn, operands);"
8303   [(set_attr "length" "4")])
8304
8305
8306 (define_insn "cmpgtsf_t_i4"
8307   [(set (reg:SI T_REG)
8308         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8309                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8310    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8311   "TARGET_SH4"
8312   "fcmp/gt      %1,%0"
8313   [(set_attr "type" "fp")
8314    (set_attr "fp_mode" "single")])
8315
8316 (define_insn "cmpeqsf_t_i4"
8317   [(set (reg:SI T_REG)
8318         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8319                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8320    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8321   "TARGET_SH4"
8322   "fcmp/eq      %1,%0"
8323   [(set_attr "type" "fp")
8324    (set_attr "fp_mode" "single")])
8325
8326 (define_insn "*ieee_ccmpeqsf_t_4"
8327   [(set (reg:SI T_REG)
8328         (ior:SI (reg:SI T_REG)
8329                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8330                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
8331    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8332   "TARGET_IEEE && TARGET_SH4"
8333   "* return output_ieee_ccmpeq (insn, operands);"
8334   [(set_attr "length" "4")
8335    (set_attr "fp_mode" "single")])
8336
8337 (define_insn "cmpeqsf_media"
8338   [(set (match_operand:DI 0 "register_operand" "=r")
8339         (eq:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8340                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8341   "TARGET_SHMEDIA_FPU"
8342   "fcmpeq.s     %1, %2, %0"
8343   [(set_attr "type" "fcmp_media")])
8344
8345 (define_insn "cmpgtsf_media"
8346   [(set (match_operand:DI 0 "register_operand" "=r")
8347         (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8348                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8349   "TARGET_SHMEDIA_FPU"
8350   "fcmpgt.s     %1, %2, %0"
8351   [(set_attr "type" "fcmp_media")])
8352
8353 (define_insn "cmpgesf_media"
8354   [(set (match_operand:DI 0 "register_operand" "=r")
8355         (ge:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8356                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8357   "TARGET_SHMEDIA_FPU"
8358   "fcmpge.s     %1, %2, %0"
8359   [(set_attr "type" "fcmp_media")])
8360
8361 (define_insn "cmpunsf_media"
8362   [(set (match_operand:DI 0 "register_operand" "=r")
8363         (unordered:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8364                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8365   "TARGET_SHMEDIA_FPU"
8366   "fcmpun.s     %1, %2, %0"
8367   [(set_attr "type" "fcmp_media")])
8368
8369 (define_expand "cmpsf"
8370   [(set (reg:SI T_REG)
8371         (compare (match_operand:SF 0 "arith_operand" "")
8372                  (match_operand:SF 1 "arith_operand" "")))]
8373   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8374   "
8375 {
8376   sh_compare_op0 = operands[0];
8377   sh_compare_op1 = operands[1];
8378   DONE;
8379 }")
8380
8381 (define_expand "negsf2"
8382   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8383         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8384   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8385   "
8386 {
8387   if (TARGET_SH3E)
8388     {
8389       expand_sf_unop (&gen_negsf2_i, operands);
8390       DONE;
8391     }
8392 }")
8393
8394 (define_insn "*negsf2_media"
8395   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8396         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8397   "TARGET_SHMEDIA_FPU"
8398   "fneg.s       %1, %0"
8399   [(set_attr "type" "fmove_media")])
8400
8401 (define_insn "negsf2_i"
8402   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8403         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8404    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8405   "TARGET_SH3E"
8406   "fneg %0"
8407   [(set_attr "type" "fmove")
8408    (set_attr "fp_mode" "single")])
8409
8410 (define_expand "sqrtsf2"
8411   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8412         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8413   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8414   "
8415 {
8416   if (TARGET_SH3E)
8417     {
8418       expand_sf_unop (&gen_sqrtsf2_i, operands);
8419       DONE;
8420     }
8421 }")
8422
8423 (define_insn "*sqrtsf2_media"
8424   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8425         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8426   "TARGET_SHMEDIA_FPU"
8427   "fsqrt.s      %1, %0"
8428   [(set_attr "type" "fdiv_media")])
8429
8430 (define_insn "sqrtsf2_i"
8431   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8432         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8433    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8434   "TARGET_SH3E"
8435   "fsqrt        %0"
8436   [(set_attr "type" "fdiv")
8437    (set_attr "fp_mode" "single")])
8438
8439 (define_expand "abssf2"
8440   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8441         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8442   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8443   "
8444 {
8445   if (TARGET_SH3E)
8446     {
8447       expand_sf_unop (&gen_abssf2_i, operands);
8448       DONE;
8449     }
8450 }")
8451
8452 (define_insn "*abssf2_media"
8453   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8454         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8455   "TARGET_SHMEDIA_FPU"
8456   "fabs.s       %1, %0"
8457   [(set_attr "type" "fmove_media")])
8458
8459 (define_insn "abssf2_i"
8460   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8461         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8462    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8463   "TARGET_SH3E"
8464   "fabs %0"
8465   [(set_attr "type" "fmove")
8466    (set_attr "fp_mode" "single")])
8467
8468 (define_expand "adddf3"
8469   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8470         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8471                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8472   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8473   "
8474 {
8475   if (TARGET_SH4)
8476     {
8477       expand_df_binop (&gen_adddf3_i, operands);
8478       DONE;
8479     }
8480 }")
8481
8482 (define_insn "*adddf3_media"
8483   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8484         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
8485                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8486   "TARGET_SHMEDIA_FPU"
8487   "fadd.d       %1, %2, %0"
8488   [(set_attr "type" "dfparith_media")])
8489
8490 (define_insn "adddf3_i"
8491   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8492         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
8493                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8494    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8495   "TARGET_SH4"
8496   "fadd %2,%0"
8497   [(set_attr "type" "dfp_arith")
8498    (set_attr "fp_mode" "double")])
8499
8500 (define_expand "subdf3"
8501   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8502         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8503                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8504   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8505   "
8506 {
8507   if (TARGET_SH4)
8508     {
8509       expand_df_binop (&gen_subdf3_i, operands);
8510       DONE;
8511     }
8512 }")
8513
8514 (define_insn "*subdf3_media"
8515   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8516         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
8517                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8518   "TARGET_SHMEDIA_FPU"
8519   "fsub.d       %1, %2, %0"
8520   [(set_attr "type" "dfparith_media")])
8521
8522 (define_insn "subdf3_i"
8523   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8524         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
8525                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8526    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8527   "TARGET_SH4"
8528   "fsub %2,%0"
8529   [(set_attr "type" "dfp_arith")
8530    (set_attr "fp_mode" "double")])
8531
8532 (define_expand "muldf3"
8533   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8534         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8535                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8536   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8537   "
8538 {
8539   if (TARGET_SH4)
8540     {
8541       expand_df_binop (&gen_muldf3_i, operands);
8542       DONE;
8543     }
8544 }")
8545
8546 (define_insn "*muldf3_media"
8547   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8548         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
8549                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8550   "TARGET_SHMEDIA_FPU"
8551   "fmul.d       %1, %2, %0"
8552   [(set_attr "type" "dfmul_media")])
8553
8554 (define_insn "muldf3_i"
8555   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8556         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
8557                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8558    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8559   "TARGET_SH4"
8560   "fmul %2,%0"
8561   [(set_attr "type" "dfp_arith")
8562    (set_attr "fp_mode" "double")])
8563
8564 (define_expand "divdf3"
8565   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8566         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8567                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8568   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8569   "
8570 {
8571   if (TARGET_SH4)
8572     {
8573       expand_df_binop (&gen_divdf3_i, operands);
8574       DONE;
8575     }
8576 }")
8577
8578 (define_insn "*divdf3_media"
8579   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8580         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
8581                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8582   "TARGET_SHMEDIA_FPU"
8583   "fdiv.d       %1, %2, %0"
8584   [(set_attr "type" "dfdiv_media")])
8585
8586 (define_insn "divdf3_i"
8587   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8588         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
8589                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8590    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8591   "TARGET_SH4"
8592   "fdiv %2,%0"
8593   [(set_attr "type" "dfdiv")
8594    (set_attr "fp_mode" "double")])
8595
8596 (define_insn "floatdidf2"
8597   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8598         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
8599   "TARGET_SHMEDIA_FPU"
8600   "float.qd     %1, %0"
8601   [(set_attr "type" "dfpconv_media")])
8602
8603 (define_expand "floatsidf2"
8604   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8605         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
8606   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8607   "
8608 {
8609   if (TARGET_SH4)
8610     {
8611       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
8612                                       get_fpscr_rtx ()));
8613       DONE;
8614     }
8615 }")
8616
8617 (define_insn "*floatsidf2_media"
8618   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8619         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
8620   "TARGET_SHMEDIA_FPU"
8621   "float.ld     %1, %0"
8622   [(set_attr "type" "dfpconv_media")])
8623
8624 (define_insn "floatsidf2_i"
8625   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8626         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
8627    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8628   "TARGET_SH4"
8629   "float        %1,%0"
8630   [(set_attr "type" "dfp_conv")
8631    (set_attr "fp_mode" "double")])
8632
8633 (define_insn "fix_truncdfdi2"
8634   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
8635         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8636   "TARGET_SHMEDIA_FPU"
8637   "ftrc.dq      %1, %0"
8638   [(set_attr "type" "dfpconv_media")])
8639
8640 (define_expand "fix_truncdfsi2"
8641   [(set (match_operand:SI 0 "fpul_operand" "")
8642         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
8643   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8644   "
8645 {
8646   if (TARGET_SH4)
8647     {
8648       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
8649                                           get_fpscr_rtx ()));
8650       DONE;
8651     }
8652 }")
8653
8654 (define_insn "*fix_truncdfsi2_media"
8655   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
8656         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8657   "TARGET_SHMEDIA_FPU"
8658   "ftrc.dl      %1, %0"
8659   [(set_attr "type" "dfpconv_media")])
8660
8661 (define_insn "fix_truncdfsi2_i"
8662   [(set (match_operand:SI 0 "fpul_operand" "=y")
8663         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
8664    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8665   "TARGET_SH4"
8666   "ftrc %1,%0"
8667   [(set_attr "type" "dfp_conv")
8668    (set_attr "dfp_comp" "no")
8669    (set_attr "fp_mode" "double")])
8670
8671 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
8672 ;; fix_truncdfsi2_i.
8673 ;; (define_insn "fix_truncdfsi2_i4"
8674 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8675 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
8676 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
8677 ;;    (clobber (reg:SI FPUL_REG))]
8678 ;;   "TARGET_SH4"
8679 ;;   "#"
8680 ;;   [(set_attr "length" "4")
8681 ;;    (set_attr "fp_mode" "double")])
8682 ;;
8683 ;; (define_split
8684 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8685 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
8686 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
8687 ;;    (clobber (reg:SI FPUL_REG))]
8688 ;;   "TARGET_SH4"
8689 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
8690 ;;            (use (match_dup 2))])
8691 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
8692
8693 (define_insn "cmpgtdf_t"
8694   [(set (reg:SI T_REG)
8695         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
8696                (match_operand:DF 1 "arith_reg_operand" "f")))
8697    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8698   "TARGET_SH4"
8699   "fcmp/gt      %1,%0"
8700   [(set_attr "type" "dfp_cmp")
8701    (set_attr "fp_mode" "double")])
8702
8703 (define_insn "cmpeqdf_t"
8704   [(set (reg:SI T_REG)
8705         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
8706                (match_operand:DF 1 "arith_reg_operand" "f")))
8707    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8708   "TARGET_SH4"
8709   "fcmp/eq      %1,%0"
8710   [(set_attr "type" "dfp_cmp")
8711    (set_attr "fp_mode" "double")])
8712
8713 (define_insn "*ieee_ccmpeqdf_t"
8714   [(set (reg:SI T_REG)
8715         (ior:SI (reg:SI T_REG)
8716                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
8717                        (match_operand:DF 1 "arith_reg_operand" "f"))))
8718    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8719   "TARGET_IEEE && TARGET_SH4"
8720   "* return output_ieee_ccmpeq (insn, operands);"
8721   [(set_attr "length" "4")
8722    (set_attr "fp_mode" "double")])
8723
8724 (define_insn "cmpeqdf_media"
8725   [(set (match_operand:DI 0 "register_operand" "=r")
8726         (eq:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8727                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8728   "TARGET_SHMEDIA_FPU"
8729   "fcmpeq.d     %1,%2,%0"
8730   [(set_attr "type" "fcmp_media")])
8731
8732 (define_insn "cmpgtdf_media"
8733   [(set (match_operand:DI 0 "register_operand" "=r")
8734         (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8735                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8736   "TARGET_SHMEDIA_FPU"
8737   "fcmpgt.d     %1,%2,%0"
8738   [(set_attr "type" "fcmp_media")])
8739
8740 (define_insn "cmpgedf_media"
8741   [(set (match_operand:DI 0 "register_operand" "=r")
8742         (ge:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8743                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8744   "TARGET_SHMEDIA_FPU"
8745   "fcmpge.d     %1,%2,%0"
8746   [(set_attr "type" "fcmp_media")])
8747
8748 (define_insn "cmpundf_media"
8749   [(set (match_operand:DI 0 "register_operand" "=r")
8750         (unordered:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8751                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8752   "TARGET_SHMEDIA_FPU"
8753   "fcmpun.d     %1,%2,%0"
8754   [(set_attr "type" "fcmp_media")])
8755
8756 (define_expand "cmpdf"
8757   [(set (reg:SI T_REG)
8758         (compare (match_operand:DF 0 "arith_operand" "")
8759                  (match_operand:DF 1 "arith_operand" "")))]
8760   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8761   "
8762 {
8763   sh_compare_op0 = operands[0];
8764   sh_compare_op1 = operands[1];
8765   DONE;
8766 }")
8767
8768 (define_expand "negdf2"
8769   [(set (match_operand:DF 0 "arith_reg_operand" "")
8770         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
8771   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8772   "
8773 {
8774   if (TARGET_SH4)
8775     {
8776       expand_df_unop (&gen_negdf2_i, operands);
8777       DONE;
8778     }
8779 }")
8780
8781 (define_insn "*negdf2_media"
8782   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8783         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8784   "TARGET_SHMEDIA_FPU"
8785   "fneg.d       %1, %0"
8786   [(set_attr "type" "fmove_media")])
8787
8788 (define_insn "negdf2_i"
8789   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
8790         (neg:DF (match_operand:DF 1 "arith_reg_operand" "0")))
8791    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8792   "TARGET_SH4"
8793   "fneg %0"
8794   [(set_attr "type" "fmove")
8795    (set_attr "fp_mode" "double")])
8796
8797 (define_expand "sqrtdf2"
8798   [(set (match_operand:DF 0 "arith_reg_operand" "")
8799         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
8800   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8801   "
8802 {
8803   if (TARGET_SH4)
8804     {
8805       expand_df_unop (&gen_sqrtdf2_i, operands);
8806       DONE;
8807     }
8808 }")
8809
8810 (define_insn "*sqrtdf2_media"
8811   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8812         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8813   "TARGET_SHMEDIA_FPU"
8814   "fsqrt.d      %1, %0"
8815   [(set_attr "type" "dfdiv_media")])
8816
8817 (define_insn "sqrtdf2_i"
8818   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
8819         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "0")))
8820    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8821   "TARGET_SH4"
8822   "fsqrt        %0"
8823   [(set_attr "type" "dfdiv")
8824    (set_attr "fp_mode" "double")])
8825
8826 (define_expand "absdf2"
8827   [(set (match_operand:DF 0 "arith_reg_operand" "")
8828         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
8829   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8830   "
8831 {
8832   if (TARGET_SH4)
8833     {
8834       expand_df_unop (&gen_absdf2_i, operands);
8835       DONE;
8836     }
8837 }")
8838
8839 (define_insn "*absdf2_media"
8840   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8841         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8842   "TARGET_SHMEDIA_FPU"
8843   "fabs.d       %1, %0"
8844   [(set_attr "type" "fmove_media")])
8845
8846 (define_insn "absdf2_i"
8847   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
8848         (abs:DF (match_operand:DF 1 "arith_reg_operand" "0")))
8849    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8850   "TARGET_SH4"
8851   "fabs %0"
8852   [(set_attr "type" "fmove")
8853    (set_attr "fp_mode" "double")])
8854
8855 (define_expand "extendsfdf2"
8856   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8857         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
8858   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8859   "
8860 {
8861   if (TARGET_SH4)
8862     {
8863       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
8864                                         get_fpscr_rtx ()));
8865       DONE;
8866     }
8867 }")
8868
8869 (define_insn "*extendsfdf2_media"
8870   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8871         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8872   "TARGET_SHMEDIA_FPU"
8873   "fcnv.sd      %1, %0"
8874   [(set_attr "type" "dfpconv_media")])
8875
8876 (define_insn "extendsfdf2_i4"
8877   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8878         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
8879    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8880   "TARGET_SH4"
8881   "fcnvsd  %1,%0"
8882   [(set_attr "type" "fp")
8883    (set_attr "fp_mode" "double")])
8884
8885 (define_expand "truncdfsf2"
8886   [(set (match_operand:SF 0 "fpul_operand" "")
8887         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
8888   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8889   "
8890 {
8891   if (TARGET_SH4)
8892     {
8893       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
8894                                        get_fpscr_rtx ()));
8895       DONE;
8896     }
8897 }")
8898
8899 (define_insn "*truncdfsf2_media"
8900   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8901         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8902   "TARGET_SHMEDIA_FPU"
8903   "fcnv.ds      %1, %0"
8904   [(set_attr "type" "dfpconv_media")])
8905
8906 (define_insn "truncdfsf2_i4"
8907   [(set (match_operand:SF 0 "fpul_operand" "=y")
8908         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
8909    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8910   "TARGET_SH4"
8911   "fcnvds  %1,%0"
8912   [(set_attr "type" "fp")
8913    (set_attr "fp_mode" "double")])
8914 \f
8915 ;; Bit field extract patterns.  These give better code for packed bitfields,
8916 ;; because they allow auto-increment addresses to be generated.
8917
8918 (define_expand "insv"
8919   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
8920                          (match_operand:SI 1 "immediate_operand" "")
8921                          (match_operand:SI 2 "immediate_operand" ""))
8922         (match_operand:SI 3 "general_operand" ""))]
8923   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
8924   "
8925 {
8926   rtx addr_target, orig_address, shift_reg, qi_val;
8927   HOST_WIDE_INT bitsize, size, v;
8928   rtx x = operands[3];
8929
8930   /* ??? expmed doesn't care for non-register predicates.  */
8931   if (! memory_operand (operands[0], VOIDmode)
8932       || ! immediate_operand (operands[1], VOIDmode)
8933       || ! immediate_operand (operands[2], VOIDmode)
8934       || ! general_operand (x, VOIDmode))
8935     FAIL;
8936   /* If this isn't a 16 / 24 / 32 bit field, or if
8937      it doesn't start on a byte boundary, then fail.  */
8938   bitsize = INTVAL (operands[1]);
8939   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
8940       || (INTVAL (operands[2]) % 8) != 0)
8941     FAIL;
8942
8943   size = bitsize / 8;
8944   orig_address = XEXP (operands[0], 0);
8945   shift_reg = gen_reg_rtx (SImode);
8946   if (GET_CODE (x) == CONST_INT)
8947     {
8948       v = INTVAL (x);
8949       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
8950     }
8951   else
8952     {
8953       emit_insn (gen_movsi (shift_reg, operands[3]));
8954       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
8955     }
8956   addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
8957
8958   operands[0] = replace_equiv_address (operands[0], addr_target);
8959   emit_insn (gen_movqi (operands[0], qi_val));
8960
8961   while (size -= 1)
8962     {
8963       if (GET_CODE (x) == CONST_INT)
8964         qi_val
8965           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
8966       else
8967         {
8968           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
8969           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
8970         }
8971       emit_insn (gen_addsi3 (addr_target, addr_target, GEN_INT (-1)));
8972       emit_insn (gen_movqi (operands[0], qi_val));
8973     }
8974
8975   DONE;
8976 }")
8977 \f
8978 ;; -------------------------------------------------------------------------
8979 ;; Peepholes
8980 ;; -------------------------------------------------------------------------
8981
8982 ;; This matches cases where a stack pointer increment at the start of the
8983 ;; epilogue combines with a stack slot read loading the return value.
8984
8985 (define_peephole
8986   [(set (match_operand:SI 0 "arith_reg_operand" "")
8987         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
8988    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
8989   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
8990   "mov.l        @%1+,%0")
8991
8992 ;; See the comment on the dt combiner pattern above.
8993
8994 (define_peephole
8995   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8996         (plus:SI (match_dup 0)
8997                  (const_int -1)))
8998    (set (reg:SI T_REG)
8999         (eq:SI (match_dup 0)
9000                (const_int 0)))]
9001   "TARGET_SH2"
9002   "dt   %0")
9003
9004 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
9005 ;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
9006 ;; reload when the constant is too large for a reg+offset address.
9007
9008 ;; ??? We would get much better code if this was done in reload.  This would
9009 ;; require modifying find_reloads_address to recognize that if the constant
9010 ;; is out-of-range for an immediate add, then we get better code by reloading
9011 ;; the constant into a register than by reloading the sum into a register,
9012 ;; since the former is one instruction shorter if the address does not need
9013 ;; to be offsettable.  Unfortunately this does not work, because there is
9014 ;; only one register, r0, that can be used as an index register.  This register
9015 ;; is also the function return value register.  So, if we try to force reload
9016 ;; to use double-reg addresses, then we end up with some instructions that
9017 ;; need to use r0 twice.  The only way to fix this is to change the calling
9018 ;; convention so that r0 is not used to return values.
9019
9020 (define_peephole
9021   [(set (match_operand:SI 0 "register_operand" "=r")
9022         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9023    (set (mem:SI (match_dup 0))
9024         (match_operand:SI 2 "general_movsrc_operand" ""))]
9025   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9026   "mov.l        %2,@(%0,%1)")
9027
9028 (define_peephole
9029   [(set (match_operand:SI 0 "register_operand" "=r")
9030         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9031    (set (match_operand:SI 2 "general_movdst_operand" "")
9032         (mem:SI (match_dup 0)))]
9033   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9034   "mov.l        @(%0,%1),%2")
9035
9036 (define_peephole
9037   [(set (match_operand:SI 0 "register_operand" "=r")
9038         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9039    (set (mem:HI (match_dup 0))
9040         (match_operand:HI 2 "general_movsrc_operand" ""))]
9041   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9042   "mov.w        %2,@(%0,%1)")
9043
9044 (define_peephole
9045   [(set (match_operand:SI 0 "register_operand" "=r")
9046         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9047    (set (match_operand:HI 2 "general_movdst_operand" "")
9048         (mem:HI (match_dup 0)))]
9049   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9050   "mov.w        @(%0,%1),%2")
9051
9052 (define_peephole
9053   [(set (match_operand:SI 0 "register_operand" "=r")
9054         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9055    (set (mem:QI (match_dup 0))
9056         (match_operand:QI 2 "general_movsrc_operand" ""))]
9057   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9058   "mov.b        %2,@(%0,%1)")
9059
9060 (define_peephole
9061   [(set (match_operand:SI 0 "register_operand" "=r")
9062         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9063    (set (match_operand:QI 2 "general_movdst_operand" "")
9064         (mem:QI (match_dup 0)))]
9065   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9066   "mov.b        @(%0,%1),%2")
9067
9068 (define_peephole
9069   [(set (match_operand:SI 0 "register_operand" "=r")
9070         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9071    (set (mem:SF (match_dup 0))
9072         (match_operand:SF 2 "general_movsrc_operand" ""))]
9073   "TARGET_SH1 && REGNO (operands[0]) == 0
9074    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
9075        || (GET_CODE (operands[2]) == SUBREG
9076            && REGNO (SUBREG_REG (operands[2])) < 16))
9077    && reg_unused_after (operands[0], insn)"
9078   "mov.l        %2,@(%0,%1)")
9079
9080 (define_peephole
9081   [(set (match_operand:SI 0 "register_operand" "=r")
9082         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9083    (set (match_operand:SF 2 "general_movdst_operand" "")
9084
9085         (mem:SF (match_dup 0)))]
9086   "TARGET_SH1 && REGNO (operands[0]) == 0
9087    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
9088        || (GET_CODE (operands[2]) == SUBREG
9089            && REGNO (SUBREG_REG (operands[2])) < 16))
9090    && reg_unused_after (operands[0], insn)"
9091   "mov.l        @(%0,%1),%2")
9092
9093 (define_peephole
9094   [(set (match_operand:SI 0 "register_operand" "=r")
9095         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9096    (set (mem:SF (match_dup 0))
9097         (match_operand:SF 2 "general_movsrc_operand" ""))]
9098   "TARGET_SH3E && REGNO (operands[0]) == 0
9099    && ((GET_CODE (operands[2]) == REG
9100         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
9101        || (GET_CODE (operands[2]) == SUBREG
9102            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
9103    && reg_unused_after (operands[0], insn)"
9104   "fmov{.s|}    %2,@(%0,%1)")
9105
9106 (define_peephole
9107   [(set (match_operand:SI 0 "register_operand" "=r")
9108         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9109    (set (match_operand:SF 2 "general_movdst_operand" "")
9110
9111         (mem:SF (match_dup 0)))]
9112   "TARGET_SH3E && REGNO (operands[0]) == 0
9113    && ((GET_CODE (operands[2]) == REG
9114         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
9115        || (GET_CODE (operands[2]) == SUBREG
9116            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
9117    && reg_unused_after (operands[0], insn)"
9118   "fmov{.s|}    @(%0,%1),%2")
9119
9120 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
9121 (define_insn "sp_switch_1"
9122   [(const_int 1)]
9123   "TARGET_SH1"
9124   "*
9125 {
9126   rtx xoperands[1];
9127
9128   xoperands[0] = sp_switch;
9129   output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", xoperands);
9130   output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", xoperands);
9131   return \"mov r0,r15\";
9132 }"
9133   [(set_attr "length" "10")])
9134
9135 ;; Switch back to the original stack for interrupt functions with the
9136 ;; sp_switch attribute.  */
9137 (define_insn "sp_switch_2"
9138   [(const_int 2)]
9139   "TARGET_SH1"
9140   "mov.l @r15+,r15\;mov.l @r15+,r0"
9141   [(set_attr "length" "4")])
9142
9143 ;; Integer vector moves
9144
9145 (define_expand "movv8qi"
9146   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
9147         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
9148   "TARGET_SHMEDIA"
9149   "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
9150
9151 (define_insn "movv8qi_i"
9152   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
9153         (match_operand:V8QI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))]
9154   "TARGET_SHMEDIA
9155    && (register_operand (operands[0], V8QImode)
9156        || register_operand (operands[1], V8QImode))"
9157   "@
9158         add     %1, r63, %0
9159         movi    %1, %0
9160         #
9161         ld%M1.q %m1, %0
9162         st%M0.q %m0, %1"
9163   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9164    (set_attr "length" "4,4,16,4,4")])
9165
9166 (define_split
9167   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
9168         (subreg:V8QI (const_int 0) 0))]
9169   "TARGET_SHMEDIA"
9170   [(set (match_dup 0)
9171         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
9172                             (const_int 0) (const_int 0) (const_int 0)
9173                             (const_int 0) (const_int 0)]))])
9174
9175 (define_split
9176   [(set (match_operand 0 "arith_reg_dest" "")
9177         (match_operand 1 "sh_rep_vec" ""))]
9178   "TARGET_SHMEDIA && reload_completed
9179    && GET_MODE (operands[0]) == GET_MODE (operands[1])
9180    && VECTOR_MODE_SUPPORTED_P (GET_MODE (operands[0]))
9181    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
9182    && (XVECEXP (operands[1], 0, 0) != const0_rtx
9183        || XVECEXP (operands[1], 0, 1) != const0_rtx)
9184    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
9185        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
9186   [(set (match_dup 0) (match_dup 1))
9187    (match_dup 2)]
9188   "
9189 {
9190   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
9191   rtx elt1 = XVECEXP (operands[1], 0, 1);
9192
9193   if (unit_size > 2)
9194     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
9195   else
9196     {
9197       if (unit_size < 2)
9198         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
9199       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
9200     }
9201   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
9202   operands[1] = XVECEXP (operands[1], 0, 0);
9203   if (unit_size < 2)
9204     {
9205       if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (elt1) == CONST_INT)
9206         operands[1] = GEN_INT (TARGET_LITTLE_ENDIAN
9207                                ? INTVAL (operands[1]) + (INTVAL (elt1) << 8)
9208                                : (INTVAL (operands[1]) << 8) + INTVAL (elt1));
9209       else
9210         {
9211           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
9212           operands[1]
9213             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
9214         }
9215     }
9216 }")
9217
9218 (define_split
9219   [(set (match_operand 0 "arith_reg_dest" "")
9220         (match_operand 1 "sh_const_vec" ""))]
9221   "TARGET_SHMEDIA && reload_completed
9222    && GET_MODE (operands[0]) == GET_MODE (operands[1])
9223    && VECTOR_MODE_SUPPORTED_P (GET_MODE (operands[0]))
9224    && operands[1] != CONST0_RTX (GET_MODE (operands[1]))"
9225   [(set (match_dup 0) (match_dup 1))]
9226   "
9227 {
9228   rtx v = operands[1];
9229   enum machine_mode new_mode
9230     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
9231
9232   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
9233   operands[1]
9234     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
9235 }")
9236
9237 (define_expand "movv2hi"
9238   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
9239         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
9240   "TARGET_SHMEDIA"
9241   "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
9242
9243 (define_insn "movv2hi_i"
9244   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
9245         (match_operand:V2HI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))]
9246   "TARGET_SHMEDIA
9247    && (register_operand (operands[0], V2HImode)
9248        || register_operand (operands[1], V2HImode))"
9249   "@
9250         addz.l  %1, r63, %0
9251         movi    %1, %0
9252         #
9253         ld%M1.l %m1, %0
9254         st%M0.l %m0, %1"
9255   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9256    (set_attr "length" "4,4,16,4,4")])
9257
9258 (define_expand "movv4hi"
9259   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
9260         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
9261   "TARGET_SHMEDIA"
9262   "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
9263
9264 (define_insn "movv4hi_i"
9265   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
9266         (match_operand:V4HI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))]
9267   "TARGET_SHMEDIA
9268    && (register_operand (operands[0], V4HImode)
9269        || register_operand (operands[1], V4HImode))"
9270   "@
9271         add     %1, r63, %0
9272         movi    %1, %0
9273         #
9274         ld%M1.q %m1, %0
9275         st%M0.q %m0, %1"
9276   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9277    (set_attr "length" "4,4,16,4,4")])
9278
9279 (define_expand "movv2si"
9280   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
9281         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
9282   "TARGET_SHMEDIA"
9283   "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
9284
9285 (define_insn "movv2si_i"
9286   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
9287         (match_operand:V2SI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))]
9288   "TARGET_SHMEDIA
9289    && (register_operand (operands[0], V2SImode)
9290        || register_operand (operands[1], V2SImode))"
9291   "@
9292         add     %1, r63, %0
9293         #
9294         #
9295         ld%M1.q %m1, %0
9296         st%M0.q %m0, %1"
9297   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9298    (set_attr "length" "4,4,16,4,4")])
9299
9300 ;; Multimedia Intrinsics
9301
9302 (define_insn "absv2si2"
9303   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9304         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
9305   "TARGET_SHMEDIA"
9306   "mabs.l       %1, %0"
9307   [(set_attr "type" "mcmp_media")])
9308
9309 (define_insn "absv4hi2"
9310   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9311         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
9312   "TARGET_SHMEDIA"
9313   "mabs.w       %1, %0"
9314   [(set_attr "type" "mcmp_media")])
9315
9316 (define_insn "addv2si3"
9317   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9318         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
9319                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9320   "TARGET_SHMEDIA"
9321   "madd.l       %1, %2, %0"
9322   [(set_attr "type" "arith_media")])
9323
9324 (define_insn "addv4hi3"
9325   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9326         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
9327                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9328   "TARGET_SHMEDIA"
9329   "madd.w       %1, %2, %0"
9330   [(set_attr "type" "arith_media")])
9331
9332 (define_insn "ssaddv2si3"
9333   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9334         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
9335                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9336   "TARGET_SHMEDIA"
9337   "madds.l      %1, %2, %0"
9338   [(set_attr "type" "mcmp_media")])
9339
9340 (define_insn "usaddv8qi3"
9341   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9342         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
9343                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
9344   "TARGET_SHMEDIA"
9345   "madds.ub     %1, %2, %0"
9346   [(set_attr "type" "mcmp_media")])
9347
9348 (define_insn "ssaddv4hi3"
9349   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9350         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
9351                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9352   "TARGET_SHMEDIA"
9353   "madds.w      %1, %2, %0"
9354   [(set_attr "type" "mcmp_media")])
9355
9356 (define_insn "negcmpeqv8qi"
9357   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9358         (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rU")
9359                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))))]
9360   "TARGET_SHMEDIA"
9361   "mcmpeq.b     %N1, %N2, %0"
9362   [(set_attr "type" "mcmp_media")])
9363
9364 (define_insn "negcmpeqv2si"
9365   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9366         (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rU")
9367                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))))]
9368   "TARGET_SHMEDIA"
9369   "mcmpeq.l     %N1, %N2, %0"
9370   [(set_attr "type" "mcmp_media")])
9371
9372 (define_insn "negcmpeqv4hi"
9373   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9374         (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rU")
9375                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))]
9376   "TARGET_SHMEDIA"
9377   "mcmpeq.w     %N1, %N2, %0"
9378   [(set_attr "type" "mcmp_media")])
9379
9380 (define_insn "negcmpgtuv8qi"
9381   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9382         (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rU")
9383                             (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))))]
9384   "TARGET_SHMEDIA"
9385   "mcmpgt.ub    %N1, %N2, %0"
9386   [(set_attr "type" "mcmp_media")])
9387
9388 (define_insn "negcmpgtv2si"
9389   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9390         (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rU")
9391                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))))]
9392   "TARGET_SHMEDIA"
9393   "mcmpgt.l     %N1, %N2, %0"
9394   [(set_attr "type" "mcmp_media")])
9395
9396 (define_insn "negcmpgtv4hi"
9397   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9398         (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rU")
9399                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))]
9400   "TARGET_SHMEDIA"
9401   "mcmpgt.w     %N1, %N2, %0"
9402   [(set_attr "type" "mcmp_media")])
9403
9404 (define_insn "mcmv"
9405   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9406         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9407                         (match_operand:DI 2 "arith_reg_operand" "r"))
9408                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
9409                         (not:DI (match_dup 2)))))]
9410   "TARGET_SHMEDIA"
9411   "mcmv %N1, %2, %0"
9412   [(set_attr "type" "arith_media")])
9413
9414 (define_insn "mcnvs_lw"
9415   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9416         (vec_concat:V4HI
9417          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU"))
9418          (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))))]
9419   "TARGET_SHMEDIA"
9420   "mcnvs.lw     %N1, %N2, %0"
9421   [(set_attr "type" "mcmp_media")])
9422
9423 (define_insn "mcnvs_wb"
9424   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9425         (vec_concat:V8QI
9426          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU"))
9427          (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))]
9428   "TARGET_SHMEDIA"
9429   "mcnvs.wb     %N1, %N2, %0"
9430   [(set_attr "type" "mcmp_media")])
9431
9432 (define_insn "mcnvs_wub"
9433   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9434         (vec_concat:V8QI
9435          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU"))
9436          (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))]
9437   "TARGET_SHMEDIA"
9438   "mcnvs.wub    %N1, %N2, %0"
9439   [(set_attr "type" "mcmp_media")])
9440
9441 (define_insn "mextr_rl"
9442   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9443         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9444                              (match_operand:HI 3 "mextr_bit_offset" "i"))
9445                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
9446                           (match_operand:HI 4 "mextr_bit_offset" "i"))))]
9447   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
9448   "*
9449 {
9450   static char templ[16];
9451
9452   sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
9453            (int) INTVAL (operands[3]) >> 3);
9454   return templ;
9455 }"
9456   [(set_attr "type" "arith_media")])
9457
9458 (define_insn "*mextr_lr"
9459   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9460         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9461                            (match_operand:HI 3 "mextr_bit_offset" "i"))
9462                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
9463                             (match_operand:HI 4 "mextr_bit_offset" "i"))))]
9464   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
9465   "*
9466 {
9467   static char templ[16];
9468
9469   sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
9470            (int) INTVAL (operands[4]) >> 3);
9471   return templ;
9472 }"
9473   [(set_attr "type" "arith_media")])
9474
9475 ; mextrN can be modelled with vec_select / vec_concat, but the selection
9476 ; vector then varies depending on endianness.
9477 (define_expand "mextr1"
9478   [(match_operand:DI 0 "arith_reg_dest" "")
9479    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9480    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9481   "TARGET_SHMEDIA"
9482   "
9483 {
9484   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9485                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
9486   DONE;
9487 }")
9488
9489 (define_expand "mextr2"
9490   [(match_operand:DI 0 "arith_reg_dest" "")
9491    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9492    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9493   "TARGET_SHMEDIA"
9494   "
9495 {
9496   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9497                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
9498   DONE;
9499 }")
9500
9501 (define_expand "mextr3"
9502   [(match_operand:DI 0 "arith_reg_dest" "")
9503    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9504    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9505   "TARGET_SHMEDIA"
9506   "
9507 {
9508   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9509                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
9510   DONE;
9511 }")
9512
9513 (define_expand "mextr4"
9514   [(match_operand:DI 0 "arith_reg_dest" "")
9515    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9516    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9517   "TARGET_SHMEDIA"
9518   "
9519 {
9520   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9521                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
9522   DONE;
9523 }")
9524
9525 (define_expand "mextr5"
9526   [(match_operand:DI 0 "arith_reg_dest" "")
9527    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9528    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9529   "TARGET_SHMEDIA"
9530   "
9531 {
9532   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9533                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
9534   DONE;
9535 }")
9536
9537 (define_expand "mextr6"
9538   [(match_operand:DI 0 "arith_reg_dest" "")
9539    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9540    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9541   "TARGET_SHMEDIA"
9542   "
9543 {
9544   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9545                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
9546   DONE;
9547 }")
9548
9549 (define_expand "mextr7"
9550   [(match_operand:DI 0 "arith_reg_dest" "")
9551    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9552    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9553   "TARGET_SHMEDIA"
9554   "
9555 {
9556   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9557                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
9558   DONE;
9559 }")
9560
9561 (define_expand "mmacfx_wl"
9562   [(match_operand:V2SI 0 "arith_reg_dest" "")
9563    (match_operand:V2HI 1 "extend_reg_operand" "")
9564    (match_operand:V2HI 2 "extend_reg_operand" "")
9565    (match_operand:V2SI 3 "arith_reg_operand" "")]
9566   "TARGET_SHMEDIA"
9567   "
9568 {
9569   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
9570                               operands[1], operands[2]));
9571   DONE;
9572 }")
9573
9574 (define_insn "mmacfx_wl_i"
9575   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9576         (ss_plus:V2SI
9577          (match_operand:V2SI 1 "arith_reg_operand" "0")
9578          (ss_truncate:V2SI
9579           (ashift:V2DI
9580            (sign_extend:V2DI
9581             (mult:V2SI
9582              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
9583              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
9584            (const_int 1)))))]
9585   "TARGET_SHMEDIA"
9586   "mmacfx.wl    %2, %3, %0"
9587   [(set_attr "type" "mac_media")])
9588
9589 (define_expand "mmacnfx_wl"
9590   [(match_operand:V2SI 0 "arith_reg_dest" "")
9591    (match_operand:V2HI 1 "extend_reg_operand" "")
9592    (match_operand:V2HI 2 "extend_reg_operand" "")
9593    (match_operand:V2SI 3 "arith_reg_operand" "")]
9594   "TARGET_SHMEDIA"
9595   "
9596 {
9597   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
9598                                operands[1], operands[2]));
9599   DONE;
9600 }")
9601
9602 (define_insn "mmacnfx_wl_i"
9603   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9604         (ss_minus:V2SI
9605          (match_operand:V2SI 1 "arith_reg_operand" "0")
9606          (ss_truncate:V2SI
9607           (ashift:V2DI
9608            (sign_extend:V2DI
9609             (mult:V2SI
9610              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
9611              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
9612            (const_int 1)))))]
9613   "TARGET_SHMEDIA"
9614   "mmacnfx.wl   %2, %3, %0"
9615   [(set_attr "type" "mac_media")])
9616
9617 (define_insn "mulv2si3"
9618   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9619         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
9620                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9621   "TARGET_SHMEDIA"
9622   "mmul.l       %1, %2, %0"
9623   [(set_attr "type" "d2mpy_media")])
9624
9625 (define_insn "mulv4hi3"
9626   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9627         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
9628                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9629   "TARGET_SHMEDIA"
9630   "mmul.w       %1, %2, %0"
9631   [(set_attr "type" "dmpy_media")])
9632
9633 (define_insn "mmulfx_l"
9634   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9635         (ss_truncate:V2SI
9636          (ashiftrt:V2DI
9637           (mult:V2DI
9638            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
9639            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
9640           (const_int 31))))]
9641   "TARGET_SHMEDIA"
9642   "mmulfx.l     %1, %2, %0"
9643   [(set_attr "type" "d2mpy_media")])
9644
9645 (define_insn "mmulfx_w"
9646   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9647         (ss_truncate:V4HI
9648          (ashiftrt:V4SI
9649           (mult:V4SI
9650            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9651            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
9652           (const_int 15))))]
9653   "TARGET_SHMEDIA"
9654   "mmulfx.w     %1, %2, %0"
9655   [(set_attr "type" "dmpy_media")])
9656
9657 (define_insn "mmulfxrp_w"
9658   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9659         (ss_truncate:V4HI
9660          (ashiftrt:V4SI
9661           (plus:V4SI
9662            (mult:V4SI
9663             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9664             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
9665            (const_int 16384))
9666           (const_int 15))))]
9667   "TARGET_SHMEDIA"
9668   "mmulfxrp.w   %1, %2, %0"
9669   [(set_attr "type" "dmpy_media")])
9670
9671 (define_expand "mmulhi_wl"
9672   [(match_operand:V2SI 0 "arith_reg_dest" "")
9673    (match_operand:V4HI 1 "arith_reg_operand" "")
9674    (match_operand:V4HI 2 "arith_reg_operand" "")]
9675   "TARGET_SHMEDIA"
9676   "
9677 {
9678   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
9679              (operands[0], operands[1], operands[2]));
9680   DONE;
9681 }")
9682
9683 (define_expand "mmullo_wl"
9684   [(match_operand:V2SI 0 "arith_reg_dest" "")
9685    (match_operand:V4HI 1 "arith_reg_operand" "")
9686    (match_operand:V4HI 2 "arith_reg_operand" "")]
9687   "TARGET_SHMEDIA"
9688   "
9689 {
9690   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
9691              (operands[0], operands[1], operands[2]));
9692   DONE;
9693 }")
9694
9695 (define_insn "mmul23_wl"
9696   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9697         (vec_select:V2SI
9698          (mult:V4SI
9699           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9700           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
9701          (parallel [(const_int 2) (const_int 3)])))]
9702   "TARGET_SHMEDIA"
9703   "* return (TARGET_LITTLE_ENDIAN
9704              ? \"mmulhi.wl      %1, %2, %0\"
9705              : \"mmullo.wl      %1, %2, %0\");"
9706   [(set_attr "type" "dmpy_media")])
9707
9708 (define_insn "mmul01_wl"
9709   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9710         (vec_select:V2SI
9711          (mult:V4SI
9712           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9713           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
9714          (parallel [(const_int 0) (const_int 1)])))]
9715   "TARGET_SHMEDIA"
9716   "* return (TARGET_LITTLE_ENDIAN
9717              ? \"mmullo.wl      %1, %2, %0\"
9718              : \"mmulhi.wl      %1, %2, %0\");"
9719   [(set_attr "type" "dmpy_media")])
9720
9721 (define_expand "mmulsum_wq"
9722   [(match_operand:DI 0 "arith_reg_dest" "")
9723    (match_operand:V4HI 1 "arith_reg_operand" "")
9724    (match_operand:V4HI 2 "arith_reg_operand" "")
9725    (match_operand:DI 3 "arith_reg_operand" "")]
9726   "TARGET_SHMEDIA"
9727   "
9728 {
9729   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
9730                                operands[1], operands[2]));
9731   DONE;
9732 }")
9733
9734 (define_insn "mmulsum_wq_i"
9735   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9736         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
9737          (plus:DI
9738           (plus:DI
9739            (vec_select:DI
9740             (mult:V4DI
9741              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
9742              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
9743             (parallel [(const_int 0)]))
9744            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
9745                                      (sign_extend:V4DI (match_dup 3)))
9746                           (parallel [(const_int 1)])))
9747           (plus:DI
9748            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
9749                                      (sign_extend:V4DI (match_dup 3)))
9750                           (parallel [(const_int 2)]))
9751            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
9752                                      (sign_extend:V4DI (match_dup 3)))
9753                           (parallel [(const_int 3)]))))))]
9754   "TARGET_SHMEDIA"
9755   "mmulsum.wq   %2, %3, %0"
9756   [(set_attr "type" "mac_media")])
9757
9758 (define_expand "mperm_w"
9759   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
9760    (match_operand:V4HI 1 "arith_reg_operand" "r")
9761    (match_operand:QI 2 "extend_reg_or_0_operand" "rU")]
9762   "TARGET_SHMEDIA"
9763   "
9764 {
9765   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
9766              (operands[0], operands[1], operands[2]));
9767   DONE;
9768 }")
9769
9770 ; This use of vec_select isn't exactly correct according to rtl.texi
9771 ; (because not constant), but it seems a straightforward extension.
9772 (define_insn "mperm_w_little"
9773   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9774         (vec_select:V4HI
9775          (match_operand:V4HI 1 "arith_reg_operand" "r")
9776          (parallel
9777           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rU")
9778                             (const_int 2) (const_int 0))
9779            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
9780            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
9781            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
9782   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
9783   "mperm.w      %1, %N2, %0"
9784   [(set_attr "type" "arith_media")])
9785
9786 (define_insn "mperm_w_big"
9787   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9788         (vec_select:V4HI
9789          (match_operand:V4HI 1 "arith_reg_operand" "r")
9790          (parallel
9791           [(zero_extract:QI (not:QI (match_operand:QI 2
9792                                      "extend_reg_or_0_operand" "rU"))
9793                             (const_int 2) (const_int 0))
9794            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
9795            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
9796            (zero_extract:QI (not:QI (match_dup 2))
9797                             (const_int 2) (const_int 6))])))]
9798   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
9799   "mperm.w      %1, %N2, %0"
9800   [(set_attr "type" "arith_media")])
9801
9802 (define_insn "mperm_w0"
9803   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9804         (vec_duplicate:V4HI (truncate:HI (match_operand 1
9805                                           "trunc_hi_operand" "r"))))]
9806   "TARGET_SHMEDIA"
9807   "mperm.w      %1, r63, %0"
9808   [(set_attr "type" "arith_media")])
9809
9810 (define_expand "msad_ubq"
9811   [(match_operand:DI 0 "arith_reg_dest" "")
9812    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
9813    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
9814    (match_operand:DI 3 "arith_reg_operand" "")]
9815   "TARGET_SHMEDIA"
9816   "
9817 {
9818   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
9819                              operands[1], operands[2]));
9820   DONE;
9821 }")
9822
9823 (define_insn "msad_ubq_i"
9824   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9825         (plus:DI
9826          (plus:DI
9827           (plus:DI
9828            (plus:DI
9829             (match_operand:DI 1 "arith_reg_operand" "0")
9830             (abs:DI (vec_select:DI
9831                      (minus:V8DI
9832                       (zero_extend:V8DI
9833                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "r"))
9834                       (zero_extend:V8DI
9835                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "r")))
9836                      (parallel [(const_int 0)]))))
9837            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9838                                               (zero_extend:V8DI (match_dup 3)))
9839                                   (parallel [(const_int 1)]))))
9840           (plus:DI
9841            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9842                                               (zero_extend:V8DI (match_dup 3)))
9843                                   (parallel [(const_int 2)])))
9844            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9845                                               (zero_extend:V8DI (match_dup 3)))
9846                                   (parallel [(const_int 3)])))))
9847          (plus:DI
9848           (plus:DI
9849            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9850                                               (zero_extend:V8DI (match_dup 3)))
9851                                   (parallel [(const_int 4)])))
9852            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9853                                               (zero_extend:V8DI (match_dup 3)))
9854                                   (parallel [(const_int 5)]))))
9855           (plus:DI
9856            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9857                                               (zero_extend:V8DI (match_dup 3)))
9858                                   (parallel [(const_int 6)])))
9859            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9860                                               (zero_extend:V8DI (match_dup 3)))
9861                                   (parallel [(const_int 7)])))))))]
9862   "TARGET_SHMEDIA"
9863   "msad.ubq     %N2, %N3, %0"
9864   [(set_attr "type" "mac_media")])
9865
9866 (define_insn "mshalds_l"
9867   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9868         (ss_truncate:V2SI
9869          (ashift:V2DI
9870           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
9871           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
9872                   (const_int 31)))))]
9873   "TARGET_SHMEDIA"
9874   "mshalds.l    %1, %2, %0"
9875   [(set_attr "type" "mcmp_media")])
9876
9877 (define_insn "mshalds_w"
9878   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9879         (ss_truncate:V4HI
9880          (ashift:V4SI
9881           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9882           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
9883                   (const_int 15)))))]
9884   "TARGET_SHMEDIA"
9885   "mshalds.w    %1, %2, %0"
9886   [(set_attr "type" "mcmp_media")])
9887
9888 (define_insn "ashrv2si3"
9889   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9890         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
9891                        (match_operand:DI 2 "arith_reg_operand" "r")))]
9892   "TARGET_SHMEDIA"
9893   "mshard.l     %1, %2, %0"
9894   [(set_attr "type" "arith_media")])
9895
9896 (define_insn "ashrv4hi3"
9897   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9898         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
9899                        (match_operand:DI 2 "arith_reg_operand" "r")))]
9900   "TARGET_SHMEDIA"
9901   "mshard.w     %1, %2, %0"
9902   [(set_attr "type" "arith_media")])
9903
9904 (define_insn "mshards_q"
9905   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
9906         (ss_truncate:HI
9907          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
9908                       (match_operand:DI 2 "arith_reg_or_0_operand" "rU"))))]
9909   "TARGET_SHMEDIA"
9910   "mshards.q    %1, %N2, %0"
9911   [(set_attr "type" "mcmp_media")])
9912
9913 (define_expand "mshfhi_b"
9914   [(match_operand:V8QI 0 "arith_reg_dest" "")
9915    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
9916    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
9917   "TARGET_SHMEDIA"
9918   "
9919 {
9920   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
9921              (operands[0], operands[1], operands[2]));
9922   DONE;
9923 }")
9924
9925 (define_expand "mshflo_b"
9926   [(match_operand:V8QI 0 "arith_reg_dest" "")
9927    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
9928    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
9929   "TARGET_SHMEDIA"
9930   "
9931 {
9932   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
9933              (operands[0], operands[1], operands[2]));
9934   DONE;
9935 }")
9936
9937 (define_insn "mshf4_b"
9938   [(set
9939     (match_operand:V8QI 0 "arith_reg_dest" "=r")
9940     (vec_select:V8QI
9941      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
9942                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))
9943      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
9944                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
9945   "TARGET_SHMEDIA"
9946   "* return (TARGET_LITTLE_ENDIAN
9947              ? \"mshfhi.b       %N1, %N2, %0\"
9948              : \"mshflo.b       %N1, %N2, %0\");"
9949   [(set_attr "type" "arith_media")])
9950
9951 (define_insn "mshf0_b"
9952   [(set
9953     (match_operand:V8QI 0 "arith_reg_dest" "=r")
9954     (vec_select:V8QI
9955      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
9956                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))
9957      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
9958                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
9959   "TARGET_SHMEDIA"
9960   "* return (TARGET_LITTLE_ENDIAN
9961              ? \"mshflo.b       %N1, %N2, %0\"
9962              : \"mshfhi.b       %N1, %N2, %0\");"
9963   [(set_attr "type" "arith_media")])
9964
9965 (define_expand "mshfhi_l"
9966   [(match_operand:V2SI 0 "arith_reg_dest" "")
9967    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
9968    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU")]
9969   "TARGET_SHMEDIA"
9970   "
9971 {
9972   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
9973              (operands[0], operands[1], operands[2]));
9974   DONE;
9975 }")
9976
9977 (define_expand "mshflo_l"
9978   [(match_operand:V2SI 0 "arith_reg_dest" "")
9979    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
9980    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU")]
9981   "TARGET_SHMEDIA"
9982   "
9983 {
9984   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
9985              (operands[0], operands[1], operands[2]));
9986   DONE;
9987 }")
9988
9989 (define_insn "mshf4_l"
9990   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9991         (vec_select:V2SI
9992          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
9993                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))
9994          (parallel [(const_int 1) (const_int 3)])))]
9995   "TARGET_SHMEDIA"
9996   "* return (TARGET_LITTLE_ENDIAN
9997              ? \"mshfhi.l       %N1, %N2, %0\"
9998              : \"mshflo.l       %N1, %N2, %0\");"
9999   [(set_attr "type" "arith_media")])
10000
10001 (define_insn "mshf0_l"
10002   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10003         (vec_select:V2SI
10004          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
10005                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))
10006          (parallel [(const_int 0) (const_int 2)])))]
10007   "TARGET_SHMEDIA"
10008   "* return (TARGET_LITTLE_ENDIAN
10009              ? \"mshflo.l       %N1, %N2, %0\"
10010              : \"mshfhi.l       %N1, %N2, %0\");"
10011   [(set_attr "type" "arith_media")])
10012
10013 (define_expand "mshfhi_w"
10014   [(match_operand:V4HI 0 "arith_reg_dest" "")
10015    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10016    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU")]
10017   "TARGET_SHMEDIA"
10018   "
10019 {
10020   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
10021              (operands[0], operands[1], operands[2]));
10022   DONE;
10023 }")
10024
10025 (define_expand "mshflo_w"
10026   [(match_operand:V4HI 0 "arith_reg_dest" "")
10027    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10028    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU")]
10029   "TARGET_SHMEDIA"
10030   "
10031 {
10032   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
10033              (operands[0], operands[1], operands[2]));
10034   DONE;
10035 }")
10036
10037 (define_insn "mshf4_w"
10038   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10039         (vec_select:V4HI
10040          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10041                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))
10042          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
10043   "TARGET_SHMEDIA"
10044   "* return (TARGET_LITTLE_ENDIAN
10045              ? \"mshfhi.w       %N1, %N2, %0\"
10046              : \"mshflo.w       %N1, %N2, %0\");"
10047   [(set_attr "type" "arith_media")])
10048
10049 (define_insn "mshf0_w"
10050   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10051         (vec_select:V4HI
10052          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10053                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))
10054          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
10055   "TARGET_SHMEDIA"
10056   "* return (TARGET_LITTLE_ENDIAN
10057              ? \"mshflo.w       %N1, %N2, %0\"
10058              : \"mshfhi.w       %N1, %N2, %0\");"
10059   [(set_attr "type" "arith_media")])
10060
10061 (define_insn "mshflo_w_x"
10062   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10063         (vec_select:V4HI
10064          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rU")
10065                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rU"))
10066          (parallel [(const_int 0) (const_int 2) (const_int 1) (const_int 3)])))]
10067   "TARGET_SHMEDIA"
10068   "mshflo.w     %N1, %N2, %0"
10069   [(set_attr "type" "arith_media")])
10070
10071 /* These are useful to expand ANDs and as combiner patterns.  */
10072 (define_insn_and_split "mshfhi_l_di"
10073   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
10074         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU,f")
10075                              (const_int 32))
10076                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU,?f")
10077                         (const_int -4294967296))))]
10078   "TARGET_SHMEDIA"
10079   "@
10080         mshfhi.l        %N1, %N2, %0
10081         #"
10082   "TARGET_SHMEDIA && reload_completed
10083    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
10084   [(set (match_dup 3) (match_dup 4))
10085    (set (match_dup 5) (match_dup 6))]
10086   "
10087 {
10088   operands[3] = gen_lowpart (SImode, operands[0]);
10089   operands[4] = gen_highpart (SImode, operands[1]);
10090   operands[5] = gen_highpart (SImode, operands[0]);
10091   operands[6] = gen_highpart (SImode, operands[2]);
10092 }"
10093   [(set_attr "type" "arith_media")])
10094
10095 (define_insn "*mshfhi_l_di_rev"
10096   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10097         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
10098                         (const_int -4294967296))
10099                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
10100                              (const_int 32))))]
10101   "TARGET_SHMEDIA"
10102   "mshfhi.l     %N2, %N1, %0"
10103   [(set_attr "type" "arith_media")])
10104
10105 (define_split
10106   [(set (match_operand:DI 0 "arith_reg_dest" "")
10107         (ior:DI (zero_extend:DI (match_operand:SI 1
10108                                               "extend_reg_or_0_operand" ""))
10109                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
10110                         (const_int -4294967296))))
10111    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
10112   "TARGET_SHMEDIA"
10113   [(const_int 0)]
10114   "
10115 {
10116   emit_insn (gen_ashldi3_media (operands[3],
10117                                 simplify_gen_subreg (DImode, operands[1],
10118                                                      SImode, 0),
10119                                 GEN_INT (32)));
10120   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
10121   DONE;
10122 }")
10123
10124 (define_insn "mshflo_l_di"
10125   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10126         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
10127                         (const_int 4294967295))
10128                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
10129                            (const_int 32))))]
10130                                 
10131   "TARGET_SHMEDIA"
10132   "mshflo.l     %N1, %N2, %0"
10133   [(set_attr "type" "arith_media")])
10134
10135 (define_insn "*mshflo_l_di_rev"
10136   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10137         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
10138                            (const_int 32))
10139                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
10140                         (const_int 4294967295))))]
10141                                 
10142   "TARGET_SHMEDIA"
10143   "mshflo.l     %N2, %N1, %0"
10144   [(set_attr "type" "arith_media")])
10145
10146 ;; Combiner pattern for trampoline initialization.
10147 (define_insn_and_split "*double_shori"
10148   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10149         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
10150                            (const_int 32))
10151                 (match_operand:DI 2 "const_int_operand" "n")))]
10152   "TARGET_SHMEDIA
10153    && INTVAL (operands[2]) == trunc_int_for_mode (INTVAL (operands[2]), SImode)"
10154   "#"
10155   "rtx_equal_p (operands[0], operands[1])"
10156   [(const_int 0)]
10157   "
10158 {
10159   HOST_WIDE_INT v = INTVAL (operands[2]);
10160
10161   emit_insn (gen_shori_media (operands[0], operands[0],
10162              gen_int_mode (INTVAL (operands[2]) >> 16, HImode)));
10163   emit_insn (gen_shori_media (operands[0], operands[0],
10164                               gen_int_mode (v, HImode)));
10165   DONE;
10166 }")
10167
10168
10169 (define_insn "*mshflo_l_di_x"
10170   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10171         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
10172                                  "rU"))
10173                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
10174                            (const_int 32))))]
10175                                 
10176   "TARGET_SHMEDIA"
10177   "mshflo.l     %N1, %N2, %0"
10178   [(set_attr "type" "arith_media")])
10179
10180 (define_insn_and_split "concat_v2sf"
10181   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
10182 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rU,0,f")
10183         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rU,f,f")
10184                          (match_operand:SF 2 "register_operand" "rU,f,f")))]
10185                                 
10186   "TARGET_SHMEDIA"
10187   "@
10188         mshflo.l        %N1, %N2, %0
10189         #
10190         #"
10191   "TARGET_SHMEDIA && reload_completed
10192    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
10193   [(set (match_dup 3) (match_dup 1))
10194    (set (match_dup 4) (match_dup 2))]
10195   "
10196 {
10197   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
10198   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
10199 }"
10200   [(set_attr "type" "arith_media")])
10201
10202 (define_insn "*mshflo_l_di_x_rev"
10203   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10204         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
10205                            (const_int 32))
10206                 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rU"))))]
10207                                 
10208   "TARGET_SHMEDIA"
10209   "mshflo.l     %N2, %N1, %0"
10210   [(set_attr "type" "arith_media")])
10211
10212 (define_insn "ashlv2si3"
10213   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10214         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10215                      (match_operand:DI 2 "arith_reg_operand" "r")))]
10216   "TARGET_SHMEDIA"
10217   "mshlld.l     %1, %2, %0"
10218   [(set_attr "type" "arith_media")])
10219
10220 (define_insn "ashlv4hi3"
10221   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10222         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10223                      (match_operand:DI 2 "arith_reg_operand" "r")))]
10224   "TARGET_SHMEDIA"
10225   "mshlld.w     %1, %2, %0"
10226   [(set_attr "type" "arith_media")])
10227
10228 (define_insn "lshrv2si3"
10229   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10230         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10231                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10232   "TARGET_SHMEDIA"
10233   "mshlrd.l     %1, %2, %0"
10234   [(set_attr "type" "arith_media")])
10235
10236 (define_insn "lshrv4hi3"
10237   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10238         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10239                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10240   "TARGET_SHMEDIA"
10241   "mshlrd.w     %1, %2, %0"
10242   [(set_attr "type" "arith_media")])
10243
10244 (define_insn "subv2si3"
10245   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10246         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
10247                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10248   "TARGET_SHMEDIA"
10249   "msub.l       %N1, %2, %0"
10250   [(set_attr "type" "arith_media")])
10251
10252 (define_insn "subv4hi3"
10253   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10254         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10255                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10256   "TARGET_SHMEDIA"
10257   "msub.w       %N1, %2, %0"
10258   [(set_attr "type" "arith_media")])
10259
10260 (define_insn "sssubv2si3"
10261   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10262         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
10263                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10264   "TARGET_SHMEDIA"
10265   "msubs.l      %N1, %2, %0"
10266   [(set_attr "type" "mcmp_media")])
10267
10268 (define_insn "ussubv8qi3"
10269   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
10270         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
10271                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
10272   "TARGET_SHMEDIA"
10273   "msubs.ub     %1, %2, %0"
10274   [(set_attr "type" "mcmp_media")])
10275
10276 (define_insn "sssubv4hi3"
10277   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10278         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10279                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10280   "TARGET_SHMEDIA"
10281   "msubs.w      %N1, %2, %0"
10282   [(set_attr "type" "mcmp_media")])
10283
10284 ;; Floating Point Intrinsics
10285
10286 (define_insn "fcosa_s"
10287   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10288         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
10289                    UNSPEC_FCOSA))]
10290   "TARGET_SHMEDIA"
10291   "fcosa.s      %1, %0"
10292   [(set_attr "type" "atrans_media")])
10293
10294 (define_insn "fsina_s"
10295   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10296         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
10297                    UNSPEC_FSINA))]
10298   "TARGET_SHMEDIA"
10299   "fsina.s      %1, %0"
10300   [(set_attr "type" "atrans_media")])
10301
10302 (define_insn "fipr"
10303   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10304         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
10305                                                     "fp_arith_reg_operand" "f")
10306                                                    (match_operand:V4SF 2
10307                                                     "fp_arith_reg_operand" "f"))
10308                                          (parallel [(const_int 0)]))
10309                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10310                                          (parallel [(const_int 1)])))
10311                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10312                                          (parallel [(const_int 2)]))
10313                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10314                                          (parallel [(const_int 3)])))))]
10315   "TARGET_SHMEDIA"
10316   "fipr %1, %2, %0"
10317   [(set_attr "type" "fparith_media")])
10318
10319 (define_insn "fsrra_s"
10320   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10321         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
10322                    UNSPEC_FSRRA))]
10323   "TARGET_SHMEDIA"
10324   "fsrra.s      %1, %0"
10325   [(set_attr "type" "atrans_media")])
10326
10327 (define_insn "ftrv"
10328   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
10329         (plus:V4SF
10330          (plus:V4SF
10331           (mult:V4SF
10332            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
10333                             (parallel [(const_int 0) (const_int 5)
10334                                        (const_int 10) (const_int 15)]))
10335            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
10336           (mult:V4SF
10337            (vec_select:V4SF (match_dup 1)
10338                             (parallel [(const_int 4) (const_int 9)
10339                                        (const_int 14) (const_int 3)]))
10340            (vec_select:V4SF (match_dup 2)
10341                             (parallel [(const_int 1) (const_int 2)
10342                                       (const_int 3) (const_int 0)]))))
10343          (plus:V4SF
10344           (mult:V4SF
10345            (vec_select:V4SF (match_dup 1)
10346                             (parallel [(const_int 8) (const_int 13)
10347                                        (const_int 2) (const_int 7)]))
10348            (vec_select:V4SF (match_dup 2)
10349                             (parallel [(const_int 2) (const_int 3)
10350                                        (const_int 0) (const_int 1)])))
10351           (mult:V4SF
10352            (vec_select:V4SF (match_dup 1)
10353                             (parallel [(const_int 12) (const_int 1)
10354                                        (const_int 6) (const_int 11)]))
10355            (vec_select:V4SF (match_dup 2)
10356                             (parallel [(const_int 3) (const_int 0)
10357                                        (const_int 1) (const_int 2)]))))))]
10358   "TARGET_SHMEDIA"
10359   "ftrv %1, %2, %0"
10360   [(set_attr "type" "fparith_media")])
10361
10362 (define_insn "nsb"
10363   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
10364         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10365                    UNSPEC_NSB))]
10366   "TARGET_SHMEDIA"
10367   "nsb  %1, %0"
10368   [(set_attr "type" "arith_media")])
10369
10370 (define_insn "nsbsi"
10371   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
10372         (zero_extend:SI
10373          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10374                     UNSPEC_NSB)))]
10375   "TARGET_SHMEDIA"
10376   "nsb  %1, %0"
10377   [(set_attr "type" "arith_media")])
10378
10379 (define_insn "nsbdi"
10380   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10381         (zero_extend:DI
10382          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10383                     UNSPEC_NSB)))]
10384   "TARGET_SHMEDIA"
10385   "nsb  %1, %0"
10386   [(set_attr "type" "arith_media")])
10387
10388 (define_expand "ffsdi2"
10389   [(set (match_operand:DI 0 "arith_reg_dest" "")
10390         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
10391   "TARGET_SHMEDIA"
10392   "
10393 {
10394   rtx scratch = gen_reg_rtx (DImode);
10395   rtx last;
10396
10397   emit_insn (gen_adddi3 (scratch, operands[1], GEN_INT (-1)));
10398   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
10399   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
10400   emit_insn (gen_nsbdi (scratch, scratch));
10401   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
10402   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
10403   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
10404   REG_NOTES (last)
10405     = gen_rtx_EXPR_LIST (REG_EQUAL,
10406                          gen_rtx_FFS (DImode, operands[0]), REG_NOTES (last));
10407   DONE;
10408 }")
10409
10410 (define_expand "ffssi2"
10411   [(set (match_operand:SI 0 "arith_reg_dest" "")
10412         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
10413   "TARGET_SHMEDIA"
10414   "
10415 {
10416   rtx scratch = gen_reg_rtx (SImode);
10417   rtx discratch = gen_reg_rtx (DImode);
10418   rtx last;
10419
10420   emit_insn (gen_adddi3 (discratch,
10421                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
10422                          GEN_INT (-1)));
10423   emit_insn (gen_andcdi3 (discratch,
10424                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
10425                           discratch));
10426   emit_insn (gen_nsbsi (scratch, discratch));
10427   last = emit_insn (gen_subsi3 (operands[0],
10428                                 force_reg (SImode, GEN_INT (63)), scratch));
10429   REG_NOTES (last)
10430     = gen_rtx_EXPR_LIST (REG_EQUAL,
10431                          gen_rtx_FFS (SImode, operands[0]), REG_NOTES (last));
10432   DONE;
10433 }")
10434
10435 (define_insn "byterev"
10436   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
10437         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
10438                          (parallel [(const_int 7) (const_int 6) (const_int 5)
10439                                     (const_int 4) (const_int 3) (const_int 2)
10440                                     (const_int 1) (const_int 0)])))]
10441   "TARGET_SHMEDIA"
10442   "byterev      %1, %0"
10443   [(set_attr "type" "arith_media")])
10444
10445 ;; The following description  models the
10446 ;; SH4 pipeline using the DFA based scheduler. 
10447 ;; The DFA based description is better way to model 
10448 ;; a superscalar pipeline as compared to function unit
10449 ;; reservation model.   
10450 ;; 1. The function unit based model is oriented to describe at most one 
10451 ;;    unit reservation by each insn. It is difficult to model unit reservations in multiple 
10452 ;;    pipeline units by same insn. This can be done using DFA based description.
10453 ;; 2. The execution performance of DFA based scheduler does not depend on processor complexity.
10454 ;; 3. Writing all unit reservations for an instruction class is more natural description 
10455 ;;    of the pipeline and makes interface of the hazard recognizer simpler than the 
10456 ;;    old function unit based model.
10457 ;; 4. The DFA model is richer and is a part of greater overall framework of RCSP.
10458
10459
10460 ;; Two automata are defined to reduce number of states
10461 ;; which a single large automaton will have.(Factoring)
10462
10463 (define_automaton "inst_pipeline,fpu_pipe")
10464
10465 ;; This unit is basically the decode unit of the processor.
10466 ;; Since SH4 is a dual issue machine,it is as if there are two 
10467 ;; units so that any insn can be processed by either one
10468 ;; of the decoding unit.
10469
10470 (define_cpu_unit "pipe_01,pipe_02" "inst_pipeline")
10471
10472
10473 ;; The fixed point arithmetic calculator(?? EX Unit).
10474
10475 (define_cpu_unit  "int" "inst_pipeline")
10476
10477 ;; f1_1 and f1_2 are floating point units.Actually there is
10478 ;; a f1 unit which can overlap with other f1 unit but
10479 ;; not another F1 unit.It is as though there were two
10480 ;; f1 units.
10481
10482 (define_cpu_unit "f1_1,f1_2" "fpu_pipe")
10483
10484 ;; The floating point units (except FS - F2 always precedes it.)
10485
10486 (define_cpu_unit "F0,F1,F2,F3" "fpu_pipe")
10487
10488 ;; This is basically the MA unit of SH4
10489 ;; used in LOAD/STORE pipeline.
10490
10491 (define_cpu_unit "memory" "inst_pipeline")
10492
10493 ;; However, there are LS group insns that don't use it, even ones that
10494 ;; complete in 0 cycles.  So we use an extra unit for the issue of LS insns.
10495 (define_cpu_unit "load_store" "inst_pipeline")
10496
10497 ;; The address calculator used for branch instructions.
10498 ;; This will be reserved after "issue" of branch instructions
10499 ;; and this is to make sure that no two branch instructions 
10500 ;; can be issued in parallel. 
10501
10502 (define_cpu_unit "pcr_addrcalc" "inst_pipeline")
10503
10504 ;; ----------------------------------------------------
10505 ;; This reservation is to simplify the dual issue description.
10506
10507 (define_reservation  "issue"  "pipe_01|pipe_02")
10508
10509 ;; This is to express the locking of D stage.
10510 ;; Note that the issue of a CO group insn also effectively locks the D stage.
10511
10512 (define_reservation  "d_lock" "pipe_01+pipe_02")
10513
10514 ;; Every FE instruction but fipr / ftrv starts with issue and this.
10515 (define_reservation "F01" "F0+F1")
10516
10517 ;; This is to simplify description where F1,F2,FS
10518 ;; are used simultaneously.
10519
10520 (define_reservation "fpu" "F1+F2")
10521
10522 ;; This is to highlight the fact that f1 
10523 ;; cannot overlap with F1.
10524
10525 (exclusion_set  "f1_1,f1_2" "F1")
10526
10527 (define_insn_reservation "nil" 0 (eq_attr "type" "nil") "nothing")
10528
10529 ;; Although reg moves have a latency of zero 
10530 ;; we need to highlight that they use D stage
10531 ;; for one cycle.
10532
10533 ;; Group:       MT
10534
10535 (define_insn_reservation "reg_mov" 0
10536   (and (eq_attr "pipe_model" "sh4")
10537        (eq_attr "type" "move"))
10538   "issue")
10539
10540 ;; Group:       LS
10541
10542 (define_insn_reservation "freg_mov" 0
10543   (and (eq_attr "pipe_model" "sh4")
10544        (eq_attr "type" "fmove"))
10545   "issue+load_store")
10546
10547 ;; We don't model all pipeline stages; we model the issue ('D') stage
10548 ;; inasmuch as we allow only two instructions to issue simultanously,
10549 ;; and CO instructions prevent any simultanous issue of another instruction.
10550 ;; (This uses pipe_01 and pipe_02).
10551 ;; Double issue of EX insns is prevented by using the int unit in the EX stage.
10552 ;; Double issue of EX / BR insns is prevented by using the int unit /
10553 ;; pcr_addrcalc unit in the EX stage.
10554 ;; Double issue of BR / LS instructions is prevented by using the
10555 ;; pcr_addrcalc / load_store unit in the issue cycle.
10556 ;; Double issue of FE instructions is prevented by using F0 in the first
10557 ;; pipeline stage after the first D stage.
10558 ;; There is no need to describe the [ES]X / [MN]A / S stages after a D stage
10559 ;; (except in the cases outlined above), nor to describe the FS stage after
10560 ;; the F2 stage.
10561
10562 ;; Other MT  group intructions(1 step operations)
10563 ;; Group:       MT
10564 ;; Latency:     1
10565 ;; Issue Rate:  1
10566
10567 (define_insn_reservation "mt" 1
10568   (and (eq_attr "pipe_model" "sh4")
10569        (eq_attr "type" "mt_group"))
10570   "issue")
10571
10572 ;; Fixed Point Arithmetic Instructions(1 step operations)
10573 ;; Group:       EX
10574 ;; Latency:     1
10575 ;; Issue Rate:  1
10576
10577 (define_insn_reservation "sh4_simple_arith" 1 
10578   (and (eq_attr "pipe_model" "sh4")
10579        (eq_attr "insn_class" "ex_group"))
10580   "issue,int")
10581
10582 ;; Load and store instructions have no alignment peculiarities for the SH4,
10583 ;; but they use the load-store unit, which they share with the fmove type
10584 ;; insns (fldi[01]; fmov frn,frm; flds; fsts; fabs; fneg) .
10585 ;; Loads have a latency of two.
10586 ;; However, call insns can only paired with a preceding insn, and have
10587 ;; a delay slot, so that we want two more insns to be scheduled between the
10588 ;; load of the function address and the call.  This is equivalent to a
10589 ;; latency of three.
10590 ;; ADJUST_COST can only properly handle reductions of the cost, so we
10591 ;; use a latency of three here, which gets multiplied by 10 to yield 30.
10592 ;; We only do this for SImode loads of general registers, to make the work
10593 ;; for ADJUST_COST easier.
10594
10595 ;; Load Store instructions. (MOV.[BWL]@(d,GBR)
10596 ;; Group:       LS
10597 ;; Latency:     2
10598 ;; Issue Rate:  1
10599
10600 (define_insn_reservation "sh4_load" 2
10601   (and (eq_attr "pipe_model" "sh4")
10602        (eq_attr "type" "load,pcload"))
10603   "issue+load_store,nothing,memory")
10604
10605 ;; calls / sfuncs need an extra instruction for their delay slot.
10606 ;; Moreover, estimating the latency for SImode loads as 3 will also allow
10607 ;; adjust_cost to meaningfully bump it back up to 3 if they load the shift
10608 ;; count of a dynamic shift.
10609 (define_insn_reservation "sh4_load_si" 3
10610   (and (eq_attr "pipe_model" "sh4")
10611        (eq_attr "type" "load_si,pcload_si"))
10612   "issue+load_store,nothing,memory")
10613
10614 ;; (define_bypass 2 "sh4_load_si" "!sh4_call")
10615
10616 ;; The load latency is upped to three higher if the dependent insn does
10617 ;; double precision computation.  We want the 'default' latency to reflect
10618 ;; that increased latency because otherwise the insn priorities won't
10619 ;; allow proper scheduling.
10620 (define_insn_reservation "sh4_fload" 3
10621   (and (eq_attr "pipe_model" "sh4")
10622        (eq_attr "type" "fload,pcfload"))
10623   "issue+load_store,nothing,memory")
10624
10625 ;; (define_bypass 2 "sh4_fload" "!")
10626
10627 (define_insn_reservation "sh4_store" 1
10628   (and (eq_attr "pipe_model" "sh4")
10629        (eq_attr "type" "store"))
10630   "issue+load_store,nothing,memory")
10631
10632 ;; Load Store instructions.
10633 ;; Group:       LS
10634 ;; Latency:     1
10635 ;; Issue Rate:  1
10636
10637 (define_insn_reservation "sh4_gp_fpul" 1
10638   (and (eq_attr "pipe_model" "sh4")
10639        (eq_attr "type" "gp_fpul"))
10640   "issue+load_store")
10641
10642 ;; Load Store instructions.
10643 ;; Group:       LS
10644 ;; Latency:     3
10645 ;; Issue Rate:  1
10646
10647 (define_insn_reservation "sh4_fpul_gp" 3
10648   (and (eq_attr "pipe_model" "sh4")
10649        (eq_attr "type" "fpul_gp"))
10650   "issue+load_store")
10651
10652 ;; Branch (BF,BF/S,BT,BT/S,BRA)
10653 ;; Group:       BR
10654 ;; Latency when taken:  2 (or 1)
10655 ;; Issue Rate:  1
10656 ;; The latency is 1 when displacement is 0.
10657 ;; We can't really do much with the latency, even if we could express it,
10658 ;; but the pairing restrictions are useful to take into account.
10659 ;; ??? If the branch is likely, we might want to fill the delay slot;
10660 ;; if the branch is likely, but not very likely, should we pretend to use
10661 ;; a resource that CO instructions use, to get a pairable delay slot insn?
10662
10663 (define_insn_reservation "sh4_branch"  1
10664   (and (eq_attr "pipe_model" "sh4")
10665        (eq_attr "type" "cbranch,jump"))
10666   "issue+pcr_addrcalc")
10667
10668 ;; Branch Far (JMP,RTS,BRAF)
10669 ;; Group:       CO
10670 ;; Latency:     3
10671 ;; Issue Rate:  2
10672 ;; ??? Scheduling happens before branch shortening, and hence jmp and braf
10673 ;; can't be distinguished from bra for the "jump" pattern.
10674
10675 (define_insn_reservation "sh4_return" 3
10676   (and (eq_attr "pipe_model" "sh4")
10677        (eq_attr "type" "return,jump_ind"))
10678          "d_lock*2")
10679
10680 ;; RTE
10681 ;; Group:       CO
10682 ;; Latency:     5
10683 ;; Issue Rate:  5
10684 ;; this instruction can be executed in any of the pipelines 
10685 ;; and blocks the pipeline for next 4 stages.
10686
10687 (define_insn_reservation "sh4_return_from_exp" 5
10688   (and (eq_attr "pipe_model" "sh4")
10689        (eq_attr "type" "rte"))
10690   "d_lock*5")
10691
10692 ;; OCBP, OCBWB
10693 ;; Group:       CO
10694 ;; Latency:     1-5
10695 ;; Issue Rate:  1
10696
10697 ;; cwb is used for the sequence ocbwb @%0; extu.w %0,%2; or %1,%2; mov.l %0,@%2
10698 ;; ocbwb on its own would be "d_lock,nothing,memory*5"
10699 (define_insn_reservation "ocbwb"  6
10700   (and (eq_attr "pipe_model" "sh4")
10701        (eq_attr "type" "cwb"))
10702   "d_lock*2,(d_lock+memory)*3,issue+load_store+memory,memory*2")
10703                 
10704 ;; LDS to PR,JSR
10705 ;; Group:       CO
10706 ;; Latency:     3
10707 ;; Issue Rate:  2
10708 ;; The SX stage is blocked for last 2 cycles.
10709 ;; OTOH, the only time that has an effect for insns generated by the compiler
10710 ;; is when lds to PR is followed by sts from PR - and that is highly unlikely -
10711 ;; or when we are doing a function call - and we don't do inter-function
10712 ;; scheduling.  For the function call case, it's really best that we end with
10713 ;; something that models an rts.
10714
10715 (define_insn_reservation "sh4_lds_to_pr" 3 
10716   (and (eq_attr "pipe_model" "sh4")
10717        (eq_attr "type" "prset") )
10718   "d_lock*2")
10719
10720 ;; calls introduce a longisch delay that is likely to flush the pipelines
10721 ;; of the caller's instructions.  Ordinary functions tend to end with a
10722 ;; load to restore a register (in the delay slot of rts), while sfuncs
10723 ;; tend to end with an EX or MT insn.  But that is not actually relevant,
10724 ;; since there are no instructions that contend for memory access early.
10725 ;; We could, of course, provide exact scheduling information for specific
10726 ;; sfuncs, if that should prove useful.
10727
10728 (define_insn_reservation "sh4_call" 16 
10729   (and (eq_attr "pipe_model" "sh4")
10730        (eq_attr "type" "call,sfunc"))
10731   "d_lock*16")
10732
10733 ;; LDS.L to PR 
10734 ;; Group:       CO
10735 ;; Latency:     3
10736 ;; Issue Rate:  2
10737 ;; The SX unit is blocked for last 2 cycles.
10738  
10739 (define_insn_reservation "ldsmem_to_pr"  3
10740   (and (eq_attr "pipe_model" "sh4")
10741        (eq_attr "type" "pload"))
10742   "d_lock*2")
10743
10744 ;; STS from PR
10745 ;; Group:       CO
10746 ;; Latency:     2
10747 ;; Issue Rate:  2
10748 ;; The SX unit in second and third cycles.
10749
10750 (define_insn_reservation "sts_from_pr" 2
10751   (and (eq_attr "pipe_model" "sh4")
10752        (eq_attr "type" "prget"))
10753   "d_lock*2")
10754
10755 ;; STS.L from PR
10756 ;; Group:       CO
10757 ;; Latency:     2
10758 ;; Issue Rate:  2
10759
10760 (define_insn_reservation "sh4_prstore_mem" 2 
10761   (and (eq_attr "pipe_model" "sh4")
10762        (eq_attr "type" "pstore"))
10763   "d_lock*2,nothing,memory")
10764
10765 ;; LDS to FPSCR
10766 ;; Group:       CO
10767 ;; Latency:     4
10768 ;; Issue Rate:  1
10769 ;; F1 is blocked for last three cycles. 
10770
10771 (define_insn_reservation "fpscr_load" 4
10772   (and (eq_attr "pipe_model" "sh4")
10773        (eq_attr "type" "gp_fpscr"))
10774   "d_lock,nothing,F1*3")
10775
10776 ;; LDS.L to FPSCR
10777 ;; Group:       CO
10778 ;; Latency:     1 / 4
10779 ;; Latency to update Rn is 1 and latency to update FPSCR is 4
10780 ;; Issue Rate:  1
10781 ;; F1 is blocked for last three cycles.
10782
10783 (define_insn_reservation "fpscr_load_mem" 4
10784   (and (eq_attr "pipe_model" "sh4")
10785        (eq_attr "type"  "mem_fpscr"))
10786   "d_lock,nothing,(F1+memory),F1*2")
10787
10788 \f
10789 ;; Fixed point multiplication (DMULS.L DMULU.L MUL.L MULS.W,MULU.W)
10790 ;; Group:       CO
10791 ;; Latency:     4 / 4
10792 ;; Issue Rate:  1
10793
10794 (define_insn_reservation "multi" 4
10795   (and (eq_attr "pipe_model" "sh4")
10796        (eq_attr "type" "smpy,dmpy"))
10797   "d_lock,(d_lock+f1_1),(f1_1|f1_2)*3,F2")
10798
10799 ;; Fixed STS from MACL / MACH
10800 ;; Group:       CO
10801 ;; Latency:     3
10802 ;; Issue Rate:  1
10803
10804 (define_insn_reservation "sh4_mac_gp" 3
10805   (and (eq_attr "pipe_model" "sh4")
10806        (eq_attr "type" "mac_gp"))
10807   "d_lock")
10808
10809
10810 ;; Single precision floating point computation FCMP/EQ,
10811 ;; FCMP/GT, FADD, FLOAT, FMAC, FMUL, FSUB, FTRC, FRVHG, FSCHG
10812 ;; Group:       FE
10813 ;; Latency:     3/4
10814 ;; Issue Rate:  1
10815
10816 (define_insn_reservation "fp_arith"  3
10817   (and (eq_attr "pipe_model" "sh4")
10818        (eq_attr "type" "fp"))
10819   "issue,F01,F2")
10820
10821 (define_insn_reservation "fp_arith_ftrc"  3
10822   (and (eq_attr "pipe_model" "sh4")
10823        (eq_attr "type" "ftrc_s"))
10824   "issue,F01,F2")
10825
10826 (define_bypass 1 "fp_arith_ftrc" "sh4_fpul_gp")
10827
10828 ;; Single Precision FDIV/SQRT
10829 ;; Group:       FE
10830 ;; Latency:     12/13 (FDIV); 11/12 (FSQRT)
10831 ;; Issue Rate:  1
10832 ;; We describe fdiv here; fsqrt is actually one cycle faster.
10833
10834 (define_insn_reservation "fp_div" 12
10835   (and (eq_attr "pipe_model" "sh4")
10836        (eq_attr "type" "fdiv"))
10837   "issue,F01+F3,F2+F3,F3*7,F1+F3,F2")
10838
10839 ;; Double Precision floating point computation
10840 ;; (FCNVDS, FCNVSD, FLOAT, FTRC)
10841 ;; Group:       FE
10842 ;; Latency:     (3,4)/5
10843 ;; Issue Rate:  1
10844
10845 (define_insn_reservation "dp_float" 4
10846   (and (eq_attr "pipe_model" "sh4")
10847        (eq_attr "type" "dfp_conv"))
10848   "issue,F01,F1+F2,F2")
10849
10850 ;; Double-precision floating-point (FADD,FMUL,FSUB) 
10851 ;; Group:       FE
10852 ;; Latency:     (7,8)/9
10853 ;; Issue Rate:  1
10854
10855 (define_insn_reservation "fp_double_arith" 8
10856   (and (eq_attr "pipe_model" "sh4")
10857        (eq_attr "type" "dfp_arith"))
10858   "issue,F01,F1+F2,fpu*4,F2")
10859
10860 ;; Double-precision FCMP (FCMP/EQ,FCMP/GT) 
10861 ;; Group:       CO
10862 ;; Latency:     3/5
10863 ;; Issue Rate:  2
10864
10865 (define_insn_reservation "fp_double_cmp" 3 
10866   (and (eq_attr "pipe_model" "sh4")
10867        (eq_attr "type" "dfp_cmp"))
10868   "d_lock,(d_lock+F01),F1+F2,F2")
10869
10870 ;; Double precision FDIV/SQRT
10871 ;; Group:       FE
10872 ;; Latency:     (24,25)/26
10873 ;; Issue Rate:  1
10874
10875 (define_insn_reservation "dp_div" 25
10876   (and (eq_attr "pipe_model" "sh4")
10877        (eq_attr "type" "dfdiv"))
10878   "issue,F01+F3,F1+F2+F3,F2+F3,F3*16,F1+F3,(fpu+F3)*2,F2")
10879
10880
10881 ;; Use the branch-not-taken case to model arith3 insns.  For the branch taken
10882 ;; case, we'd get a d_lock instead of issue at the end.
10883 (define_insn_reservation "arith3" 3
10884   (and (eq_attr "pipe_model" "sh4")
10885        (eq_attr "type" "arith3"))
10886   "issue,d_lock+pcr_addrcalc,issue")
10887
10888 ;; arith3b insns schedule the same no matter if the branch is taken or not.
10889 (define_insn_reservation "arith3b" 2
10890   (and (eq_attr "pipe_model" "sh4")
10891        (eq_attr "type" "arith3"))
10892   "issue,d_lock+pcr_addrcalc")