OSDN Git Service

* sh.c (reg_class_from_letter): No longer const. Add 'e' entry.
[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 ;; ??? We can't include f/f because we need the proper FPSCR setting when
3412 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
3413 (define_insn "movsi_ie"
3414   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
3415         (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
3416   "TARGET_SH3E
3417    && (register_operand (operands[0], SImode)
3418        || register_operand (operands[1], SImode))"
3419   "@
3420         mov.l   %1,%0
3421         mov     %1,%0
3422         cmp/pl  %1
3423         mov.l   %1,%0
3424         sts     %1,%0
3425         sts     %1,%0
3426         movt    %0
3427         mov.l   %1,%0
3428         sts.l   %1,%0
3429         sts.l   %1,%0
3430         lds     %1,%0
3431         lds     %1,%0
3432         lds.l   %1,%0
3433         lds.l   %1,%0
3434         lds.l   %1,%0
3435         sts.l   %1,%0
3436         fake    %1,%0
3437         lds     %1,%0
3438         sts     %1,%0
3439         fsts    fpul,%0
3440         flds    %1,fpul
3441         fmov    %1,%0
3442         ! move optimized away"
3443   [(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,fmove,fmove,fmove,nil")
3444    (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
3445    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
3446
3447 (define_insn "movsi_i_lowpart"
3448   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
3449         (match_operand:SI 1 "general_movsrc_operand" "Q,rI,mr,x,l,t,r,i"))]
3450    "TARGET_SH1
3451     && (register_operand (operands[0], SImode)
3452         || register_operand (operands[1], SImode))"
3453   "@
3454         mov.l   %1,%0
3455         mov     %1,%0
3456         mov.l   %1,%0
3457         sts     %1,%0
3458         sts     %1,%0
3459         movt    %0
3460         mov.l   %1,%0
3461         fake    %1,%0"
3462   [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
3463
3464 (define_insn "*movsi_media"
3465   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,m,f,m,f,r,f,*b,r,b")
3466         (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,m,f,rU,f,f,r,*b,T"))]
3467   "TARGET_SHMEDIA_FPU
3468    && (register_operand (operands[0], SImode)
3469        || register_operand (operands[1], SImode))"
3470   "@
3471         add.l   %1, r63, %0
3472         movi    %1, %0
3473         #
3474         ld%M1.l %m1, %0
3475         st%M0.l %m0, %1
3476         fld%M1.s        %m1, %0
3477         fst%M0.s        %m0, %1
3478         fmov.ls %N1, %0
3479         fmov.sl %1, %0
3480         fmov.s  %1, %0
3481         ptabs   %1, %0
3482         gettr   %1, %0
3483         pt      %1, %0"
3484   [(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")
3485    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")])
3486
3487 (define_insn "*movsi_media_nofpu"
3488   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,m,*b,r,b")
3489         (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,r,*b,T"))]
3490   "TARGET_SHMEDIA
3491    && (register_operand (operands[0], SImode)
3492        || register_operand (operands[1], SImode))"
3493   "@
3494         add.l   %1, r63, %0
3495         movi    %1, %0
3496         #
3497         ld%M1.l %m1, %0
3498         st%M0.l %m0, %1
3499         ptabs   %1, %0
3500         gettr   %1, %0
3501         pt      %1, %0"
3502   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
3503    (set_attr "length" "4,4,8,4,4,4,4,12")])
3504
3505 (define_split
3506   [(set (match_operand:SI 0 "arith_reg_operand" "")
3507         (match_operand:SI 1 "immediate_operand" ""))]
3508   "TARGET_SHMEDIA && reload_completed
3509    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3510   [(set (subreg:DI (match_dup 0) 0) (match_dup 2))]
3511   "
3512 {
3513   operands[2] = shallow_copy_rtx (operands[1]);
3514   PUT_MODE (operands[2], DImode);
3515 }")
3516
3517 (define_split
3518   [(set (match_operand:SI 0 "register_operand" "")
3519         (match_operand:SI 1 "immediate_operand" ""))]
3520   "TARGET_SHMEDIA && reload_completed
3521    && ((GET_CODE (operands[1]) == CONST_INT
3522         && ! CONST_OK_FOR_J (INTVAL (operands[1])))
3523        || GET_CODE (operands[1]) == CONST_DOUBLE)"
3524   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3525
3526 (define_expand "movsi"
3527   [(set (match_operand:SI 0 "general_movdst_operand" "")
3528         (match_operand:SI 1 "general_movsrc_operand" ""))]
3529   ""
3530   "{ if (prepare_move_operands (operands, SImode)) DONE; }")
3531
3532 (define_expand "ic_invalidate_line"
3533   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
3534                                 (match_dup 1)] UNSPEC_ICACHE)
3535               (clobber (scratch:SI))])]
3536   "TARGET_HARD_SH4 || TARGET_SH5"
3537   "
3538 {
3539   if (TARGET_SHMEDIA)
3540     {
3541       emit_insn (gen_ic_invalidate_line_media (operands[0]));
3542       DONE;
3543     }
3544   else if (TARGET_SHCOMPACT)
3545     {
3546       operands[1] = gen_rtx_SYMBOL_REF (Pmode, \"__ic_invalidate\");
3547       operands[1] = force_reg (Pmode, operands[1]);
3548       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
3549       DONE;
3550     }
3551   operands[0] = force_reg (Pmode, operands[0]);
3552   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
3553                                                                Pmode)));
3554 }")
3555
3556 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
3557 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
3558 ;; the requirement *1*00 for associative address writes.  The alignment of
3559 ;; %0 implies that its least significant bit is cleared,
3560 ;; thus we clear the V bit of a matching entry if there is one.
3561 (define_insn "ic_invalidate_line_i"
3562   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
3563                      (match_operand:SI 1 "register_operand" "r")]
3564                      UNSPEC_ICACHE)
3565    (clobber (match_scratch:SI 2 "=&r"))]
3566   "TARGET_HARD_SH4"
3567   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
3568   [(set_attr "length" "8")
3569    (set_attr "type" "cwb")])
3570
3571 ;; ??? could make arg 0 an offsettable memory operand to allow to save
3572 ;; an add in the code that calculates the address.
3573 (define_insn "ic_invalidate_line_media"
3574   [(unspec_volatile [(match_operand 0 "register_operand" "r")]
3575                     UNSPEC_ICACHE)]
3576   "TARGET_SHMEDIA"
3577   "ocbwb        %0,0\;synco\;icbi       %0, 0\;synci"
3578   [(set_attr "length" "16")
3579    (set_attr "type" "invalidate_line_media")])
3580
3581 (define_insn "ic_invalidate_line_compact"
3582   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
3583                      (match_operand:SI 1 "register_operand" "r")]
3584                     UNSPEC_ICACHE)
3585    (clobber (reg:SI PR_REG))]
3586   "TARGET_SHCOMPACT"
3587   "jsr @%1%#"
3588   [(set_attr "type" "sfunc")
3589    (set_attr "needs_delay_slot" "yes")])
3590
3591 (define_expand "initialize_trampoline"
3592   [(match_operand:SI 0 "" "")
3593    (match_operand:SI 1 "" "")
3594    (match_operand:SI 2 "" "")]
3595   "TARGET_SHCOMPACT"
3596   "
3597 {
3598   rtx sfun, tramp;
3599
3600   tramp = force_reg (Pmode, operands[0]);
3601   sfun = force_reg (Pmode, gen_rtx_SYMBOL_REF (Pmode, \"__init_trampoline\"));
3602   emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
3603   emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
3604
3605   emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
3606   DONE;
3607 }")
3608
3609 (define_insn "initialize_trampoline_compact"
3610   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
3611                      (match_operand:SI 1 "register_operand" "r")
3612                      (reg:SI R2_REG) (reg:SI R3_REG)]
3613                     UNSPEC_INIT_TRAMP)
3614
3615    (clobber (reg:SI PR_REG))]
3616   "TARGET_SHCOMPACT"
3617   "jsr @%1%#"
3618   [(set_attr "type" "sfunc")
3619    (set_attr "needs_delay_slot" "yes")])
3620
3621 (define_insn "movqi_i"
3622   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l")
3623         (match_operand:QI 1 "general_movsrc_operand"  "ri,m,r,t,l,r"))]
3624   "TARGET_SH1
3625    && (arith_reg_operand (operands[0], QImode)
3626        || arith_reg_operand (operands[1], QImode))"
3627   "@
3628         mov     %1,%0
3629         mov.b   %1,%0
3630         mov.b   %1,%0
3631         movt    %0
3632         sts     %1,%0
3633         lds     %1,%0"
3634  [(set_attr "type" "move,load,store,move,move,move")])
3635
3636 (define_insn "*movqi_media"
3637   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
3638         (match_operand:QI 1 "general_movsrc_operand" "r,JS,m,r"))]
3639   "TARGET_SHMEDIA
3640    && (arith_reg_operand (operands[0], QImode)
3641        || arith_reg_operand (operands[1], QImode))"
3642   "@
3643         add.l   %1, r63, %0
3644         movi    %1, %0
3645         ld%M1.ub        %m1, %0
3646         st%M0.b %m0, %1"
3647   [(set_attr "type" "arith_media,arith_media,load_media,store_media")])
3648
3649 (define_expand "movqi"
3650   [(set (match_operand:QI 0 "general_operand" "")
3651         (match_operand:QI 1 "general_operand"  ""))]
3652   ""
3653   "{ if (prepare_move_operands (operands, QImode)) DONE; }")
3654
3655 (define_expand "reload_inqi"
3656   [(set (match_operand:SI 2 "" "=&r")
3657         (match_operand:QI 1 "inqhi_operand" ""))
3658    (set (match_operand:QI 0 "arith_reg_operand" "=r")
3659         (truncate:HI (match_dup 3)))]
3660   "TARGET_SHMEDIA"
3661   "
3662 {
3663   rtx inner = XEXP (operands[1], 0);
3664   int regno = REGNO (inner);
3665
3666   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
3667   operands[1] = gen_rtx_REG (SImode, regno);
3668   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
3669 }")
3670
3671 (define_insn "movhi_i"
3672   [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r")
3673         (match_operand:HI 1 "general_movsrc_operand" "Q,rI,m,t,r,l,r,i"))]
3674   "TARGET_SH1
3675    && (arith_reg_operand (operands[0], HImode)
3676        || arith_reg_operand (operands[1], HImode))"
3677   "@
3678         mov.w   %1,%0
3679         mov     %1,%0
3680         mov.w   %1,%0
3681         movt    %0
3682         mov.w   %1,%0
3683         sts     %1,%0
3684         lds     %1,%0
3685         fake    %1,%0"
3686   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
3687
3688 (define_insn "*movhi_media"
3689   [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
3690         (match_operand:HI 1 "general_movsrc_operand" "r,JS,n,m,r"))]
3691   "TARGET_SHMEDIA
3692    && (arith_reg_operand (operands[0], HImode)
3693        || arith_reg_operand (operands[1], HImode))"
3694   "@
3695         add.l   %1, r63, %0
3696         movi    %1, %0
3697         #
3698         ld%M1.w %m1, %0
3699         st%M0.w %m0, %1"
3700   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")])
3701
3702 (define_split
3703   [(set (match_operand:HI 0 "register_operand" "")
3704         (match_operand:HI 1 "immediate_operand" ""))]
3705   "TARGET_SHMEDIA && reload_completed
3706    && ! CONST_OK_FOR_J (INTVAL (operands[1]))"
3707   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3708
3709 (define_expand "movhi"
3710   [(set (match_operand:HI 0 "general_movdst_operand" "")
3711         (match_operand:HI 1 "general_movsrc_operand"  ""))]
3712   ""
3713   "{ if (prepare_move_operands (operands, HImode)) DONE; }")
3714
3715 (define_expand "reload_inhi"
3716   [(set (match_operand:SI 2 "" "=&r")
3717         (match_operand:HI 1 "inqhi_operand" ""))
3718    (set (match_operand:HI 0 "arith_reg_operand" "=r")
3719         (truncate:HI (match_dup 3)))]
3720   "TARGET_SHMEDIA"
3721   "
3722 {
3723   rtx inner = XEXP (operands[1], 0);
3724   int regno = REGNO (inner);
3725
3726   regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
3727   operands[1] = gen_rtx_REG (SImode, regno);
3728   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
3729 }")
3730
3731 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
3732 ;; compiled with -m2 -ml -O3 -funroll-loops
3733 (define_insn "*movdi_i"
3734   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
3735         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I,i,x,r"))]
3736   "TARGET_SH1
3737    && (arith_reg_operand (operands[0], DImode)
3738        || arith_reg_operand (operands[1], DImode))"
3739   "* return output_movedouble (insn, operands, DImode);"
3740   [(set_attr "length" "4")
3741    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
3742
3743 ;; If the output is a register and the input is memory or a register, we have
3744 ;; to be careful and see which word needs to be loaded first.
3745
3746 (define_split
3747   [(set (match_operand:DI 0 "general_movdst_operand" "")
3748         (match_operand:DI 1 "general_movsrc_operand" ""))]
3749   "TARGET_SH1 && reload_completed"
3750   [(set (match_dup 2) (match_dup 3))
3751    (set (match_dup 4) (match_dup 5))]
3752   "
3753 {
3754   int regno;
3755
3756   if ((GET_CODE (operands[0]) == MEM
3757        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
3758       || (GET_CODE (operands[1]) == MEM
3759           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
3760     FAIL;
3761
3762   if (GET_CODE (operands[0]) == REG)
3763     regno = REGNO (operands[0]);
3764   else if (GET_CODE (operands[0]) == SUBREG)
3765     regno = subreg_regno (operands[0]);
3766   else if (GET_CODE (operands[0]) == MEM)
3767     regno = -1;
3768   else
3769     abort ();
3770
3771   if (regno == -1
3772       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
3773     {
3774       operands[2] = operand_subword (operands[0], 0, 0, DImode);
3775       operands[3] = operand_subword (operands[1], 0, 0, DImode);
3776       operands[4] = operand_subword (operands[0], 1, 0, DImode);
3777       operands[5] = operand_subword (operands[1], 1, 0, DImode);
3778     }
3779   else
3780     {
3781       operands[2] = operand_subword (operands[0], 1, 0, DImode);
3782       operands[3] = operand_subword (operands[1], 1, 0, DImode);
3783       operands[4] = operand_subword (operands[0], 0, 0, DImode);
3784       operands[5] = operand_subword (operands[1], 0, 0, DImode);
3785     }
3786
3787   if (operands[2] == 0 || operands[3] == 0
3788       || operands[4] == 0 || operands[5] == 0)
3789     FAIL;
3790 }")
3791
3792 (define_insn "*movdi_media"
3793   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,f,m,f,r,f,*b,r,b")
3794         (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,m,f,rU,f,f,r,*b,T"))]
3795   "TARGET_SHMEDIA_FPU
3796    && (register_operand (operands[0], DImode)
3797        || register_operand (operands[1], DImode))"
3798   "@
3799         add     %1, r63, %0
3800         movi    %1, %0
3801         #
3802         ld%M1.q %m1, %0
3803         st%M0.q %m0, %1
3804         fld%M1.d        %m1, %0
3805         fst%M0.d        %m0, %1
3806         fmov.qd %N1, %0
3807         fmov.dq %1, %0
3808         fmov.d  %1, %0
3809         ptabs   %1, %0
3810         gettr   %1, %0
3811         pt      %1, %0"
3812   [(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")
3813    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
3814
3815 (define_insn "*movdi_media_nofpu"
3816   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,b")
3817         (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,r,*b,T"))]
3818   "TARGET_SHMEDIA
3819    && (register_operand (operands[0], DImode)
3820        || register_operand (operands[1], DImode))"
3821   "@
3822         add     %1, r63, %0
3823         movi    %1, %0
3824         #
3825         ld%M1.q %m1, %0
3826         st%M0.q %m0, %1
3827         ptabs   %1, %0
3828         gettr   %1, %0
3829         pt      %1, %0"
3830   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
3831    (set_attr "length" "4,4,16,4,4,4,4,*")])
3832
3833 (define_split
3834   [(set (match_operand:DI 0 "arith_reg_operand" "")
3835         (match_operand:DI 1 "immediate_operand" ""))]
3836   "TARGET_SHMEDIA && reload_completed
3837    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3838   [(set (match_dup 0) (match_dup 1))]
3839   "
3840 {
3841   rtx insn;
3842
3843   if (TARGET_SHMEDIA64)
3844     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
3845   else
3846     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
3847
3848   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
3849                                         REG_NOTES (insn));
3850
3851   DONE;
3852 }")
3853
3854 (define_expand "movdi_const"
3855   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3856         (const:DI (sign_extend:DI
3857                    (truncate:HI
3858                     (ashiftrt:DI
3859                      (match_operand:DI 1 "immediate_operand" "s")
3860                      (const_int 48))))))
3861    (set (match_dup 0)
3862         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3863                 (zero_extend:DI
3864                  (truncate:HI
3865                   (const:DI
3866                    (sign_extend:DI
3867                     (truncate:HI
3868                      (ashiftrt:SI
3869                       (match_dup 1)
3870                       (const_int 32)))))))))
3871    (set (match_dup 0)
3872         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3873                 (zero_extend:DI
3874                  (truncate:HI
3875                   (const:DI
3876                    (sign_extend:DI
3877                     (truncate:HI
3878                      (ashiftrt:SI
3879                       (match_dup 1)
3880                       (const_int 16)))))))))
3881    (set (match_dup 0)
3882         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3883                 (zero_extend:DI
3884                  (truncate:HI
3885                   (const:DI
3886                    (sign_extend:DI
3887                     (truncate:HI
3888                      (match_dup 1))))))))]
3889   "TARGET_SHMEDIA64 && reload_completed
3890    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3891   "
3892 {
3893   sh_mark_label (operands[1], 4);
3894 }")
3895
3896 (define_expand "movdi_const_32bit"
3897   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3898         (const:DI (sign_extend:DI
3899                    (truncate:HI
3900                     (ashiftrt:DI
3901                      (match_operand:DI 1 "immediate_operand" "s")
3902                      (const_int 16))))))
3903    (set (match_dup 0)
3904         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3905                 (zero_extend:DI
3906                  (truncate:HI
3907                   (const:DI
3908                    (sign_extend:DI
3909                     (truncate:HI
3910                      (match_dup 1))))))))]
3911   "TARGET_SHMEDIA32 && reload_completed
3912    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3913   "
3914 {
3915   sh_mark_label (operands[1], 2);
3916 }")
3917
3918 (define_expand "movdi_const_16bit"
3919   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3920         (const:DI (sign_extend:DI
3921                    (truncate:HI
3922                     (match_operand:DI 1 "immediate_operand" "s")))))]
3923   "TARGET_SHMEDIA && flag_pic && reload_completed
3924    && GET_CODE (operands[1]) == SYMBOL_REF"
3925   "")
3926
3927 (define_split
3928   [(set (match_operand:DI 0 "arith_reg_operand" "")
3929         (match_operand:DI 1 "immediate_operand" ""))]
3930   "TARGET_SHMEDIA && reload_completed
3931    && GET_CODE (operands[1]) == CONST_INT
3932    && ! CONST_OK_FOR_J (INTVAL (operands[1]))"
3933   [(set (match_dup 0) (match_dup 2))
3934    (match_dup 1)]
3935   "
3936 {
3937   unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3938   unsigned HOST_WIDE_INT low = val;
3939   unsigned HOST_WIDE_INT high = val;
3940   unsigned HOST_WIDE_INT sign;
3941   unsigned HOST_WIDE_INT val2 = val ^ (val-1);
3942
3943   /* Sign-extend the 16 least-significant bits.  */
3944   low &= 0xffff;
3945   low ^= 0x8000;
3946   low -= 0x8000;
3947
3948   /* Arithmetic shift right the word by 16 bits.  */
3949   high >>= 16;
3950   sign = 1;
3951   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
3952   high ^= sign;
3953   high -= sign;
3954   do
3955     {
3956       /* If we can't generate the constant with a two-insn movi / shori
3957          sequence, try some other strategies.  */
3958       if (! CONST_OK_FOR_J (high))
3959         {
3960           /* Try constant load / left shift.  We know VAL != 0.  */
3961           val2 = val ^ (val-1);
3962           if (val2 > 0x1ffff)
3963             {
3964               int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
3965
3966               if (CONST_OK_FOR_J (val >> trailing_zeroes)
3967                   || (! CONST_OK_FOR_J (high >> 16)
3968                       && CONST_OK_FOR_J (val >> (trailing_zeroes + 16))))
3969                 {
3970                   val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
3971                   operands[1] = gen_ashldi3_media (operands[0], operands[0],
3972                                                    GEN_INT (trailing_zeroes));
3973                   break;
3974                 }
3975             }
3976           /* Try constant load / right shift.  */
3977           val2 = (val >> 15) + 1;
3978           if (val2 == (val2 & -val2))
3979             {
3980               int shift = 49 - exact_log2 (val2);
3981
3982               val2 = trunc_int_for_mode (val << shift, DImode);
3983               if (CONST_OK_FOR_J (val2))
3984                 {
3985                   operands[1] = gen_lshrdi3_media (operands[0], operands[0],
3986                                                    GEN_INT (shift));
3987                   break;
3988                 }
3989             }
3990           /* Try mperm.w .  */
3991           val2 = val & 0xffff;
3992           if ((val >> 16 & 0xffff) == val2
3993               && (val >> 32 & 0xffff) == val2
3994               && (val >> 48 & 0xffff) == val2)
3995             {
3996               val2 = (HOST_WIDE_INT) val >> 48;
3997               operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
3998               operands[1] = gen_mperm_w0 (operands[1], operands[1]);
3999               break;
4000             }
4001           /* Try movi / mshflo.l  */
4002           val2 = (HOST_WIDE_INT) val >> 32;
4003           if (val2 == trunc_int_for_mode (val, SImode))
4004             {
4005               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
4006                                              operands[0]);
4007               break;
4008             }
4009           /* Try movi / mshflo.l w/ r63.  */
4010           val2 = val + ((HOST_WIDE_INT) -1 << 32);
4011           if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_J (val2))
4012             {
4013               operands[1] = gen_mshflo_l_di (operands[0], operands[0],
4014                                              GEN_INT (0));
4015               break;
4016             }
4017         }
4018       val2 = high;
4019       operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
4020     }
4021   while (0);
4022   operands[2] = GEN_INT (val2);
4023 }")
4024
4025 (define_split
4026   [(set (match_operand:DI 0 "arith_reg_operand" "")
4027         (match_operand:DI 1 "immediate_operand" ""))]
4028   "TARGET_SHMEDIA && reload_completed
4029    && GET_CODE (operands[1]) == CONST_DOUBLE"
4030   [(set (match_dup 0) (match_dup 2))
4031   (set (match_dup 0)
4032        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
4033                (zero_extend:DI (truncate:HI (match_dup 1)))))]
4034   "
4035 {
4036   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
4037   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
4038   unsigned HOST_WIDE_INT val = low;
4039   unsigned HOST_WIDE_INT sign;
4040
4041   /* Sign-extend the 16 least-significant bits.  */
4042   val &= 0xffff;
4043   val ^= 0x8000;
4044   val -= 0x8000;
4045   operands[1] = GEN_INT (val);
4046
4047   /* Arithmetic shift right the double-word by 16 bits.  */
4048   low >>= 16;
4049   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
4050   high >>= 16;
4051   sign = 1;
4052   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
4053   high ^= sign;
4054   high -= sign;
4055
4056   /* This will only be true if high is a sign-extension of low, i.e.,
4057      it must be either 0 or (unsigned)-1, and be zero iff the
4058      most-significant bit of low is set.  */
4059   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
4060     operands[2] = GEN_INT (low);
4061   else
4062     operands[2] = immed_double_const (low, high, DImode);
4063 }")
4064
4065 (define_insn "shori_media"
4066   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
4067         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
4068                            (const_int 16))
4069                 (zero_extend:DI
4070                  (truncate:HI
4071                   (match_operand:DI 2 "immediate_operand" "JS,nF")))))]
4072   "TARGET_SHMEDIA"
4073   "@
4074         shori   %u2, %0
4075         #"
4076   [(set_attr "type" "arith_media,*")])
4077
4078 (define_expand "movdi"
4079   [(set (match_operand:DI 0 "general_movdst_operand" "")
4080         (match_operand:DI 1 "general_movsrc_operand" ""))]
4081   ""
4082   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
4083
4084 (define_insn "movdf_media"
4085   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
4086         (match_operand:DF 1 "general_movsrc_operand" "f,rU,f,r,F,m,f,m,r"))]
4087   "TARGET_SHMEDIA_FPU
4088    && (register_operand (operands[0], DFmode)
4089        || register_operand (operands[1], DFmode))"
4090   "@
4091         fmov.d  %1, %0
4092         fmov.qd %N1, %0
4093         fmov.dq %1, %0
4094         add     %1, r63, %0
4095         #
4096         fld%M1.d        %m1, %0
4097         fst%M0.d        %m0, %1
4098         ld%M1.q %m1, %0
4099         st%M0.q %m0, %1"
4100   [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
4101
4102 (define_insn "movdf_media_nofpu"
4103   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
4104         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,r"))]
4105   "TARGET_SHMEDIA
4106    && (register_operand (operands[0], DFmode)
4107        || register_operand (operands[1], DFmode))"
4108   "@
4109         add     %1, r63, %0
4110         #
4111         ld%M1.q %m1, %0
4112         st%M0.q %m0, %1"
4113   [(set_attr "type" "arith_media,*,load_media,store_media")])
4114
4115 (define_split
4116   [(set (match_operand:DF 0 "arith_reg_operand" "")
4117         (match_operand:DF 1 "immediate_operand" ""))]
4118   "TARGET_SHMEDIA && reload_completed"
4119   [(set (match_dup 3) (match_dup 2))]
4120   "
4121 {
4122   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
4123   long values[2];
4124   REAL_VALUE_TYPE value;
4125
4126   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
4127   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
4128
4129   if (HOST_BITS_PER_WIDE_INT >= 64)
4130     operands[2] = immed_double_const ((unsigned long) values[endian]
4131                                       | ((HOST_WIDE_INT) values[1 - endian]
4132                                          << 32), 0, DImode);
4133   else if (HOST_BITS_PER_WIDE_INT == 32)
4134     operands[2] = immed_double_const (values[endian], values[1 - endian],
4135                                       DImode);
4136   else
4137     abort ();
4138
4139   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4140 }")
4141
4142 ;; ??? This should be a define expand.
4143
4144 (define_insn "movdf_k"
4145   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
4146         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
4147   "TARGET_SH1
4148    && (! TARGET_SH4 || reload_completed
4149        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
4150        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
4151        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
4152    && (arith_reg_operand (operands[0], DFmode)
4153        || arith_reg_operand (operands[1], DFmode))"
4154   "* return output_movedouble (insn, operands, DFmode);"
4155   [(set_attr "length" "4")
4156    (set_attr "type" "move,pcload,load,store")])
4157
4158 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
4159 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
4160 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
4161 ;; the d/m/c/X alternative, which is split later into single-precision
4162 ;; instructions.  And when not optimizing, no splits are done before fixing
4163 ;; up pcloads, so we need usable length information for that.
4164 (define_insn "movdf_i4"
4165   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
4166         (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
4167    (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
4168    (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
4169   "TARGET_SH4
4170    && (arith_reg_operand (operands[0], DFmode)
4171        || arith_reg_operand (operands[1], DFmode))"
4172   "@
4173         fmov    %1,%0
4174         #
4175         #
4176         fmov.d  %1,%0
4177         fmov.d  %1,%0
4178         #
4179         #
4180         #
4181         #
4182         #"
4183   [(set_attr_alternative "length"
4184      [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
4185       (const_int 4)
4186       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
4187       (if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 6))
4188       (if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 6))
4189       (const_int 4)
4190       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
4191       ;; We can't use 4-byte push/pop on SHcompact, so we have to
4192       ;; increment or decrement r15 explicitly.
4193       (if_then_else
4194        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
4195        (const_int 10) (const_int 8))
4196       (if_then_else
4197        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
4198        (const_int 10) (const_int 8))])
4199    (set_attr "type" "fmove,move,pcfload,fload,store,pcload,load,store,load,fload")
4200    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
4201    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
4202                                            (const_string "double")
4203                                            (const_string "none")))])
4204
4205 ;; Moving DFmode between fp/general registers through memory
4206 ;; (the top of the stack) is faster than moving through fpul even for
4207 ;; little endian.  Because the type of an instruction is important for its
4208 ;; scheduling,  it is beneficial to split these operations, rather than
4209 ;; emitting them in one single chunk, even if this will expose a stack
4210 ;; use that will prevent scheduling of other stack accesses beyond this
4211 ;; instruction.
4212 (define_split
4213   [(set (match_operand:DF 0 "register_operand" "")
4214         (match_operand:DF 1 "register_operand" ""))
4215    (use (match_operand:PSI 2 "fpscr_operand" ""))
4216    (clobber (match_scratch:SI 3 "=X"))]
4217   "TARGET_SH4 && reload_completed
4218    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
4219   [(const_int 0)]
4220   "
4221 {
4222   rtx insn, tos;
4223
4224   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
4225     {
4226       emit_move_insn (stack_pointer_rtx,
4227                       plus_constant (stack_pointer_rtx, -8));
4228       tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
4229     }
4230   else
4231     tos = gen_rtx (MEM, DFmode, gen_rtx (PRE_DEC, Pmode, stack_pointer_rtx));
4232   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
4233   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
4234     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
4235   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
4236     tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
4237   else
4238     tos = gen_rtx (MEM, DFmode, gen_rtx (POST_INC, Pmode, stack_pointer_rtx));
4239   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
4240   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
4241     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
4242   else
4243     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
4244   DONE;
4245 }")
4246
4247 ;; local-alloc sometimes allocates scratch registers even when not required,
4248 ;; so we must be prepared to handle these.
4249
4250 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
4251 (define_split
4252   [(set (match_operand:DF 0 "general_movdst_operand" "")
4253         (match_operand:DF 1 "general_movsrc_operand"  ""))
4254    (use (match_operand:PSI 2 "fpscr_operand" ""))
4255    (clobber (match_scratch:SI 3 ""))]
4256   "TARGET_SH4
4257    && reload_completed
4258    && true_regnum (operands[0]) < 16
4259    && true_regnum (operands[1]) < 16"
4260   [(set (match_dup 0) (match_dup 1))]
4261   "
4262 {
4263   /* If this was a reg <-> mem operation with base + index reg addressing,
4264      we have to handle this in a special way.  */
4265   rtx mem = operands[0];
4266   int store_p = 1;
4267   if (! memory_operand (mem, DFmode))
4268     {
4269       mem = operands[1];
4270       store_p = 0;
4271     }
4272   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
4273     mem = SUBREG_REG (mem);
4274   if (GET_CODE (mem) == MEM)
4275     {
4276       rtx addr = XEXP (mem, 0);
4277       if (GET_CODE (addr) == PLUS
4278           && GET_CODE (XEXP (addr, 0)) == REG
4279           && GET_CODE (XEXP (addr, 1)) == REG)
4280         {
4281           int offset;
4282           rtx reg0 = gen_rtx (REG, Pmode, 0);
4283           rtx regop = operands[store_p], word0 ,word1;
4284
4285           if (GET_CODE (regop) == SUBREG)
4286             alter_subreg (&regop);
4287           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
4288             offset = 2;
4289           else
4290             offset = 4;
4291           mem = copy_rtx (mem);
4292           PUT_MODE (mem, SImode);
4293           word0 = gen_rtx (SUBREG, SImode, regop, 0);
4294           alter_subreg (&word0);
4295           word1 = gen_rtx (SUBREG, SImode, regop, 4);
4296           alter_subreg (&word1);
4297           if (store_p || ! refers_to_regno_p (REGNO (word0),
4298                                               REGNO (word0) + 1, addr, 0))
4299             {
4300               emit_insn (store_p
4301                          ? gen_movsi_ie (mem, word0)
4302                          : gen_movsi_ie (word0, mem));
4303               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
4304               mem = copy_rtx (mem);
4305               emit_insn (store_p
4306                          ? gen_movsi_ie (mem, word1)
4307                          : gen_movsi_ie (word1, mem));
4308               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
4309             }
4310           else
4311             {
4312               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
4313               emit_insn (gen_movsi_ie (word1, mem));
4314               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
4315               mem = copy_rtx (mem);
4316               emit_insn (gen_movsi_ie (word0, mem));
4317             }
4318           DONE;
4319         }
4320     }
4321 }")
4322
4323 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
4324 (define_split
4325   [(set (match_operand:DF 0 "register_operand" "")
4326         (match_operand:DF 1 "memory_operand"  ""))
4327    (use (match_operand:PSI 2 "fpscr_operand" ""))
4328    (clobber (reg:SI R0_REG))]
4329   "TARGET_SH4 && reload_completed"
4330   [(parallel [(set (match_dup 0) (match_dup 1))
4331               (use (match_dup 2))
4332               (clobber (scratch:SI))])]
4333   "")
4334
4335 (define_expand "reload_indf"
4336   [(parallel [(set (match_operand:DF 0 "register_operand" "=f")
4337                    (match_operand:DF 1 "immediate_operand" "FQ"))
4338               (use (reg:PSI FPSCR_REG))
4339               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4340   "TARGET_SH1"
4341   "")
4342
4343 (define_expand "reload_outdf"
4344   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
4345                    (match_operand:DF 1 "register_operand" "af,r"))
4346               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
4347   "TARGET_SH1"
4348   "")
4349
4350 ;; Simplify no-op moves.
4351 (define_split
4352   [(set (match_operand:SF 0 "register_operand" "")
4353         (match_operand:SF 1 "register_operand" ""))
4354    (use (match_operand:PSI 2 "fpscr_operand" ""))
4355    (clobber (match_scratch:SI 3 "X"))]
4356   "TARGET_SH3E && reload_completed
4357    && true_regnum (operands[0]) == true_regnum (operands[1])"
4358   [(set (match_dup 0) (match_dup 0))]
4359   "")
4360
4361 ;; fmovd substitute post-reload splits
4362 (define_split
4363   [(set (match_operand:DF 0 "register_operand" "")
4364         (match_operand:DF 1 "register_operand" ""))
4365    (use (match_operand:PSI 2 "fpscr_operand" ""))
4366    (clobber (match_scratch:SI 3 "X"))]
4367   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4368    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
4369    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
4370   [(const_int 0)]
4371   "
4372 {
4373   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
4374   emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, dst),
4375                            gen_rtx (REG, SFmode, src), operands[2]));
4376   emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, dst + 1),
4377                            gen_rtx (REG, SFmode, src + 1), operands[2]));
4378   DONE;
4379 }")
4380
4381 (define_split
4382   [(set (match_operand:DF 0 "register_operand" "")
4383         (mem:DF (match_operand:SI 1 "register_operand" "")))
4384    (use (match_operand:PSI 2 "fpscr_operand" ""))
4385    (clobber (match_scratch:SI 3 ""))]
4386   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4387    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
4388    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
4389   [(const_int 0)]
4390   "
4391 {
4392   int regno = true_regnum (operands[0]);
4393   rtx insn;
4394   rtx mem2 = gen_rtx (MEM, SFmode, gen_rtx (POST_INC, Pmode, operands[1]));
4395
4396   insn = emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode,
4397                                            regno + !! TARGET_LITTLE_ENDIAN),
4398                                   mem2, operands[2]));
4399   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[1], NULL_RTX);
4400   insn = emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode,
4401                                            regno + ! TARGET_LITTLE_ENDIAN),
4402                                   gen_rtx (MEM, SFmode, operands[1]),
4403                                   operands[2]));
4404   DONE;
4405 }")
4406
4407 (define_split
4408   [(set (match_operand:DF 0 "register_operand" "")
4409         (match_operand:DF 1 "memory_operand" ""))
4410    (use (match_operand:PSI 2 "fpscr_operand" ""))
4411    (clobber (match_scratch:SI 3 ""))]
4412   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4413    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
4414   [(const_int 0)]
4415   "
4416 {
4417   int regno = true_regnum (operands[0]);
4418   rtx addr, insn, adjust = NULL_RTX;
4419   rtx mem2 = copy_rtx (operands[1]);
4420   rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
4421   rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
4422
4423   PUT_MODE (mem2, SFmode);
4424   operands[1] = copy_rtx (mem2);
4425   addr = XEXP (mem2, 0);
4426   if (GET_CODE (addr) != POST_INC)
4427     {
4428       /* If we have to modify the stack pointer, the value that we have
4429          read with post-increment might be modified by an interrupt,
4430          so write it back.  */
4431       if (REGNO (addr) == STACK_POINTER_REGNUM)
4432         adjust = gen_push_e (reg0);
4433       else
4434         adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
4435       XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
4436     }
4437   addr = XEXP (addr, 0);
4438   insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
4439   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4440   insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
4441   if (adjust)
4442     emit_insn (adjust);
4443   else
4444     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
4445   DONE;
4446 }")
4447
4448 (define_split
4449   [(set (match_operand:DF 0 "memory_operand" "")
4450         (match_operand:DF 1 "register_operand" ""))
4451    (use (match_operand:PSI 2 "fpscr_operand" ""))
4452    (clobber (match_scratch:SI 3 ""))]
4453   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
4454    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
4455   [(const_int 0)]
4456   "
4457 {
4458   int regno = true_regnum (operands[1]);
4459   rtx insn, addr, adjust = NULL_RTX;
4460
4461   operands[0] = copy_rtx (operands[0]);
4462   PUT_MODE (operands[0], SFmode);
4463   insn = emit_insn (gen_movsf_ie (operands[0],
4464                                   gen_rtx (REG, SFmode,
4465                                            regno + ! TARGET_LITTLE_ENDIAN),
4466                                   operands[2]));
4467   operands[0] = copy_rtx (operands[0]);
4468   addr = XEXP (operands[0], 0);
4469   if (GET_CODE (addr) != PRE_DEC)
4470     {
4471       adjust = gen_addsi3 (addr, addr, GEN_INT (4));
4472       emit_insn_before (adjust, insn);
4473       XEXP (operands[0], 0) = addr = gen_rtx (PRE_DEC, SImode, addr);
4474     }
4475   addr = XEXP (addr, 0);
4476   if (! adjust)
4477     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, addr, NULL_RTX);
4478   insn = emit_insn (gen_movsf_ie (operands[0],
4479                                   gen_rtx (REG, SFmode,
4480                                            regno + !! TARGET_LITTLE_ENDIAN),
4481                                   operands[2]));
4482   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, addr, NULL_RTX);
4483   DONE;
4484 }")
4485
4486 ;; If the output is a register and the input is memory or a register, we have
4487 ;; to be careful and see which word needs to be loaded first.
4488
4489 (define_split
4490   [(set (match_operand:DF 0 "general_movdst_operand" "")
4491         (match_operand:DF 1 "general_movsrc_operand" ""))]
4492   "TARGET_SH1 && reload_completed"
4493   [(set (match_dup 2) (match_dup 3))
4494    (set (match_dup 4) (match_dup 5))]
4495   "
4496 {
4497   int regno;
4498
4499   if ((GET_CODE (operands[0]) == MEM
4500        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
4501       || (GET_CODE (operands[1]) == MEM
4502           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
4503     FAIL;
4504
4505   if (GET_CODE (operands[0]) == REG)
4506     regno = REGNO (operands[0]);
4507   else if (GET_CODE (operands[0]) == SUBREG)
4508     regno = subreg_regno (operands[0]);
4509   else if (GET_CODE (operands[0]) == MEM)
4510     regno = -1;
4511   else
4512     abort ();
4513
4514   if (regno == -1
4515       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
4516     {
4517       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
4518       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
4519       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
4520       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
4521     }
4522   else
4523     {
4524       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
4525       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
4526       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
4527       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
4528     }
4529
4530   if (operands[2] == 0 || operands[3] == 0
4531       || operands[4] == 0 || operands[5] == 0)
4532     FAIL;
4533 }")
4534
4535 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
4536 ;; used only once, let combine add in the index again.
4537
4538 (define_split
4539   [(set (match_operand:SI 0 "register_operand" "")
4540         (match_operand:SI 1 "" ""))
4541    (clobber (match_operand 2 "register_operand" ""))]
4542   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4543   [(use (reg:SI R0_REG))]
4544   "
4545 {
4546   rtx addr, reg, const_int;
4547
4548   if (GET_CODE (operands[1]) != MEM)
4549     FAIL;
4550   addr = XEXP (operands[1], 0);
4551   if (GET_CODE (addr) != PLUS)
4552     FAIL;
4553   reg = XEXP (addr, 0);
4554   const_int = XEXP (addr, 1);
4555   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4556          && GET_CODE (const_int) == CONST_INT))
4557     FAIL;
4558   emit_move_insn (operands[2], const_int);
4559   emit_move_insn (operands[0],
4560                   change_address (operands[1], VOIDmode,
4561                                   gen_rtx_PLUS (SImode, reg, operands[2])));
4562   DONE;
4563 }")
4564
4565 (define_split
4566   [(set (match_operand:SI 1 "" "")
4567         (match_operand:SI 0 "register_operand" ""))
4568    (clobber (match_operand 2 "register_operand" ""))]
4569   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4570   [(use (reg:SI R0_REG))]
4571   "
4572 {
4573   rtx addr, reg, const_int;
4574
4575   if (GET_CODE (operands[1]) != MEM)
4576     FAIL;
4577   addr = XEXP (operands[1], 0);
4578   if (GET_CODE (addr) != PLUS)
4579     FAIL;
4580   reg = XEXP (addr, 0);
4581   const_int = XEXP (addr, 1);
4582   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4583          && GET_CODE (const_int) == CONST_INT))
4584     FAIL;
4585   emit_move_insn (operands[2], const_int);
4586   emit_move_insn (change_address (operands[1], VOIDmode,
4587                                   gen_rtx_PLUS (SImode, reg, operands[2])),
4588                   operands[0]);
4589   DONE;
4590 }")
4591
4592 (define_expand "movdf"
4593   [(set (match_operand:DF 0 "general_movdst_operand" "")
4594         (match_operand:DF 1 "general_movsrc_operand" ""))]
4595   ""
4596   "
4597 {
4598   if (prepare_move_operands (operands, DFmode)) DONE;
4599   if (TARGET_SHMEDIA)
4600     {
4601       if (TARGET_SHMEDIA_FPU)
4602         emit_insn (gen_movdf_media (operands[0], operands[1]));
4603       else
4604         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
4605       DONE;
4606     }
4607   if (TARGET_SH4)
4608     {
4609       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
4610       DONE;
4611     }
4612 }")
4613
4614 ;;This is incompatible with the way gcc uses subregs.
4615 ;;(define_insn "movv2sf_i"
4616 ;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
4617 ;;      (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
4618 ;;  "TARGET_SHMEDIA_FPU
4619 ;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
4620 ;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
4621 ;;  "@
4622 ;;      #
4623 ;;      fld%M1.p        %m1, %0
4624 ;;      fst%M0.p        %m0, %1"
4625 ;;  [(set_attr "type" "*,fload_media,fstore_media")])
4626
4627 (define_insn_and_split "movv2sf_i"
4628   [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
4629         (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfU?"))]
4630   "TARGET_SHMEDIA_FPU"
4631   "#"
4632   "TARGET_SHMEDIA_FPU && reload_completed"
4633   [(set (match_dup 0) (match_dup 1))]
4634   "
4635 {
4636   operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
4637   operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
4638 }")
4639
4640 (define_expand "movv2sf"
4641   [(set (match_operand:V2SF 0 "general_movdst_operand" "")
4642         (match_operand:V2SF 1 "nonimmediate_operand" ""))]
4643   "TARGET_SHMEDIA_FPU"
4644   "
4645 {
4646   if (prepare_move_operands (operands, V2SFmode))
4647     DONE;
4648 }")
4649
4650 (define_expand "addv2sf3"
4651   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4652    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4653    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4654   "TARGET_SHMEDIA_FPU"
4655   "
4656 {
4657   sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
4658   DONE;
4659 }")
4660
4661 (define_expand "subv2sf3"
4662   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4663    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4664    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4665   "TARGET_SHMEDIA_FPU"
4666   "
4667 {
4668   sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
4669   DONE;
4670 }")
4671
4672 (define_expand "mulv2sf3"
4673   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4674    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4675    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4676   "TARGET_SHMEDIA_FPU"
4677   "
4678 {
4679   sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
4680   DONE;
4681 }")
4682
4683 (define_expand "divv2sf3"
4684   [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
4685    (match_operand:V2SF 1 "fp_arith_reg_operand" "")
4686    (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
4687   "TARGET_SHMEDIA_FPU"
4688   "
4689 {
4690   sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
4691   DONE;
4692 }")
4693
4694 (define_insn_and_split "*movv4sf_i"
4695   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
4696         (match_operand:V4SF 1 "general_operand" "fU,m,f"))]
4697   "TARGET_SHMEDIA_FPU"
4698   "#"
4699   "&& reload_completed"
4700   [(const_int 0)]
4701   "
4702 {
4703   int i;
4704
4705   for (i = 0; i < 4/2; i++)
4706     {
4707       rtx x, y;
4708
4709       if (GET_CODE (operands[0]) == MEM)
4710         x = gen_rtx_MEM (V2SFmode,
4711                          plus_constant (XEXP (operands[0], 0),
4712                                         i * GET_MODE_SIZE (V2SFmode)));
4713       else
4714         x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
4715
4716       if (GET_CODE (operands[1]) == MEM)
4717         y = gen_rtx_MEM (V2SFmode,
4718                          plus_constant (XEXP (operands[1], 0),
4719                                         i * GET_MODE_SIZE (V2SFmode)));
4720       else
4721         y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
4722
4723       emit_insn (gen_movv2sf_i (x, y));
4724     }
4725
4726   DONE;
4727 }"
4728   [(set_attr "length" "8")])
4729
4730 (define_expand "movv4sf"
4731   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
4732         (match_operand:V4SF 1 "general_operand" ""))]
4733   "TARGET_SHMEDIA_FPU"
4734   "
4735 {
4736   if (prepare_move_operands (operands, V4SFmode))
4737     DONE;
4738 }")
4739
4740 (define_insn_and_split "*movv16sf_i"
4741   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4742         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4743   "TARGET_SHMEDIA_FPU"
4744   "#"
4745   "&& reload_completed"
4746   [(const_int 0)]
4747   "
4748 {
4749   int i;
4750
4751   for (i = 0; i < 16/2; i++)
4752     {
4753       rtx x,y;
4754
4755       if (GET_CODE (operands[0]) == MEM)
4756         x = gen_rtx_MEM (V2SFmode,
4757                          plus_constant (XEXP (operands[0], 0),
4758                                         i * GET_MODE_SIZE (V2SFmode)));
4759       else
4760         {
4761           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 2);
4762           alter_subreg (&x);
4763         }
4764
4765       if (GET_CODE (operands[1]) == MEM)
4766         y = gen_rtx_MEM (V2SFmode,
4767                          plus_constant (XEXP (operands[1], 0),
4768                                         i * GET_MODE_SIZE (V2SFmode)));
4769       else
4770         {
4771           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 2);
4772           alter_subreg (&y);
4773         }
4774
4775       emit_insn (gen_movv2sf_i (x, y));
4776     }
4777
4778   DONE;
4779 }"
4780   [(set_attr "length" "32")])
4781
4782 (define_expand "movv16sf"
4783   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4784         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4785   "TARGET_SHMEDIA_FPU"
4786   "
4787 {
4788   if (prepare_move_operands (operands, V16SFmode))
4789     DONE;
4790 }")
4791
4792 (define_insn "movsf_media"
4793   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
4794         (match_operand:SF 1 "general_movsrc_operand" "f,rU,f,r,F,m,f,m,r"))]
4795   "TARGET_SHMEDIA_FPU
4796    && (register_operand (operands[0], SFmode)
4797        || register_operand (operands[1], SFmode))"
4798   "@
4799         fmov.s  %1, %0
4800         fmov.ls %N1, %0
4801         fmov.sl %1, %0
4802         add.l   %1, r63, %0
4803         #
4804         fld%M1.s        %m1, %0
4805         fst%M0.s        %m0, %1
4806         ld%M1.l %m1, %0
4807         st%M0.l %m0, %1"
4808   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
4809
4810 (define_insn "movsf_media_nofpu"
4811   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
4812         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,r"))]
4813   "TARGET_SHMEDIA
4814    && (register_operand (operands[0], SFmode)
4815        || register_operand (operands[1], SFmode))"
4816   "@
4817         add.l   %1, r63, %0
4818         #
4819         ld%M1.l %m1, %0
4820         st%M0.l %m0, %1"
4821   [(set_attr "type" "arith_media,*,load_media,store_media")])
4822
4823 (define_split
4824   [(set (match_operand:SF 0 "arith_reg_operand" "")
4825         (match_operand:SF 1 "immediate_operand" ""))]
4826   "TARGET_SHMEDIA && reload_completed
4827    && ! FP_REGISTER_P (true_regnum (operands[0]))"
4828   [(set (match_dup 3) (match_dup 2))]
4829   "
4830 {
4831   long values;
4832   REAL_VALUE_TYPE value;
4833
4834   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
4835   REAL_VALUE_TO_TARGET_SINGLE (value, values);
4836   operands[2] = GEN_INT (values);
4837
4838   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4839 }")
4840
4841 (define_insn "movsf_i"
4842   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
4843         (match_operand:SF 1 "general_movsrc_operand"  "r,I,FQ,mr,r,r,l"))]
4844   "TARGET_SH1
4845    && (! TARGET_SH3E
4846        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
4847        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
4848        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
4849    && (arith_reg_operand (operands[0], SFmode)
4850        || arith_reg_operand (operands[1], SFmode))"
4851   "@
4852         mov     %1,%0
4853         mov     %1,%0
4854         mov.l   %1,%0
4855         mov.l   %1,%0
4856         mov.l   %1,%0
4857         lds     %1,%0
4858         sts     %1,%0"
4859   [(set_attr "type" "move,move,pcload,load,store,move,move")])
4860
4861 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
4862 ;; update_flow_info would not know where to put REG_EQUAL notes
4863 ;; when the destination changes mode.
4864 (define_insn "movsf_ie"
4865   [(set (match_operand:SF 0 "general_movdst_operand"
4866          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
4867         (match_operand:SF 1 "general_movsrc_operand"
4868           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
4869    (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"))
4870    (clobber (match_scratch:SI 3 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
4871
4872   "TARGET_SH3E
4873    && (arith_reg_operand (operands[0], SFmode)
4874        || arith_reg_operand (operands[1], SFmode)
4875        || arith_reg_operand (operands[3], SImode)
4876        || (fpul_operand (operands[0], SFmode)
4877            && memory_operand (operands[1], SFmode)
4878            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
4879        || (fpul_operand (operands[1], SFmode)
4880            && memory_operand (operands[0], SFmode)
4881            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
4882   "@
4883         fmov    %1,%0
4884         mov     %1,%0
4885         fldi0   %0
4886         fldi1   %0
4887         #
4888         fmov.s  %1,%0
4889         fmov.s  %1,%0
4890         mov.l   %1,%0
4891         mov.l   %1,%0
4892         mov.l   %1,%0
4893         fsts    fpul,%0
4894         flds    %1,fpul
4895         lds.l   %1,%0
4896         #
4897         sts     %1,%0
4898         lds     %1,%0
4899         sts.l   %1,%0
4900         lds.l   %1,%0
4901         ! move optimized away"
4902   [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,store,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,store,load,nil")
4903    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
4904    (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,4,2,2,2,2,0")
4905    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
4906                                            (const_string "single")
4907                                            (const_string "none")))])
4908
4909 (define_split
4910   [(set (match_operand:SF 0 "register_operand" "")
4911         (match_operand:SF 1 "register_operand" ""))
4912    (use (match_operand:PSI 2 "fpscr_operand" ""))
4913    (clobber (reg:SI FPUL_REG))]
4914   "TARGET_SH1"
4915   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
4916               (use (match_dup 2))
4917               (clobber (scratch:SI))])
4918    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
4919               (use (match_dup 2))
4920               (clobber (scratch:SI))])]
4921   "")
4922
4923 (define_expand "movsf"
4924   [(set (match_operand:SF 0 "general_movdst_operand" "")
4925         (match_operand:SF 1 "general_movsrc_operand" ""))]
4926   ""
4927   "
4928 {
4929   if (prepare_move_operands (operands, SFmode))
4930     DONE;
4931   if (TARGET_SHMEDIA)
4932     {
4933       if (TARGET_SHMEDIA_FPU)
4934         emit_insn (gen_movsf_media (operands[0], operands[1]));
4935       else
4936         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
4937       DONE;
4938     }
4939   if (TARGET_SH3E)
4940     {
4941       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
4942       DONE;
4943     }
4944 }")
4945
4946 (define_insn "mov_nop"
4947   [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
4948   "TARGET_SH3E"
4949   ""
4950   [(set_attr "length" "0")
4951    (set_attr "type" "nil")])
4952
4953 (define_expand "reload_insf"
4954   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
4955                    (match_operand:SF 1 "immediate_operand" "FQ"))
4956               (use (reg:PSI FPSCR_REG))
4957               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4958   "TARGET_SH1"
4959   "")
4960
4961 (define_expand "reload_insi"
4962   [(parallel [(set (match_operand:SF 0 "register_operand" "=y")
4963                    (match_operand:SF 1 "immediate_operand" "FQ"))
4964               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4965   "TARGET_SH1"
4966   "")
4967
4968 (define_insn "*movsi_y"
4969   [(set (match_operand:SI 0 "register_operand" "=y,y")
4970         (match_operand:SI 1 "immediate_operand" "Qi,I"))
4971    (clobber (match_scratch:SI 2 "=&z,r"))]
4972   "TARGET_SH3E
4973    && (reload_in_progress || reload_completed)"
4974   "#"
4975   [(set_attr "length" "4")
4976    (set_attr "type" "pcload,move")])
4977
4978 (define_split
4979   [(set (match_operand:SI 0 "register_operand" "")
4980         (match_operand:SI 1 "immediate_operand" ""))
4981    (clobber (match_operand:SI 2 "register_operand" ""))]
4982   "TARGET_SH1"
4983   [(set (match_dup 2) (match_dup 1))
4984    (set (match_dup 0) (match_dup 2))]
4985   "")
4986
4987 (define_split
4988   [(set (match_operand:SI 0 "register_operand" "")
4989         (match_operand:SI 1 "memory_operand" ""))
4990    (clobber (reg:SI R0_REG))]
4991   "TARGET_SH1"
4992   [(set (match_dup 0) (match_dup 1))]
4993   "")
4994 \f
4995 ;; ------------------------------------------------------------------------
4996 ;; Define the real conditional branch instructions.
4997 ;; ------------------------------------------------------------------------
4998
4999 (define_insn "branch_true"
5000   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
5001                            (label_ref (match_operand 0 "" ""))
5002                            (pc)))]
5003   "TARGET_SH1"
5004   "* return output_branch (1, insn, operands);"
5005   [(set_attr "type" "cbranch")])
5006
5007 (define_insn "branch_false"
5008   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
5009                            (label_ref (match_operand 0 "" ""))
5010                            (pc)))]
5011   "TARGET_SH1"
5012   "* return output_branch (0, insn, operands);"
5013   [(set_attr "type" "cbranch")])
5014
5015 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
5016 ;; which destination is too far away.
5017 ;; The const_int_operand is distinct for each branch target; it avoids
5018 ;; unwanted matches with redundant_insn.
5019 (define_insn "block_branch_redirect"
5020   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
5021   "TARGET_SH1"
5022   ""
5023   [(set_attr "length" "0")])
5024
5025 ;; This one has the additional purpose to record a possible scratch register
5026 ;; for the following branch.
5027 (define_insn "indirect_jump_scratch"
5028   [(set (match_operand:SI 0 "register_operand" "=r")
5029         (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))]
5030   "TARGET_SH1"
5031   ""
5032   [(set_attr "length" "0")])
5033
5034 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
5035 ;; being pulled into the delay slot of a condbranch that has been made to
5036 ;; jump around the unconditional jump because it was out of range.
5037 (define_insn "stuff_delay_slot"
5038   [(set (pc)
5039         (unspec [(match_operand 0 "const_int_operand" "") (pc)] UNSPEC_BBR))
5040    (set (reg:SI T_REG) (match_operand 1 "const_int_operand" ""))]
5041   "TARGET_SH1"
5042   ""
5043   [(set_attr "length" "0")
5044    (set_attr "cond_delay_slot" "yes")])
5045 \f
5046 ;; Conditional branch insns
5047
5048 (define_expand "beq_media"
5049   [(set (pc)
5050         (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
5051                           (match_operand:DI 2 "arith_operand" "r,O"))
5052                       (label_ref:DI (match_operand 0 "" ""))
5053                       (pc)))]
5054   "TARGET_SHMEDIA"
5055   "")
5056
5057 (define_insn "*beq_media_i"
5058   [(set (pc)
5059         (if_then_else (match_operator 3 "equality_comparison_operator"
5060                         [(match_operand:DI 1 "arith_reg_operand" "r,r")
5061                          (match_operand:DI 2 "arith_operand" "r,O")])
5062                       (match_operand:DI 0 "target_operand" "b,b")
5063                       (pc)))]
5064   "TARGET_SHMEDIA"
5065   "@
5066         b%o3%'  %1, %2, %0
5067         b%o3i%' %1, %2, %0"
5068   [(set_attr "type" "cbranch_media")])
5069
5070 (define_expand "bne_media"
5071   [(set (pc)
5072         (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
5073                           (match_operand:DI 2 "arith_operand" "r,O"))
5074                       (label_ref:DI (match_operand 0 "" ""))
5075                       (pc)))]
5076   "TARGET_SHMEDIA"
5077   "")
5078
5079 (define_expand "bgt_media"
5080   [(set (pc)
5081         (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5082                           (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5083                       (label_ref:DI (match_operand 0 "" ""))
5084                       (pc)))]
5085   "TARGET_SHMEDIA"
5086   "")
5087
5088 (define_expand "bge_media"
5089   [(set (pc)
5090         (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5091                           (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5092                       (label_ref:DI (match_operand 0 "" ""))
5093                       (pc)))]
5094   "TARGET_SHMEDIA"
5095   "")
5096
5097 (define_expand "bgtu_media"
5098   [(set (pc)
5099         (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5100                            (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5101                       (label_ref:DI (match_operand 0 "" ""))
5102                       (pc)))]
5103   "TARGET_SHMEDIA"
5104   "")
5105
5106 (define_expand "bgeu_media"
5107   [(set (pc)
5108         (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "r")
5109                            (match_operand:DI 2 "arith_reg_or_0_operand" "r"))
5110                       (label_ref:DI (match_operand 0 "" ""))
5111                       (pc)))]
5112   "TARGET_SHMEDIA"
5113   "")
5114
5115 (define_insn "*bgt_media_i"
5116   [(set (pc)
5117         (if_then_else (match_operator 3 "greater_comparison_operator"
5118                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
5119                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
5120                       (match_operand:DI 0 "target_operand" "b")
5121                       (pc)))]
5122   "TARGET_SHMEDIA"
5123   "b%o3%'       %N1, %N2, %0"
5124   [(set_attr "type" "cbranch_media")])
5125
5126 ;; These are only needed to make invert_jump() happy.
5127 (define_insn "*blt_media_i"
5128   [(set (pc)
5129         (if_then_else (match_operator 3 "less_comparison_operator"
5130                         [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
5131                          (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
5132                       (match_operand:DI 0 "target_operand" "b")
5133                       (pc)))]
5134   "TARGET_SHMEDIA"
5135   "b%o3%'       %N2, %N1, %0"
5136   [(set_attr "type" "cbranch_media")])
5137
5138 (define_expand "beq"
5139   [(set (pc)
5140         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5141                       (label_ref (match_operand 0 "" ""))
5142                       (pc)))]
5143   ""
5144   "
5145 {
5146   if (TARGET_SHMEDIA)
5147     {
5148       if (GET_MODE (sh_compare_op0) != DImode)
5149         {
5150           rtx tmp = gen_reg_rtx (DImode);
5151
5152           emit_insn (gen_seq (tmp));
5153           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5154           DONE;
5155         }
5156
5157       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5158       emit_jump_insn (gen_beq_media (operands[0],
5159                                      sh_compare_op0, sh_compare_op1));
5160       DONE;
5161     }
5162
5163   from_compare (operands, EQ);
5164 }")
5165
5166 (define_expand "bne"
5167   [(set (pc)
5168         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5169                       (label_ref (match_operand 0 "" ""))
5170                       (pc)))]
5171   ""
5172   "
5173 {
5174   if (TARGET_SHMEDIA)
5175     {
5176       if (GET_MODE (sh_compare_op0) != DImode)
5177         {
5178           rtx tmp = gen_reg_rtx (DImode);
5179
5180           emit_insn (gen_seq (tmp));
5181           emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
5182           DONE;
5183         }
5184
5185       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5186       emit_jump_insn (gen_bne_media (operands[0],
5187                                      sh_compare_op0, sh_compare_op1));
5188       DONE;
5189     }
5190
5191   from_compare (operands, EQ);
5192 }")
5193
5194 (define_expand "bgt"
5195   [(set (pc)
5196         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5197                       (label_ref (match_operand 0 "" ""))
5198                       (pc)))]
5199   ""
5200   "
5201 {
5202   if (TARGET_SHMEDIA)
5203     {
5204       if (GET_MODE (sh_compare_op0) != DImode)
5205         {
5206           rtx tmp = gen_reg_rtx (DImode);
5207
5208           emit_insn (gen_sgt (tmp));
5209           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5210           DONE;
5211         }
5212
5213       if (sh_compare_op0 != const0_rtx)
5214         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5215       if (sh_compare_op1 != const0_rtx)
5216         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5217       emit_jump_insn (gen_bgt_media (operands[0],
5218                                      sh_compare_op0, sh_compare_op1));
5219       DONE;
5220     }
5221
5222   from_compare (operands, GT);
5223 }")
5224
5225 (define_expand "blt"
5226   [(set (pc)
5227         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5228                       (label_ref (match_operand 0 "" ""))
5229                       (pc)))]
5230   ""
5231   "
5232 {
5233   if (TARGET_SHMEDIA)
5234     {
5235       if (GET_MODE (sh_compare_op0) != DImode)
5236         {
5237           rtx tmp = gen_reg_rtx (DImode);
5238
5239           emit_insn (gen_slt (tmp));
5240           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5241           DONE;
5242         }
5243
5244       if (sh_compare_op0 != const0_rtx)
5245         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5246       if (sh_compare_op1 != const0_rtx)
5247         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5248       emit_jump_insn (gen_bgt_media (operands[0],
5249                                      sh_compare_op1, sh_compare_op0));
5250       DONE;
5251     }
5252
5253   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5254     {
5255       rtx tmp = sh_compare_op0;
5256       sh_compare_op0 = sh_compare_op1;
5257       sh_compare_op1 = tmp;
5258       emit_insn (gen_bgt (operands[0]));
5259       DONE;
5260     }
5261   from_compare (operands, GE);
5262 }")
5263
5264 (define_expand "ble"
5265   [(set (pc)
5266         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5267                       (label_ref (match_operand 0 "" ""))
5268                       (pc)))]
5269   ""
5270   "
5271 {
5272   if (TARGET_SHMEDIA)
5273     {
5274       if (GET_MODE (sh_compare_op0) != DImode)
5275         {
5276           rtx tmp = gen_reg_rtx (DImode);
5277
5278           emit_insn (gen_sle (tmp));
5279           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5280           DONE;
5281         }
5282
5283       if (sh_compare_op0 != const0_rtx)
5284         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5285       if (sh_compare_op1 != const0_rtx)
5286         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5287       emit_jump_insn (gen_bge_media (operands[0],
5288                                      sh_compare_op1, sh_compare_op0));
5289       DONE;
5290     }
5291
5292   if (TARGET_SH3E
5293       && TARGET_IEEE
5294       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5295     {
5296       rtx tmp = sh_compare_op0;
5297       sh_compare_op0 = sh_compare_op1;
5298       sh_compare_op1 = tmp;
5299       emit_insn (gen_bge (operands[0]));
5300       DONE;
5301     }
5302   from_compare (operands, GT);
5303 }")
5304
5305 (define_expand "bge"
5306   [(set (pc)
5307         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5308                       (label_ref (match_operand 0 "" ""))
5309                       (pc)))]
5310   ""
5311   "
5312 {
5313   if (TARGET_SHMEDIA)
5314     {
5315       if (GET_MODE (sh_compare_op0) != DImode)
5316         {
5317           rtx tmp = gen_reg_rtx (DImode);
5318
5319           emit_insn (gen_sge (tmp));
5320           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
5321           DONE;
5322         }
5323
5324       if (sh_compare_op0 != const0_rtx)
5325         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5326       if (sh_compare_op1 != const0_rtx)
5327         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5328       emit_jump_insn (gen_bge_media (operands[0],
5329                                      sh_compare_op0, sh_compare_op1));
5330       DONE;
5331     }
5332
5333   if (TARGET_SH3E
5334       && ! TARGET_IEEE
5335       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
5336     {
5337       rtx tmp = sh_compare_op0;
5338       sh_compare_op0 = sh_compare_op1;
5339       sh_compare_op1 = tmp;
5340       emit_insn (gen_ble (operands[0]));
5341       DONE;
5342     }
5343   from_compare (operands, GE);
5344 }")
5345
5346 (define_expand "bgtu"
5347   [(set (pc)
5348         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5349                       (label_ref (match_operand 0 "" ""))
5350                       (pc)))]
5351   ""
5352   "
5353 {
5354   if (TARGET_SHMEDIA)
5355     {
5356       if (sh_compare_op0 != const0_rtx)
5357         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5358       if (sh_compare_op1 != const0_rtx)
5359         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5360       emit_jump_insn (gen_bgtu_media (operands[0],
5361                                       sh_compare_op0, sh_compare_op1));
5362       DONE;
5363     }
5364
5365   from_compare (operands, GTU);
5366 }")
5367
5368 (define_expand "bltu"
5369   [(set (pc)
5370         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5371                       (label_ref (match_operand 0 "" ""))
5372                       (pc)))]
5373   ""
5374   "
5375 {
5376   if (TARGET_SHMEDIA)
5377     {
5378       if (sh_compare_op0 != const0_rtx)
5379         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5380       if (sh_compare_op1 != const0_rtx)
5381         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5382       emit_jump_insn (gen_bgtu_media (operands[0],
5383                                       sh_compare_op1, sh_compare_op0));
5384       DONE;
5385     }
5386
5387   from_compare (operands, GEU);
5388 }")
5389
5390 (define_expand "bgeu"
5391   [(set (pc)
5392         (if_then_else (ne (reg:SI T_REG) (const_int 0))
5393                       (label_ref (match_operand 0 "" ""))
5394                       (pc)))]
5395   ""
5396   "
5397 {
5398   if (TARGET_SHMEDIA)
5399     {
5400       if (sh_compare_op0 != const0_rtx)
5401         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5402       if (sh_compare_op1 != const0_rtx)
5403         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5404       emit_jump_insn (gen_bgeu_media (operands[0],
5405                                       sh_compare_op0, sh_compare_op1));
5406       DONE;
5407     }
5408
5409   from_compare (operands, GEU);
5410 }")
5411
5412 (define_expand "bleu"
5413   [(set (pc)
5414         (if_then_else (eq (reg:SI T_REG) (const_int 0))
5415                       (label_ref (match_operand 0 "" ""))
5416                       (pc)))]
5417   ""
5418   "
5419 {
5420   if (TARGET_SHMEDIA)
5421     {
5422       if (sh_compare_op0 != const0_rtx)
5423         sh_compare_op0 = force_reg (DImode, sh_compare_op0);
5424       if (sh_compare_op1 != const0_rtx)
5425         sh_compare_op1 = force_reg (DImode, sh_compare_op1);
5426       emit_jump_insn (gen_bgeu_media (operands[0],
5427                                       sh_compare_op1, sh_compare_op0));
5428       DONE;
5429     }
5430
5431   from_compare (operands, GTU);
5432 }")
5433
5434 (define_expand "bunordered"
5435   [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3)))
5436    (set (pc)
5437         (if_then_else (ne (match_dup 1) (const_int 0))
5438                       (label_ref:DI (match_operand 0 "" ""))
5439                       (pc)))]
5440   "TARGET_SHMEDIA"
5441   "
5442 {
5443   operands[1] = gen_reg_rtx (DImode);
5444   operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
5445   operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
5446 }")
5447 \f
5448 ;; ------------------------------------------------------------------------
5449 ;; Jump and linkage insns
5450 ;; ------------------------------------------------------------------------
5451
5452 (define_insn "jump_compact"
5453   [(set (pc)
5454         (label_ref (match_operand 0 "" "")))]
5455   "TARGET_SH1"
5456   "*
5457 {
5458   /* The length is 16 if the delay slot is unfilled.  */
5459   if (get_attr_length(insn) > 4)
5460     return output_far_jump(insn, operands[0]);
5461   else
5462     return   \"bra      %l0%#\";
5463 }"
5464   [(set_attr "type" "jump")
5465    (set_attr "needs_delay_slot" "yes")])
5466
5467 (define_insn "jump_media"
5468   [(set (pc)
5469         (match_operand:DI 0 "target_operand" "b"))]
5470   "TARGET_SHMEDIA"
5471   "blink        %0, r63"
5472   [(set_attr "type" "jump_media")])
5473
5474 (define_expand "jump"
5475   [(set (pc)
5476         (label_ref (match_operand 0 "" "")))]
5477   ""
5478   "
5479 {
5480   if (TARGET_SH1)
5481     emit_jump_insn (gen_jump_compact (operands[0]));
5482   else if (TARGET_SHMEDIA)
5483     {
5484       if (reload_in_progress || reload_completed)
5485         FAIL;
5486       emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (DImode,
5487                                                          operands[0])));
5488     }
5489   DONE;
5490 }")
5491
5492 (define_insn "force_mode_for_call"
5493   [(use (reg:PSI FPSCR_REG))]
5494   "TARGET_SHCOMPACT"
5495   ""
5496   [(set_attr "length" "0")
5497    (set (attr "fp_mode")
5498         (if_then_else (eq_attr "fpu_single" "yes")
5499                       (const_string "single") (const_string "double")))])
5500
5501 (define_insn "calli"
5502   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5503          (match_operand 1 "" ""))
5504    (use (reg:PSI FPSCR_REG))
5505    (clobber (reg:SI PR_REG))]
5506   "TARGET_SH1"
5507   "jsr  @%0%#"
5508   [(set_attr "type" "call")
5509    (set (attr "fp_mode")
5510         (if_then_else (eq_attr "fpu_single" "yes")
5511                       (const_string "single") (const_string "double")))
5512    (set_attr "needs_delay_slot" "yes")])
5513
5514 ;; This is a pc-rel call, using bsrf, for use with PIC.
5515
5516 (define_insn "calli_pcrel"
5517   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5518          (match_operand 1 "" ""))
5519    (use (reg:PSI FPSCR_REG))
5520    (use (reg:SI PIC_REG))
5521    (use (match_operand 2 "" ""))
5522    (clobber (reg:SI PR_REG))]
5523   "TARGET_SH2"
5524   "bsrf %0\\n%O2:%#"
5525   [(set_attr "type" "call")
5526    (set (attr "fp_mode")
5527         (if_then_else (eq_attr "fpu_single" "yes")
5528                       (const_string "single") (const_string "double")))
5529    (set_attr "needs_delay_slot" "yes")])
5530
5531 (define_insn_and_split "call_pcrel"
5532   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
5533          (match_operand 1 "" ""))
5534    (use (reg:PSI FPSCR_REG))
5535    (use (reg:SI PIC_REG))
5536    (clobber (reg:SI PR_REG))
5537    (clobber (match_scratch:SI 2 "=r"))]
5538   "TARGET_SH2"
5539   "#"
5540   "reload_completed"
5541   [(const_int 0)]
5542   "
5543 {
5544   rtx lab = PATTERN (gen_call_site ());
5545
5546   if (SYMBOL_REF_FLAG (operands[0]))
5547     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
5548   else
5549     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
5550   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], lab));
5551   DONE;
5552 }"
5553   [(set_attr "type" "call")
5554    (set (attr "fp_mode")
5555         (if_then_else (eq_attr "fpu_single" "yes")
5556                       (const_string "single") (const_string "double")))
5557    (set_attr "needs_delay_slot" "yes")])
5558
5559 (define_insn "call_compact"
5560   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5561          (match_operand 1 "" ""))
5562    (match_operand 2 "immediate_operand" "n")
5563    (use (reg:SI R0_REG))
5564    (use (reg:SI R1_REG))
5565    (use (reg:PSI FPSCR_REG))
5566    (clobber (reg:SI PR_REG))]
5567   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5568   "jsr  @%0%#"
5569   [(set_attr "type" "call")
5570    (set (attr "fp_mode")
5571         (if_then_else (eq_attr "fpu_single" "yes")
5572                       (const_string "single") (const_string "double")))
5573    (set_attr "needs_delay_slot" "yes")])
5574
5575 (define_insn "call_compact_rettramp"
5576   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5577          (match_operand 1 "" ""))
5578    (match_operand 2 "immediate_operand" "n")
5579    (use (reg:SI R0_REG))
5580    (use (reg:SI R1_REG))
5581    (use (reg:PSI FPSCR_REG))
5582    (clobber (reg:SI R10_REG))
5583    (clobber (reg:SI PR_REG))]
5584   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5585   "jsr  @%0%#"
5586   [(set_attr "type" "call")
5587    (set (attr "fp_mode")
5588         (if_then_else (eq_attr "fpu_single" "yes")
5589                       (const_string "single") (const_string "double")))
5590    (set_attr "needs_delay_slot" "yes")])
5591
5592 (define_insn "call_media"
5593   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "b"))
5594          (match_operand 1 "" ""))
5595    (clobber (reg:DI PR_MEDIA_REG))]
5596   "TARGET_SHMEDIA"
5597   "blink        %0, r18"
5598   [(set_attr "type" "jump_media")])
5599
5600 (define_insn "call_valuei"
5601   [(set (match_operand 0 "" "=rf")
5602         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5603               (match_operand 2 "" "")))
5604    (use (reg:PSI FPSCR_REG))
5605    (clobber (reg:SI PR_REG))]
5606   "TARGET_SH1"
5607   "jsr  @%1%#"
5608   [(set_attr "type" "call")
5609    (set (attr "fp_mode")
5610         (if_then_else (eq_attr "fpu_single" "yes")
5611                       (const_string "single") (const_string "double")))
5612    (set_attr "needs_delay_slot" "yes")])
5613
5614 (define_insn "call_valuei_pcrel"
5615   [(set (match_operand 0 "" "=rf")
5616         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5617               (match_operand 2 "" "")))
5618    (use (reg:PSI FPSCR_REG))
5619    (use (reg:SI PIC_REG))
5620    (use (match_operand 3 "" ""))
5621    (clobber (reg:SI PR_REG))]
5622   "TARGET_SH2"
5623   "bsrf %1\\n%O3:%#"
5624   [(set_attr "type" "call")
5625    (set (attr "fp_mode")
5626         (if_then_else (eq_attr "fpu_single" "yes")
5627                       (const_string "single") (const_string "double")))
5628    (set_attr "needs_delay_slot" "yes")])
5629
5630 (define_insn_and_split "call_value_pcrel"
5631   [(set (match_operand 0 "" "=rf")
5632         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
5633               (match_operand 2 "" "")))
5634    (use (reg:PSI FPSCR_REG))
5635    (use (reg:SI PIC_REG))
5636    (clobber (reg:SI PR_REG))
5637    (clobber (match_scratch:SI 3 "=r"))]
5638   "TARGET_SH2"
5639   "#"
5640   "reload_completed"
5641   [(const_int 0)]
5642   "
5643 {
5644   rtx lab = PATTERN (gen_call_site ());
5645
5646   if (SYMBOL_REF_FLAG (operands[1]))
5647     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
5648   else
5649     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
5650   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
5651                                          operands[2], lab));
5652   DONE;
5653 }"
5654   [(set_attr "type" "call")
5655    (set (attr "fp_mode")
5656         (if_then_else (eq_attr "fpu_single" "yes")
5657                       (const_string "single") (const_string "double")))
5658    (set_attr "needs_delay_slot" "yes")])
5659
5660 (define_insn "call_value_compact"
5661   [(set (match_operand 0 "" "=rf")
5662         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5663               (match_operand 2 "" "")))
5664    (match_operand 3 "immediate_operand" "n")
5665    (use (reg:SI R0_REG))
5666    (use (reg:SI R1_REG))
5667    (use (reg:PSI FPSCR_REG))
5668    (clobber (reg:SI PR_REG))]
5669   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5670   "jsr  @%1%#"
5671   [(set_attr "type" "call")
5672    (set (attr "fp_mode")
5673         (if_then_else (eq_attr "fpu_single" "yes")
5674                       (const_string "single") (const_string "double")))
5675    (set_attr "needs_delay_slot" "yes")])
5676
5677 (define_insn "call_value_compact_rettramp"
5678   [(set (match_operand 0 "" "=rf")
5679         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5680               (match_operand 2 "" "")))
5681    (match_operand 3 "immediate_operand" "n")
5682    (use (reg:SI R0_REG))
5683    (use (reg:SI R1_REG))
5684    (use (reg:PSI FPSCR_REG))
5685    (clobber (reg:SI R10_REG))
5686    (clobber (reg:SI PR_REG))]
5687   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5688   "jsr  @%1%#"
5689   [(set_attr "type" "call")
5690    (set (attr "fp_mode")
5691         (if_then_else (eq_attr "fpu_single" "yes")
5692                       (const_string "single") (const_string "double")))
5693    (set_attr "needs_delay_slot" "yes")])
5694
5695 (define_insn "call_value_media"
5696   [(set (match_operand 0 "" "=rf")
5697         (call (mem:DI (match_operand:DI 1 "target_reg_operand" "b"))
5698               (match_operand 2 "" "")))
5699    (clobber (reg:DI PR_MEDIA_REG))]
5700   "TARGET_SHMEDIA"
5701   "blink        %1, r18"
5702   [(set_attr "type" "jump_media")])
5703
5704 (define_expand "call"
5705   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5706                             (match_operand 1 "" ""))
5707               (match_operand 2 "" "")
5708               (use (reg:PSI FPSCR_REG))
5709               (clobber (reg:SI PR_REG))])]
5710   ""
5711   "
5712 {
5713   if (TARGET_SHMEDIA)
5714     {
5715       operands[0] = XEXP (operands[0], 0);
5716       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
5717         {
5718           if (! SYMBOL_REF_FLAG (operands[0]))
5719             {
5720               rtx reg = gen_reg_rtx (Pmode);
5721
5722               emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5723               operands[0] = reg;
5724             }
5725           else
5726             {
5727               operands[0] = gen_sym2PIC (operands[0]);
5728               PUT_MODE (operands[0], Pmode);
5729             }
5730         }
5731       if (GET_MODE (operands[0]) == SImode)
5732         {
5733           if (GET_CODE (operands[0]) == REG)
5734             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5735           else if (GET_CODE (operands[0]) == SUBREG)
5736             {
5737               operands[0] = SUBREG_REG (operands[0]);
5738               if (GET_MODE (operands[0]) != DImode)
5739                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5740             }
5741           else
5742             {
5743               operands[0] = shallow_copy_rtx (operands[0]);
5744               PUT_MODE (operands[0], DImode);
5745             }
5746         }
5747       if (! target_reg_operand (operands[0], DImode))
5748         operands[0] = copy_to_mode_reg (DImode, operands[0]);
5749       emit_call_insn (gen_call_media (operands[0], operands[1]));
5750       DONE;
5751     }
5752   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
5753     {
5754       rtx cookie_rtx = operands[2];
5755       long cookie = INTVAL (cookie_rtx);
5756       rtx func = XEXP (operands[0], 0);
5757       rtx r0, r1;
5758
5759       if (flag_pic)
5760         {
5761           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5762             {
5763               rtx reg = gen_reg_rtx (Pmode);
5764
5765               emit_insn (gen_symGOTPLT2reg (reg, func));
5766               func = reg;
5767             }
5768           else
5769             func = legitimize_pic_address (func, Pmode, 0);
5770         }
5771
5772       r0 = gen_rtx_REG (SImode, R0_REG);
5773       r1 = gen_rtx_REG (SImode, R1_REG);
5774
5775       /* Since such a call function may use all call-clobbered
5776          registers, we force a mode switch earlier, so that we don't
5777          run out of registers when adjusting fpscr for the call.  */
5778       emit_insn (gen_force_mode_for_call ());
5779
5780       operands[0] = gen_rtx_SYMBOL_REF (SImode,
5781                                         \"__GCC_shcompact_call_trampoline\");
5782       if (flag_pic)
5783         {
5784           rtx reg = gen_reg_rtx (Pmode);
5785
5786           emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5787           operands[0] = reg;
5788         }
5789       operands[0] = force_reg (SImode, operands[0]);
5790
5791       emit_move_insn (r0, func);
5792       emit_move_insn (r1, cookie_rtx);
5793
5794       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5795         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
5796                                                    operands[2]));
5797       else
5798         emit_call_insn (gen_call_compact (operands[0], operands[1],
5799                                           operands[2]));
5800
5801       DONE;
5802     }
5803   else if (TARGET_SHCOMPACT && flag_pic
5804            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
5805            && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
5806     {
5807       rtx reg = gen_reg_rtx (Pmode);
5808
5809       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
5810       XEXP (operands[0], 0) = reg;
5811     }
5812   if (flag_pic && TARGET_SH2
5813       && GET_CODE (operands[0]) == MEM
5814       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
5815     {
5816       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
5817       DONE;
5818     }
5819   else
5820     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
5821
5822   emit_call_insn (gen_calli (operands[0], operands[1]));
5823   DONE;
5824 }")
5825
5826 (define_insn "call_pop_compact"
5827   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5828          (match_operand 1 "" ""))
5829    (match_operand 2 "immediate_operand" "n")
5830    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5831                                  (match_operand 3 "immediate_operand" "n")))
5832    (use (reg:SI R0_REG))
5833    (use (reg:SI R1_REG))
5834    (use (reg:PSI FPSCR_REG))
5835    (clobber (reg:SI PR_REG))]
5836   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5837   "jsr  @%0%#"
5838   [(set_attr "type" "call")
5839    (set (attr "fp_mode")
5840         (if_then_else (eq_attr "fpu_single" "yes")
5841                       (const_string "single") (const_string "double")))
5842    (set_attr "needs_delay_slot" "yes")])
5843
5844 (define_insn "call_pop_compact_rettramp"
5845   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5846          (match_operand 1 "" ""))
5847    (match_operand 2 "immediate_operand" "n")
5848    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5849                                  (match_operand 3 "immediate_operand" "n")))
5850    (use (reg:SI R0_REG))
5851    (use (reg:SI R1_REG))
5852    (use (reg:PSI FPSCR_REG))
5853    (clobber (reg:SI R10_REG))
5854    (clobber (reg:SI PR_REG))]
5855   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5856   "jsr  @%0%#"
5857   [(set_attr "type" "call")
5858    (set (attr "fp_mode")
5859         (if_then_else (eq_attr "fpu_single" "yes")
5860                       (const_string "single") (const_string "double")))
5861    (set_attr "needs_delay_slot" "yes")])
5862
5863 (define_expand "call_pop"
5864   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5865                     (match_operand 1 "" ""))
5866              (match_operand 2 "" "")
5867              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5868                                            (match_operand 3 "" "")))])]
5869   "TARGET_SHCOMPACT"
5870   "
5871 {
5872   if (operands[2] && INTVAL (operands[2]))
5873     {
5874       rtx cookie_rtx = operands[2];
5875       long cookie = INTVAL (cookie_rtx);
5876       rtx func = XEXP (operands[0], 0);
5877       rtx r0, r1;
5878
5879       if (flag_pic)
5880         {
5881           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5882             {
5883               rtx reg = gen_reg_rtx (Pmode);
5884
5885               emit_insn (gen_symGOTPLT2reg (reg, func));
5886               func = reg;
5887             }
5888           else
5889             func = legitimize_pic_address (func, Pmode, 0);
5890         }
5891
5892       r0 = gen_rtx_REG (SImode, R0_REG);
5893       r1 = gen_rtx_REG (SImode, R1_REG);
5894
5895       /* Since such a call function may use all call-clobbered
5896          registers, we force a mode switch earlier, so that we don't
5897          run out of registers when adjusting fpscr for the call.  */
5898       emit_insn (gen_force_mode_for_call ());
5899
5900       operands[0] = gen_rtx_SYMBOL_REF (SImode,
5901                                         \"__GCC_shcompact_call_trampoline\");
5902       if (flag_pic)
5903         {
5904           rtx reg = gen_reg_rtx (Pmode);
5905
5906           emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5907           operands[0] = reg;
5908         }
5909       operands[0] = force_reg (SImode, operands[0]);
5910
5911       emit_move_insn (r0, func);
5912       emit_move_insn (r1, cookie_rtx);
5913
5914       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5915         emit_call_insn (gen_call_pop_compact_rettramp
5916                         (operands[0], operands[1], operands[2], operands[3]));
5917       else
5918         emit_call_insn (gen_call_pop_compact
5919                         (operands[0], operands[1], operands[2], operands[3]));
5920
5921       DONE;
5922     }
5923
5924   abort ();
5925 }")
5926
5927 (define_expand "call_value"
5928   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
5929                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
5930                                  (match_operand 2 "" "")))
5931               (match_operand 3 "" "")
5932               (use (reg:PSI FPSCR_REG))
5933               (clobber (reg:SI PR_REG))])]
5934   ""
5935   "
5936 {
5937   if (TARGET_SHMEDIA)
5938     {
5939       operands[1] = XEXP (operands[1], 0);
5940       if (flag_pic && GET_CODE (operands[1]) == SYMBOL_REF)
5941         {
5942           if (! SYMBOL_REF_FLAG (operands[1]))
5943             {
5944               rtx reg = gen_reg_rtx (Pmode);
5945
5946               emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
5947               operands[1] = reg;
5948             }
5949           else
5950             {
5951               operands[1] = gen_sym2PIC (operands[1]);
5952               PUT_MODE (operands[1], Pmode);
5953             }
5954         }
5955       if (GET_MODE (operands[1]) == SImode)
5956         {
5957           if (GET_CODE (operands[1]) == REG)
5958             operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5959           else if (GET_CODE (operands[1]) == SUBREG)
5960             {
5961               operands[1] = SUBREG_REG (operands[1]);
5962               if (GET_MODE (operands[1]) != DImode)
5963                 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5964             }
5965           else
5966             {
5967               operands[1] = shallow_copy_rtx (operands[1]);
5968               PUT_MODE (operands[1], DImode);
5969             }
5970         }
5971       if (! target_reg_operand (operands[1], DImode))
5972         operands[1] = copy_to_mode_reg (DImode, operands[1]);
5973       emit_call_insn (gen_call_value_media (operands[0], operands[1],
5974                                             operands[2]));
5975       DONE;
5976     }
5977   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
5978     {
5979       rtx cookie_rtx = operands[3];
5980       long cookie = INTVAL (cookie_rtx);
5981       rtx func = XEXP (operands[1], 0);
5982       rtx r0, r1;
5983
5984       if (flag_pic)
5985         {
5986           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5987             {
5988               rtx reg = gen_reg_rtx (Pmode);
5989
5990               emit_insn (gen_symGOTPLT2reg (reg, func));
5991               func = reg;
5992             }
5993           else
5994             func = legitimize_pic_address (func, Pmode, 0);
5995         }
5996
5997       r0 = gen_rtx_REG (SImode, R0_REG);
5998       r1 = gen_rtx_REG (SImode, R1_REG);
5999
6000       /* Since such a call function may use all call-clobbered
6001          registers, we force a mode switch earlier, so that we don't
6002          run out of registers when adjusting fpscr for the call.  */
6003       emit_insn (gen_force_mode_for_call ());
6004
6005       operands[1] = gen_rtx_SYMBOL_REF (SImode,
6006                                         \"__GCC_shcompact_call_trampoline\");
6007       if (flag_pic)
6008         {
6009           rtx reg = gen_reg_rtx (Pmode);
6010
6011           emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6012           operands[1] = reg;
6013         }
6014       operands[1] = force_reg (SImode, operands[1]);
6015
6016       emit_move_insn (r0, func);
6017       emit_move_insn (r1, cookie_rtx);
6018
6019       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6020         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
6021                                                          operands[1],
6022                                                          operands[2],
6023                                                          operands[3]));
6024       else
6025         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
6026                                                 operands[2], operands[3]));
6027
6028       DONE;
6029     }
6030   else if (TARGET_SHCOMPACT && flag_pic
6031            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
6032            && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
6033     {
6034       rtx reg = gen_reg_rtx (Pmode);
6035
6036       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
6037       XEXP (operands[1], 0) = reg;
6038     }
6039   if (flag_pic && TARGET_SH2
6040       && GET_CODE (operands[1]) == MEM
6041       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6042     {
6043       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
6044                                             operands[2]));
6045       DONE;
6046     }
6047   else
6048     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
6049
6050   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
6051   DONE;
6052 }")
6053
6054 (define_insn "sibcalli"
6055   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
6056          (match_operand 1 "" ""))
6057    (use (reg:PSI FPSCR_REG))
6058    (return)]
6059   "TARGET_SH1"
6060   "jmp  @%0%#"
6061   [(set_attr "needs_delay_slot" "yes")
6062    (set (attr "fp_mode")
6063         (if_then_else (eq_attr "fpu_single" "yes")
6064                       (const_string "single") (const_string "double")))
6065    (set_attr "type" "jump_ind")])
6066
6067 (define_insn "sibcalli_pcrel"
6068   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
6069          (match_operand 1 "" ""))
6070    (use (match_operand 2 "" ""))
6071    (use (reg:PSI FPSCR_REG))
6072    (return)]
6073   "TARGET_SH2"
6074   "braf %0\\n%O2:%#"
6075   [(set_attr "needs_delay_slot" "yes")
6076    (set (attr "fp_mode")
6077         (if_then_else (eq_attr "fpu_single" "yes")
6078                       (const_string "single") (const_string "double")))
6079    (set_attr "type" "jump_ind")])
6080
6081 (define_insn_and_split "sibcall_pcrel"
6082   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
6083          (match_operand 1 "" ""))
6084    (use (reg:PSI FPSCR_REG))
6085    (clobber (match_scratch:SI 2 "=k"))
6086    (return)]
6087   "TARGET_SH2"
6088   "#"
6089   "reload_completed"
6090   [(const_int 0)]
6091   "
6092 {
6093   rtx lab = PATTERN (gen_call_site ());
6094   rtx call_insn;
6095
6096   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
6097   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
6098                                                   lab));
6099   SIBLING_CALL_P (call_insn) = 1;
6100   DONE;
6101 }"
6102   [(set_attr "needs_delay_slot" "yes")
6103    (set (attr "fp_mode")
6104         (if_then_else (eq_attr "fpu_single" "yes")
6105                       (const_string "single") (const_string "double")))
6106    (set_attr "type" "jump_ind")])
6107
6108 (define_insn "sibcall_compact"
6109   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
6110          (match_operand 1 "" ""))
6111    (return)
6112    (use (match_operand:SI 2 "register_operand" "z,x"))
6113    (use (reg:SI R1_REG))
6114    (use (reg:PSI FPSCR_REG))
6115    ;; We want to make sure the `x' above will only match MACH_REG
6116    ;; because sibcall_epilogue may clobber MACL_REG.
6117    (clobber (reg:SI MACL_REG))]
6118   "TARGET_SHCOMPACT"
6119   "@
6120         jmp     @%0%#
6121         jmp     @%0\\n  sts     %2, r0"
6122   [(set_attr "needs_delay_slot" "yes,no")
6123    (set_attr "length" "2,4")
6124    (set (attr "fp_mode") (const_string "single"))
6125    (set_attr "type" "jump_ind")])
6126
6127 (define_insn "sibcall_media"
6128   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k"))
6129          (match_operand 1 "" ""))
6130    (return)]
6131   "TARGET_SHMEDIA"
6132   "blink        %0, r63"
6133   [(set_attr "type" "jump_media")])
6134
6135 (define_expand "sibcall"
6136   [(parallel
6137     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
6138            (match_operand 1 "" ""))
6139      (match_operand 2 "" "")
6140      (use (reg:PSI FPSCR_REG))
6141      (return)])]
6142   ""
6143   "
6144 {
6145   if (TARGET_SHMEDIA)
6146     {
6147       operands[0] = XEXP (operands[0], 0);
6148       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
6149         {
6150           if (! SYMBOL_REF_FLAG (operands[0]))
6151             {
6152               rtx reg = gen_reg_rtx (Pmode);
6153
6154               /* We must not use GOTPLT for sibcalls, because PIC_REG
6155                  must be restored before the PLT code gets to run.  */
6156               emit_insn (gen_symGOT2reg (reg, operands[0]));
6157               operands[0] = reg;
6158             }
6159           else
6160             {
6161               operands[0] = gen_sym2PIC (operands[0]);
6162               PUT_MODE (operands[0], Pmode);
6163             }
6164         }
6165       if (GET_MODE (operands[0]) == SImode)
6166         {
6167           if (GET_CODE (operands[0]) == REG)
6168             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6169           else if (GET_CODE (operands[0]) == SUBREG)
6170             {
6171               operands[0] = SUBREG_REG (operands[0]);
6172               if (GET_MODE (operands[0]) != DImode)
6173                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6174             }
6175           else
6176             {
6177               operands[0] = shallow_copy_rtx (operands[0]);
6178               PUT_MODE (operands[0], DImode);
6179             }
6180         }
6181       if (! target_reg_operand (operands[0], DImode))
6182         operands[0] = copy_to_mode_reg (DImode, operands[0]);
6183       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
6184       DONE;
6185     }
6186   else if (TARGET_SHCOMPACT && operands[2]
6187            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
6188     {
6189       rtx cookie_rtx = operands[2];
6190       long cookie = INTVAL (cookie_rtx);
6191       rtx func = XEXP (operands[0], 0);
6192       rtx mach, r1;
6193
6194       if (flag_pic)
6195         {
6196           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
6197             {
6198               rtx reg = gen_reg_rtx (Pmode);
6199
6200               emit_insn (gen_symGOT2reg (reg, func));
6201               func = reg;
6202             }
6203           else
6204             func = legitimize_pic_address (func, Pmode, 0);
6205         }
6206
6207       /* FIXME: if we could tell whether all argument registers are
6208          already taken, we could decide whether to force the use of
6209          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
6210          simple way to tell.  We could use the CALL_COOKIE, but we
6211          can't currently tell a register used for regular argument
6212          passing from one that is unused.  If we leave it up to reload
6213          to decide which register to use, it seems to always choose
6214          R0_REG, which leaves no available registers in SIBCALL_REGS
6215          to hold the address of the trampoline.  */
6216       mach = gen_rtx_REG (SImode, MACH_REG);
6217       r1 = gen_rtx_REG (SImode, R1_REG);
6218
6219       /* Since such a call function may use all call-clobbered
6220          registers, we force a mode switch earlier, so that we don't
6221          run out of registers when adjusting fpscr for the call.  */
6222       emit_insn (gen_force_mode_for_call ());
6223
6224       operands[0] = gen_rtx_SYMBOL_REF (SImode,
6225                                         \"__GCC_shcompact_call_trampoline\");
6226       if (flag_pic)
6227         {
6228           rtx reg = gen_reg_rtx (Pmode);
6229
6230           emit_insn (gen_symGOT2reg (reg, operands[0]));
6231           operands[0] = reg;
6232         }
6233       operands[0] = force_reg (SImode, operands[0]);
6234
6235       /* We don't need a return trampoline, since the callee will
6236          return directly to the upper caller.  */
6237       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6238         {
6239           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
6240           cookie_rtx = GEN_INT (cookie);
6241         }
6242
6243       emit_move_insn (mach, func);
6244       emit_move_insn (r1, cookie_rtx);
6245
6246       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
6247       DONE;
6248     }
6249   else if (TARGET_SHCOMPACT && flag_pic
6250            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
6251            && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
6252     {
6253       rtx reg = gen_reg_rtx (Pmode);
6254
6255       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
6256       XEXP (operands[0], 0) = reg;
6257     }
6258   if (flag_pic && TARGET_SH2
6259       && GET_CODE (operands[0]) == MEM
6260       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
6261       /* The PLT needs the PIC register, but the epilogue would have
6262          to restore it, so we can only use PC-relative PIC calls for
6263          static functions.  */
6264       && SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
6265     {
6266       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
6267       DONE;
6268     }
6269   else
6270     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
6271
6272   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
6273   DONE;
6274 }")
6275
6276 (define_expand "sibcall_value"
6277   [(set (match_operand 0 "" "")
6278         (call (match_operand 1 "" "")
6279               (match_operand 2 "" "")))
6280    (match_operand 3 "" "")]
6281   ""
6282   "
6283 {
6284   emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
6285   DONE;
6286 }")
6287
6288 (define_insn "call_value_pop_compact"
6289   [(set (match_operand 0 "" "=rf")
6290         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
6291               (match_operand 2 "" "")))
6292    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6293                                  (match_operand 4 "immediate_operand" "n")))
6294    (match_operand 3 "immediate_operand" "n")
6295    (use (reg:SI R0_REG))
6296    (use (reg:SI R1_REG))
6297    (use (reg:PSI FPSCR_REG))
6298    (clobber (reg:SI PR_REG))]
6299   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
6300   "jsr  @%1%#"
6301   [(set_attr "type" "call")
6302    (set (attr "fp_mode")
6303         (if_then_else (eq_attr "fpu_single" "yes")
6304                       (const_string "single") (const_string "double")))
6305    (set_attr "needs_delay_slot" "yes")])
6306
6307 (define_insn "call_value_pop_compact_rettramp"
6308   [(set (match_operand 0 "" "=rf")
6309         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
6310               (match_operand 2 "" "")))
6311    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6312                                  (match_operand 4 "immediate_operand" "n")))
6313    (match_operand 3 "immediate_operand" "n")
6314    (use (reg:SI R0_REG))
6315    (use (reg:SI R1_REG))
6316    (use (reg:PSI FPSCR_REG))
6317    (clobber (reg:SI R10_REG))
6318    (clobber (reg:SI PR_REG))]
6319   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
6320   "jsr  @%1%#"
6321   [(set_attr "type" "call")
6322    (set (attr "fp_mode")
6323         (if_then_else (eq_attr "fpu_single" "yes")
6324                       (const_string "single") (const_string "double")))
6325    (set_attr "needs_delay_slot" "yes")])
6326
6327 (define_expand "call_value_pop"
6328   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
6329                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
6330                                  (match_operand 2 "" "")))
6331               (match_operand 3 "" "")
6332               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
6333                                             (match_operand 4 "" "")))])]
6334   "TARGET_SHCOMPACT"
6335   "
6336 {
6337   if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
6338     {
6339       rtx cookie_rtx = operands[3];
6340       long cookie = INTVAL (cookie_rtx);
6341       rtx func = XEXP (operands[1], 0);
6342       rtx r0, r1;
6343
6344       if (flag_pic)
6345         {
6346           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
6347             {
6348               rtx reg = gen_reg_rtx (Pmode);
6349
6350               emit_insn (gen_symGOTPLT2reg (reg, func));
6351               func = reg;
6352             }
6353           else
6354             func = legitimize_pic_address (func, Pmode, 0);
6355         }
6356
6357       r0 = gen_rtx_REG (SImode, R0_REG);
6358       r1 = gen_rtx_REG (SImode, R1_REG);
6359
6360       /* Since such a call function may use all call-clobbered
6361          registers, we force a mode switch earlier, so that we don't
6362          run out of registers when adjusting fpscr for the call.  */
6363       emit_insn (gen_force_mode_for_call ());
6364
6365       operands[1] = gen_rtx_SYMBOL_REF (SImode,
6366                                         \"__GCC_shcompact_call_trampoline\");
6367       if (flag_pic)
6368         {
6369           rtx reg = gen_reg_rtx (Pmode);
6370
6371           emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
6372           operands[1] = reg;
6373         }
6374       operands[1] = force_reg (SImode, operands[1]);
6375
6376       emit_move_insn (r0, func);
6377       emit_move_insn (r1, cookie_rtx);
6378
6379       if (cookie & CALL_COOKIE_RET_TRAMP (1))
6380         emit_call_insn (gen_call_value_pop_compact_rettramp
6381                         (operands[0], operands[1], operands[2],
6382                          operands[3], operands[4]));
6383       else
6384         emit_call_insn (gen_call_value_pop_compact
6385                         (operands[0], operands[1], operands[2],
6386                          operands[3], operands[4]));
6387
6388       DONE;
6389     }
6390
6391   abort ();
6392 }")
6393
6394 (define_expand "sibcall_epilogue"
6395   [(return)]
6396   ""
6397   "
6398 {
6399   sh_expand_epilogue ();
6400   if (TARGET_SHCOMPACT)
6401     {
6402       rtx insn, set;
6403
6404       /* If epilogue clobbers r0, preserve it in macl.  */
6405       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
6406         if ((set = single_set (insn))
6407             && GET_CODE (SET_DEST (set)) == REG
6408             && REGNO (SET_DEST (set)) == R0_REG)
6409           {
6410             rtx r0 = gen_rtx_REG (SImode, R0_REG);
6411             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
6412             rtx i;
6413
6414             /* We can't tell at this point whether the sibcall is a
6415                sibcall_compact and, if it is, whether it uses r0 or
6416                mach as operand 2, so let the instructions that
6417                preserve r0 be optimized away if r0 turns out to be
6418                dead.  */
6419             i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
6420             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
6421                                                REG_NOTES (i));
6422             i = emit_move_insn (r0, tmp);
6423             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
6424                                                REG_NOTES (i));
6425             break;
6426           }
6427     }
6428   DONE;
6429 }")
6430
6431 (define_insn "indirect_jump_compact"
6432   [(set (pc)
6433         (match_operand:SI 0 "arith_reg_operand" "r"))]
6434   "TARGET_SH1"
6435   "jmp  @%0%#"
6436   [(set_attr "needs_delay_slot" "yes")
6437    (set_attr "type" "jump_ind")])
6438
6439 (define_expand "indirect_jump"
6440   [(set (pc)
6441         (match_operand 0 "register_operand" ""))]
6442   ""
6443   "
6444 {
6445   if (TARGET_SHMEDIA && GET_MODE (operands[0]) == SImode)
6446     operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6447 }")
6448
6449 ;; The use of operand 1 / 2 helps us distinguish case table jumps
6450 ;; which can be present in structured code from indirect jumps which can not
6451 ;; be present in structured code.  This allows -fprofile-arcs to work.
6452
6453 ;; For SH1 processors.
6454 (define_insn "casesi_jump_1"
6455   [(set (pc)
6456         (match_operand:SI 0 "register_operand" "r"))
6457    (use (label_ref (match_operand 1 "" "")))]
6458   "TARGET_SH1"
6459   "jmp  @%0%#"
6460   [(set_attr "needs_delay_slot" "yes")
6461    (set_attr "type" "jump_ind")])
6462
6463 ;; For all later processors.
6464 (define_insn "casesi_jump_2"
6465   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
6466                       (label_ref (match_operand 1 "" ""))))
6467    (use (label_ref (match_operand 2 "" "")))]
6468   "TARGET_SH2
6469    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
6470   "braf %0%#"
6471   [(set_attr "needs_delay_slot" "yes")
6472    (set_attr "type" "jump_ind")])
6473
6474 (define_insn "casesi_jump_media"
6475   [(set (pc) (match_operand:DI 0 "target_reg_operand" "b"))
6476    (use (label_ref (match_operand 1 "" "")))]
6477   "TARGET_SHMEDIA"
6478   "blink        %0, r63"
6479   [(set_attr "type" "jump_media")])
6480
6481 ;; Call subroutine returning any type.
6482 ;; ??? This probably doesn't work.
6483
6484 (define_expand "untyped_call"
6485   [(parallel [(call (match_operand 0 "" "")
6486                     (const_int 0))
6487               (match_operand 1 "" "")
6488               (match_operand 2 "" "")])]
6489   "TARGET_SH3E || TARGET_SHMEDIA"
6490   "
6491 {
6492   int i;
6493
6494   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
6495
6496   for (i = 0; i < XVECLEN (operands[2], 0); i++)
6497     {
6498       rtx set = XVECEXP (operands[2], 0, i);
6499       emit_move_insn (SET_DEST (set), SET_SRC (set));
6500     }
6501
6502   /* The optimizer does not know that the call sets the function value
6503      registers we stored in the result block.  We avoid problems by
6504      claiming that all hard registers are used and clobbered at this
6505      point.  */
6506   emit_insn (gen_blockage ());
6507
6508   DONE;
6509 }")
6510 \f
6511 ;; ------------------------------------------------------------------------
6512 ;; Misc insns
6513 ;; ------------------------------------------------------------------------
6514
6515 (define_insn "dect"
6516   [(set (reg:SI T_REG)
6517         (eq:SI (match_operand:SI 0 "arith_reg_operand" "+r") (const_int 1)))
6518    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
6519   "TARGET_SH2"
6520   "dt   %0"
6521   [(set_attr "type" "arith")])
6522
6523 (define_insn "nop"
6524   [(const_int 0)]
6525   ""
6526   "nop")
6527
6528 ;; Load address of a label. This is only generated by the casesi expand,
6529 ;; and by machine_dependent_reorg (fixing up fp moves).
6530 ;; This must use unspec, because this only works for labels that are
6531 ;; within range,
6532
6533 (define_insn "mova"
6534   [(set (reg:SI R0_REG)
6535         (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
6536   "TARGET_SH1"
6537   "mova %O0,r0"
6538   [(set_attr "in_delay_slot" "no")
6539    (set_attr "type" "arith")])
6540
6541 ;; machine_dependent_reorg() will make this a `mova'.
6542 (define_insn "mova_const"
6543   [(set (reg:SI R0_REG)
6544         (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
6545   "TARGET_SH1"
6546   "#"
6547   [(set_attr "in_delay_slot" "no")
6548    (set_attr "type" "arith")])
6549
6550 (define_expand "GOTaddr2picreg"
6551   [(set (reg:SI R0_REG)
6552         (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
6553                    UNSPEC_MOVA))
6554    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
6555    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
6556   "" "
6557 {
6558   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
6559   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
6560
6561   if (TARGET_SH5)
6562     operands[1] = gen_datalabel_ref (operands[1]);
6563
6564   if (TARGET_SHMEDIA)
6565     {
6566       rtx tr = gen_rtx_REG (DImode, TR0_REG);
6567       rtx dipic = operands[0];
6568       rtx lab = PATTERN (gen_call_site ());
6569       rtx insn, equiv;
6570
6571       equiv = operands[1];
6572       operands[1] = gen_rtx_MINUS (DImode,
6573                                    operands[1],
6574                                    gen_rtx_CONST
6575                                    (DImode,
6576                                     gen_rtx_MINUS (DImode,
6577                                                    gen_rtx_CONST (DImode,
6578                                                                   lab),
6579                                                    pc_rtx)));
6580       operands[1] = gen_sym2PIC (operands[1]);
6581       PUT_MODE (operands[1], DImode);
6582
6583       if (GET_MODE (dipic) != DImode)
6584         dipic = gen_rtx_SUBREG (DImode, dipic, 0);
6585
6586       if (TARGET_SHMEDIA64)
6587         emit_insn (gen_movdi_const (dipic, operands[1]));
6588       else
6589         emit_insn (gen_movdi_const_32bit (dipic, operands[1]));
6590
6591       emit_insn (gen_ptrel (tr, dipic, lab));
6592
6593       if (GET_MODE (operands[0]) != GET_MODE (tr))
6594         tr = gen_rtx_SUBREG (GET_MODE (operands[0]), tr, 0);
6595
6596       insn = emit_move_insn (operands[0], tr);
6597
6598       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
6599                                             REG_NOTES (insn));
6600
6601       DONE;
6602     }
6603 }
6604 ")
6605
6606 ;; When generating PIC, we must match label_refs especially, because
6607 ;; they do not satisfy LEGITIMATE_PIC_OPERAND_P(), and we don't want
6608 ;; them to do, because they can't be loaded directly into
6609 ;; non-branch-target registers.
6610 (define_insn "*pt"
6611   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6612         (match_operand:DI 1 "" "T"))]
6613   "TARGET_SHMEDIA && flag_pic
6614    && EXTRA_CONSTRAINT_T (operands[1])"
6615   "pt   %1, %0"
6616   [(set_attr "type" "pt_media")
6617    (set_attr "length" "*")])
6618
6619 (define_insn "*ptb"
6620   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6621         (const:DI (unspec:DI [(match_operand:DI 1 "" "T")]
6622                              UNSPEC_DATALABEL)))]
6623   "TARGET_SHMEDIA && flag_pic
6624    && EXTRA_CONSTRAINT_T (operands[1])"
6625   "ptb/u        datalabel %1, %0"
6626   [(set_attr "type" "pt_media")
6627    (set_attr "length" "*")])
6628
6629 (define_insn "ptrel"
6630   [(set (match_operand:DI 0 "target_reg_operand" "=b")
6631         (plus:DI (match_operand:DI 1 "register_operand" "r")
6632               (pc)))
6633    (match_operand:DI 2 "" "")]
6634   "TARGET_SHMEDIA"
6635   "%O2: ptrel/u %1, %0"
6636   [(set_attr "type" "ptabs_media")])
6637
6638 (define_expand "builtin_setjmp_receiver"
6639   [(match_operand 0 "" "")]
6640   "flag_pic"
6641   "
6642 {
6643   emit_insn (gen_GOTaddr2picreg ());
6644   DONE;
6645 }")
6646
6647 (define_expand "call_site"
6648   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
6649   "TARGET_SH1"
6650   "
6651 {
6652   static HOST_WIDE_INT i = 0;
6653   operands[0] = GEN_INT (i);
6654   i++;
6655 }")
6656
6657 (define_expand "sym_label2reg"
6658   [(set (match_operand:SI 0 "" "")
6659         (const:SI (minus:SI
6660                    (const:SI
6661                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
6662                    (const:SI
6663                     (plus:SI
6664                      (match_operand:SI 2 "" "")
6665                      (const_int 2))))))]
6666   "TARGET_SH1" "")
6667
6668 (define_expand "symGOT_load"
6669   [(set (match_dup 2) (match_operand 1 "" ""))
6670    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
6671    (set (match_operand 0 "" "") (mem (match_dup 3)))]
6672   ""
6673   "
6674 {
6675   rtx insn;
6676
6677   operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6678   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6679
6680   if (TARGET_SHMEDIA)
6681     {
6682       rtx reg = operands[2];
6683
6684       if (GET_MODE (reg) != DImode)
6685         reg = gen_rtx_SUBREG (DImode, reg, 0);
6686
6687       if (flag_pic > 1)
6688         emit_insn (gen_movdi_const_32bit (reg, operands[1]));
6689       else
6690         emit_insn (gen_movdi_const_16bit (reg, operands[1]));
6691     }
6692   else
6693     emit_move_insn (operands[2], operands[1]);
6694
6695   emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
6696                                              operands[2],
6697                                              gen_rtx_REG (Pmode, PIC_REG)));
6698
6699   insn = emit_move_insn (operands[0], gen_rtx_MEM (Pmode, operands[3]));
6700
6701   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, XVECEXP (XEXP (operands[1],
6702                                                                   0), 0, 0),
6703                                         REG_NOTES (insn));
6704
6705   DONE;
6706 }")
6707
6708 (define_expand "sym2GOT"
6709   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
6710   ""
6711   "")
6712
6713 (define_expand "symGOT2reg"
6714   [(match_operand 0 "" "") (match_operand 1 "" "")]
6715   ""
6716   "
6717 {
6718   rtx gotsym, insn;
6719
6720   gotsym = gen_sym2GOT (operands[1]);
6721   PUT_MODE (gotsym, Pmode);
6722   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
6723
6724   RTX_UNCHANGING_P (SET_SRC (PATTERN (insn))) = 1;
6725
6726   DONE;
6727 }")
6728
6729 (define_expand "sym2GOTPLT"
6730   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTPLT))]
6731   ""
6732   "")
6733
6734 (define_expand "symGOTPLT2reg"
6735   [(match_operand 0 "" "") (match_operand 1 "" "")]
6736   ""
6737   "
6738 {
6739   emit_insn (gen_symGOT_load (operands[0], gen_sym2GOTPLT (operands[1])));
6740   DONE;
6741 }")
6742
6743 (define_expand "sym2GOTOFF"
6744   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
6745   ""
6746   "")
6747
6748 (define_expand "symGOTOFF2reg"
6749   [(match_operand 0 "" "") (match_operand 1 "" "")]
6750   ""
6751   "
6752 {
6753   rtx gotoffsym, insn;
6754   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
6755
6756   gotoffsym = gen_sym2GOTOFF (operands[1]);
6757   PUT_MODE (gotoffsym, Pmode);
6758   emit_move_insn (t, gotoffsym);
6759   insn = emit_move_insn (operands[0],
6760                          gen_rtx_PLUS (Pmode, t,
6761                                        gen_rtx_REG (Pmode, PIC_REG)));
6762
6763   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
6764                                         REG_NOTES (insn));
6765
6766   DONE;
6767 }")
6768
6769 (define_expand "symPLT_label2reg"
6770   [(set (match_operand:SI 0 "" "")
6771         (const:SI (minus:SI
6772                    (const:SI
6773                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
6774                    (const:SI
6775                     (minus:SI
6776                      (const:SI (plus:SI
6777                                 (match_operand:SI 2 "" "")
6778                                 (const_int 2)))
6779                      (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
6780    ;; Even though the PIC register is not really used by the call
6781    ;; sequence in which this is expanded, the PLT code assumes the PIC
6782    ;; register is set, so we must not skip its initialization.  Since
6783    ;; we only use this expand as part of calling sequences, and never
6784    ;; to take the address of a function, this is the best point to
6785    ;; insert the (use).  Using the PLT to take the address of a
6786    ;; function would be wrong, not only because the PLT entry could
6787    ;; then be called from a function that doesn't initialize the PIC
6788    ;; register to the proper GOT, but also because pointers to the
6789    ;; same function might not compare equal, should they be set by
6790    ;; different shared libraries.
6791    (use (reg:SI PIC_REG))]
6792   "TARGET_SH1"
6793   "")
6794
6795 (define_expand "sym2PIC"
6796   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
6797   ""
6798   "")
6799
6800 ;; case instruction for switch statements.
6801
6802 ;; Operand 0 is index
6803 ;; operand 1 is the minimum bound
6804 ;; operand 2 is the maximum bound - minimum bound + 1
6805 ;; operand 3 is CODE_LABEL for the table;
6806 ;; operand 4 is the CODE_LABEL to go to if index out of range.
6807
6808 (define_expand "casesi"
6809   [(match_operand:SI 0 "arith_reg_operand" "")
6810    (match_operand:SI 1 "arith_reg_operand" "")
6811    (match_operand:SI 2 "arith_reg_operand" "")
6812    (match_operand 3 "" "") (match_operand 4 "" "")]
6813   ""
6814   "
6815 {
6816   rtx reg = gen_reg_rtx (SImode);
6817   rtx reg2 = gen_reg_rtx (SImode);
6818   if (TARGET_SHMEDIA)
6819     {
6820       rtx reg = gen_reg_rtx (DImode);
6821       rtx reg2 = gen_reg_rtx (DImode);
6822       rtx reg3 = gen_reg_rtx (DImode);
6823       rtx reg4 = gen_reg_rtx (DImode);
6824       rtx reg5 = gen_reg_rtx (DImode);
6825
6826       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
6827       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
6828       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
6829
6830       emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
6831       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
6832       emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
6833       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
6834       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
6835                                                (DImode, operands[3])));
6836       emit_insn (gen_casesi_load_media (reg4, reg3, reg2, operands[3]));
6837       emit_move_insn (reg5, gen_rtx_PLUS (DImode, reg3, reg4));
6838       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
6839       emit_barrier ();
6840       DONE;
6841     }
6842   operands[1] = copy_to_mode_reg (SImode, operands[1]);
6843   operands[2] = copy_to_mode_reg (SImode, operands[2]);
6844   /* If optimizing, casesi_worker depends on the mode of the instruction
6845      before label it 'uses' - operands[3].  */
6846   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
6847                            reg));
6848   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
6849   if (TARGET_SH2)
6850     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
6851   else
6852     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
6853   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
6854      operands[3], but to lab.  We will fix this up in
6855      machine_dependent_reorg.  */
6856   emit_barrier ();
6857   DONE;
6858 }")
6859
6860 (define_expand "casesi_0"
6861   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
6862    (set (match_dup 4) (minus:SI (match_dup 4)
6863                                 (match_operand:SI 1 "arith_operand" "")))
6864    (set (reg:SI T_REG)
6865         (gtu:SI (match_dup 4)
6866                 (match_operand:SI 2 "arith_reg_operand" "")))
6867    (set (pc)
6868         (if_then_else (ne (reg:SI T_REG)
6869                           (const_int 0))
6870                       (label_ref (match_operand 3 "" ""))
6871                       (pc)))]
6872   "TARGET_SH1"
6873   "")
6874
6875 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
6876 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
6877 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
6878
6879 (define_insn "casesi_worker_0"
6880   [(set (match_operand:SI 0 "register_operand" "=r,r")
6881         (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
6882                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6883    (clobber (match_scratch:SI 3 "=X,1"))
6884    (clobber (match_scratch:SI 4 "=&z,z"))]
6885   "TARGET_SH1"
6886   "#")
6887
6888 (define_split
6889   [(set (match_operand:SI 0 "register_operand" "")
6890         (unspec:SI [(match_operand:SI 1 "register_operand" "")
6891                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6892    (clobber (match_scratch:SI 3 ""))
6893    (clobber (match_scratch:SI 4 ""))]
6894   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
6895   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
6896    (parallel [(set (match_dup 0)
6897               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
6898                           (label_ref (match_dup 2))] UNSPEC_CASESI))
6899               (clobber (match_dup 3))])
6900    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
6901   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
6902
6903 (define_split
6904   [(set (match_operand:SI 0 "register_operand" "")
6905         (unspec:SI [(match_operand:SI 1 "register_operand" "")
6906                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6907    (clobber (match_scratch:SI 3 ""))
6908    (clobber (match_scratch:SI 4 ""))]
6909   "TARGET_SH2 && reload_completed"
6910   [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
6911    (parallel [(set (match_dup 0)
6912               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
6913                           (label_ref (match_dup 2))] UNSPEC_CASESI))
6914               (clobber (match_dup 3))])]
6915   "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
6916
6917 (define_insn "*casesi_worker"
6918   [(set (match_operand:SI 0 "register_operand" "=r,r")
6919         (unspec:SI [(reg:SI R0_REG)
6920                     (match_operand:SI 1 "register_operand" "0,r")
6921                     (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6922    (clobber (match_scratch:SI 3 "=X,1"))]
6923   "TARGET_SH1"
6924   "*
6925 {
6926   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
6927
6928   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
6929     abort ();
6930
6931   switch (GET_MODE (diff_vec))
6932     {
6933     case SImode:
6934       return \"shll2    %1\;mov.l       @(r0,%1),%0\";
6935     case HImode:
6936       return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
6937     case QImode:
6938       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
6939         return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
6940       return \"mov.b    @(r0,%1),%0\";
6941     default:
6942       abort ();
6943     }
6944 }"
6945   [(set_attr "length" "4")])
6946
6947 (define_insn "casesi_shift_media"
6948   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
6949         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
6950                    (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
6951                     UNSPEC_CASESI)))]
6952   "TARGET_SHMEDIA"
6953   "*
6954 {
6955   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
6956
6957   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
6958     abort ();
6959
6960   switch (GET_MODE (diff_vec))
6961     {
6962     case SImode:
6963       return \"shlli    %1, 2, %0\";
6964     case HImode:
6965       return \"shlli    %1, 1, %0\";
6966     case QImode:
6967       if (rtx_equal_p (operands[0], operands[1]))
6968         return \"\";
6969       return \"add      %1, r63, %0\";
6970     default:
6971       abort ();
6972     }
6973 }"
6974   [(set_attr "type" "arith_media")])
6975
6976 (define_insn "casesi_load_media"
6977   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
6978         (mem:DI (unspec [(match_operand 1 "arith_reg_operand" "r")
6979                          (match_operand 2 "arith_reg_operand" "r")
6980                          (label_ref:DI (match_operand 3 "" ""))] 2)))]
6981   "TARGET_SHMEDIA"
6982   "*
6983 {
6984   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
6985
6986   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
6987     abort ();
6988
6989   switch (GET_MODE (diff_vec))
6990     {
6991     case SImode:
6992       return \"ldx.l    %1, %2, %0\";
6993     case HImode:
6994 #if 0
6995       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
6996         return \"ldx.uw %1, %2, %0\";
6997 #endif
6998       return \"ldx.w    %1, %2, %0\";
6999     case QImode:
7000       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
7001         return \"ldx.ub %1, %2, %0\";
7002       return \"ldx.b    %1, %2, %0\";
7003     default:
7004       abort ();
7005     }
7006 }"
7007   [(set_attr "type" "load_media")])
7008
7009 (define_expand "return"
7010   [(return)]
7011   "reload_completed && ! sh_need_epilogue ()"
7012   "
7013 {
7014   if (TARGET_SHMEDIA)
7015     {
7016       emit_jump_insn (gen_return_media ());
7017       DONE;
7018     }
7019
7020   if (TARGET_SHCOMPACT
7021       && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
7022     {
7023       emit_jump_insn (gen_shcompact_return_tramp ());
7024       DONE;
7025     }
7026 }")
7027
7028 (define_insn "*return_i"
7029   [(return)]
7030   "TARGET_SH1 && ! (TARGET_SHCOMPACT
7031                     && (current_function_args_info.call_cookie
7032                         & CALL_COOKIE_RET_TRAMP (1)))
7033    && reload_completed"
7034   "%@   %#"
7035   [(set_attr "type" "return")
7036    (set_attr "needs_delay_slot" "yes")])
7037
7038 (define_expand "shcompact_return_tramp"
7039   [(return)]
7040   "TARGET_SHCOMPACT
7041    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
7042   "
7043 {
7044   rtx reg = gen_rtx_REG (Pmode, R0_REG);
7045   rtx sym = gen_rtx_SYMBOL_REF (Pmode,
7046                                 \"__GCC_shcompact_return_trampoline\");
7047
7048   if (flag_pic)
7049     emit_insn (gen_symGOTPLT2reg (reg, sym));
7050   else
7051     emit_move_insn (reg, sym);
7052
7053   emit_jump_insn (gen_shcompact_return_tramp_i ());
7054   DONE;
7055 }")
7056
7057 (define_insn "shcompact_return_tramp_i"
7058   [(parallel [(return) (use (reg:SI R0_REG))])]
7059   "TARGET_SHCOMPACT
7060    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
7061   "jmp  @r0%#"
7062   [(set_attr "type" "jump_ind")
7063    (set_attr "needs_delay_slot" "yes")])
7064
7065 (define_insn "return_media_i"
7066   [(parallel [(return) (use (match_operand:DI 0 "target_reg_operand" "k"))])]
7067   "TARGET_SHMEDIA && reload_completed"
7068   "blink        %0, r63"
7069   [(set_attr "type" "jump_media")])
7070
7071 (define_expand "return_media"
7072   [(return)]
7073   "TARGET_SHMEDIA && reload_completed"
7074   "
7075 {
7076   int tr_regno = sh_media_register_for_return ();
7077   rtx tr;
7078
7079   if (tr_regno < 0)
7080     {
7081       rtx r18 = gen_rtx_REG (DImode, PR_MEDIA_REG);
7082
7083       tr_regno = TR0_REG;
7084       tr = gen_rtx_REG (DImode, tr_regno);
7085       emit_move_insn (tr, r18);
7086     }
7087   else
7088     tr = gen_rtx_REG (DImode, tr_regno);
7089
7090   emit_jump_insn (gen_return_media_i (tr));
7091   DONE;
7092 }")
7093
7094 (define_insn "shcompact_preserve_incoming_args"
7095   [(set (match_operand:SI 0 "register_operand" "+r")
7096         (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
7097   "TARGET_SHCOMPACT"
7098   ""
7099   [(set_attr "length" "0")])
7100
7101 (define_insn "shcompact_incoming_args"
7102   [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
7103    (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
7104    (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
7105    (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
7106    (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
7107    (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
7108    (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
7109    (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
7110    (set (mem:BLK (reg:SI MACL_REG))
7111         (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
7112    (use (reg:SI R0_REG))
7113    (clobber (reg:SI R0_REG))
7114    (clobber (reg:SI MACL_REG))
7115    (clobber (reg:SI MACH_REG))
7116    (clobber (reg:SI PR_REG))]
7117   "TARGET_SHCOMPACT"
7118   "jsr  @r0%#"
7119   [(set_attr "needs_delay_slot" "yes")])
7120
7121 (define_insn "shmedia_save_restore_regs_compact"
7122   [(set (reg:SI SP_REG)
7123         (plus:SI (reg:SI SP_REG)
7124                  (match_operand:SI 0 "immediate_operand" "i")))
7125    (use (reg:SI R0_REG))
7126    (clobber (reg:SI PR_REG))]
7127   "TARGET_SHCOMPACT
7128    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
7129        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
7130   "jsr @r0%#"
7131   [(set_attr "needs_delay_slot" "yes")])
7132
7133 (define_expand "prologue"
7134   [(const_int 0)]
7135   ""
7136   "sh_expand_prologue (); DONE;")
7137
7138 (define_expand "epilogue"
7139   [(return)]
7140   ""
7141   "
7142 {
7143   sh_expand_epilogue ();
7144   emit_jump_insn (gen_return ());
7145   DONE;
7146 }")
7147
7148 (define_insn "blockage"
7149   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
7150   ""
7151   ""
7152   [(set_attr "length" "0")])
7153 \f
7154 ;; ------------------------------------------------------------------------
7155 ;; Scc instructions
7156 ;; ------------------------------------------------------------------------
7157
7158 (define_insn "movt"
7159   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7160         (eq:SI (reg:SI T_REG) (const_int 1)))]
7161   "TARGET_SH1"
7162   "movt %0"
7163   [(set_attr "type" "arith")])
7164
7165 (define_expand "seq"
7166   [(set (match_operand:SI 0 "arith_reg_operand" "")
7167         (match_dup 1))]
7168   ""
7169   "
7170 {
7171   if (TARGET_SHMEDIA)
7172     {
7173       if (GET_MODE (operands[0]) != DImode)
7174         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7175       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7176       if (sh_compare_op1 != const0_rtx)
7177         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7178                                     ? GET_MODE (sh_compare_op0)
7179                                     : GET_MODE (sh_compare_op1),
7180                                     sh_compare_op1);
7181
7182       switch (GET_MODE (sh_compare_op0))
7183         {
7184         case DImode:
7185           emit_insn (gen_cmpeqdi_media (operands[0],
7186                                         sh_compare_op0, sh_compare_op1));
7187           break;
7188
7189         case SFmode:
7190           if (! TARGET_SHMEDIA_FPU)
7191             FAIL;
7192           emit_insn (gen_cmpeqsf_media (operands[0],
7193                                         sh_compare_op0, sh_compare_op1));
7194           break;
7195
7196         case DFmode:
7197           if (! TARGET_SHMEDIA_FPU)
7198             FAIL;
7199           emit_insn (gen_cmpeqdf_media (operands[0],
7200                                         sh_compare_op0, sh_compare_op1));
7201           break;
7202
7203         default:
7204           FAIL;
7205         }
7206       DONE;
7207     }
7208   operands[1] = prepare_scc_operands (EQ);
7209 }")
7210
7211 (define_expand "slt"
7212   [(set (match_operand:SI 0 "arith_reg_operand" "")
7213         (match_dup 1))]
7214   ""
7215   "
7216 {
7217   if (TARGET_SHMEDIA)
7218     {
7219       if (GET_MODE (operands[0]) != DImode)
7220         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7221       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7222       if (sh_compare_op1 != const0_rtx)
7223         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7224                                     ? GET_MODE (sh_compare_op0)
7225                                     : GET_MODE (sh_compare_op1),
7226                                     sh_compare_op1);
7227
7228       switch (GET_MODE (sh_compare_op0))
7229         {
7230         case DImode:
7231           emit_insn (gen_cmpgtdi_media (operands[0],
7232                                         sh_compare_op1, sh_compare_op0));
7233           break;
7234
7235         case SFmode:
7236           if (! TARGET_SHMEDIA_FPU)
7237             FAIL;
7238           emit_insn (gen_cmpgtsf_media (operands[0],
7239                                         sh_compare_op1, sh_compare_op0));
7240           break;
7241
7242         case DFmode:
7243           if (! TARGET_SHMEDIA_FPU)
7244             FAIL;
7245           emit_insn (gen_cmpgtdf_media (operands[0],
7246                                         sh_compare_op1, sh_compare_op0));
7247           break;
7248
7249         default:
7250           FAIL;
7251         }
7252       DONE;
7253     }
7254   operands[1] = prepare_scc_operands (LT);
7255 }")
7256
7257 (define_expand "sle"
7258   [(match_operand:SI 0 "arith_reg_operand" "")]
7259   ""
7260   "
7261 {
7262   rtx tmp = sh_compare_op0;
7263
7264   if (TARGET_SHMEDIA)
7265     {
7266       if (GET_MODE (operands[0]) != DImode)
7267         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7268       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7269       if (sh_compare_op1 != const0_rtx)
7270         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7271                                     ? GET_MODE (sh_compare_op0)
7272                                     : GET_MODE (sh_compare_op1),
7273                                     sh_compare_op1);
7274
7275       switch (GET_MODE (sh_compare_op0))
7276         {
7277         case DImode:
7278           {
7279             tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7280
7281             emit_insn (gen_cmpgtdi_media (tmp,
7282                                           sh_compare_op0, sh_compare_op1));
7283             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7284             break;
7285           }
7286
7287         case SFmode:
7288           if (! TARGET_SHMEDIA_FPU)
7289             FAIL;
7290           emit_insn (gen_cmpgesf_media (operands[0],
7291                                         sh_compare_op1, sh_compare_op0));
7292           break;
7293
7294         case DFmode:
7295           if (! TARGET_SHMEDIA_FPU)
7296             FAIL;
7297           emit_insn (gen_cmpgedf_media (operands[0],
7298                                         sh_compare_op1, sh_compare_op0));
7299           break;
7300
7301         default:
7302           FAIL;
7303         }
7304       DONE;
7305     }
7306
7307   sh_compare_op0 = sh_compare_op1;
7308   sh_compare_op1 = tmp;
7309   emit_insn (gen_sge (operands[0]));
7310   DONE;
7311 }")
7312
7313 (define_expand "sgt"
7314   [(set (match_operand:SI 0 "arith_reg_operand" "")
7315         (match_dup 1))]
7316   ""
7317   "
7318 {
7319   if (TARGET_SHMEDIA)
7320     {
7321       if (GET_MODE (operands[0]) != DImode)
7322         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7323       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7324       if (sh_compare_op1 != const0_rtx)
7325         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7326                                     ? GET_MODE (sh_compare_op0)
7327                                     : GET_MODE (sh_compare_op1),
7328                                     sh_compare_op1);
7329
7330       switch (GET_MODE (sh_compare_op0))
7331         {
7332         case DImode:
7333           emit_insn (gen_cmpgtdi_media (operands[0],
7334                                         sh_compare_op0, sh_compare_op1));
7335           break;
7336
7337         case SFmode:
7338           if (! TARGET_SHMEDIA_FPU)
7339             FAIL;
7340           emit_insn (gen_cmpgtsf_media (operands[0],
7341                                         sh_compare_op0, sh_compare_op1));
7342           break;
7343
7344         case DFmode:
7345           if (! TARGET_SHMEDIA_FPU)
7346             FAIL;
7347           emit_insn (gen_cmpgtdf_media (operands[0],
7348                                         sh_compare_op0, sh_compare_op1));
7349           break;
7350
7351         default:
7352           FAIL;
7353         }
7354       DONE;
7355     }
7356   operands[1] = prepare_scc_operands (GT);
7357 }")
7358
7359 (define_expand "sge"
7360   [(set (match_operand:SI 0 "arith_reg_operand" "")
7361         (match_dup 1))]
7362   ""
7363   "
7364 {
7365   if (TARGET_SHMEDIA)
7366     {
7367       if (GET_MODE (operands[0]) != DImode)
7368         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7369       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7370       if (sh_compare_op1 != const0_rtx)
7371         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7372                                     ? GET_MODE (sh_compare_op0)
7373                                     : GET_MODE (sh_compare_op1),
7374                                     sh_compare_op1);
7375
7376       switch (GET_MODE (sh_compare_op0))
7377         {
7378         case DImode:
7379           {
7380             rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7381
7382             emit_insn (gen_cmpgtdi_media (tmp,
7383                                           sh_compare_op1, sh_compare_op0));
7384             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7385             break;
7386           }
7387
7388         case SFmode:
7389           if (! TARGET_SHMEDIA_FPU)
7390             FAIL;
7391           emit_insn (gen_cmpgesf_media (operands[0],
7392                                         sh_compare_op0, sh_compare_op1));
7393           break;
7394
7395         case DFmode:
7396           if (! TARGET_SHMEDIA_FPU)
7397             FAIL;
7398           emit_insn (gen_cmpgedf_media (operands[0],
7399                                         sh_compare_op0, sh_compare_op1));
7400           break;
7401
7402         default:
7403           FAIL;
7404         }
7405       DONE;
7406     }
7407
7408   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
7409     {
7410       if (TARGET_IEEE)
7411         {
7412           rtx lab = gen_label_rtx ();
7413           prepare_scc_operands (EQ);
7414           emit_jump_insn (gen_branch_true (lab));
7415           prepare_scc_operands (GT);
7416           emit_label (lab);
7417           emit_insn (gen_movt (operands[0]));
7418         }
7419       else
7420         emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
7421       DONE;
7422     }
7423   operands[1] = prepare_scc_operands (GE);
7424 }")
7425
7426 (define_expand "sgtu"
7427   [(set (match_operand:SI 0 "arith_reg_operand" "")
7428         (match_dup 1))]
7429   ""
7430   "
7431 {
7432   if (TARGET_SHMEDIA)
7433     {
7434       if (GET_MODE (operands[0]) != DImode)
7435         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7436       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7437       if (sh_compare_op1 != const0_rtx)
7438         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7439                                     ? GET_MODE (sh_compare_op0)
7440                                     : GET_MODE (sh_compare_op1),
7441                                     sh_compare_op1);
7442
7443       emit_insn (gen_cmpgtudi_media (operands[0],
7444                                      sh_compare_op0, sh_compare_op1));
7445       DONE;
7446     }
7447   operands[1] = prepare_scc_operands (GTU);
7448 }")
7449
7450 (define_expand "sltu"
7451   [(set (match_operand:SI 0 "arith_reg_operand" "")
7452         (match_dup 1))]
7453   ""
7454   "
7455 {
7456   if (TARGET_SHMEDIA)
7457     {
7458       if (GET_MODE (operands[0]) != DImode)
7459         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7460       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7461       if (sh_compare_op1 != const0_rtx)
7462         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7463                                     ? GET_MODE (sh_compare_op0)
7464                                     : GET_MODE (sh_compare_op1),
7465                                     sh_compare_op1);
7466
7467       emit_insn (gen_cmpgtudi_media (operands[0],
7468                                      sh_compare_op1, sh_compare_op0));
7469       DONE;
7470     }
7471   operands[1] = prepare_scc_operands (LTU);
7472 }")
7473
7474 (define_expand "sleu"
7475   [(set (match_operand:SI 0 "arith_reg_operand" "")
7476         (match_dup 1))]
7477   ""
7478   "
7479 {
7480   if (TARGET_SHMEDIA)
7481     {
7482       rtx tmp;
7483
7484       if (GET_MODE (operands[0]) != DImode)
7485         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7486       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7487       if (sh_compare_op1 != const0_rtx)
7488         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7489                                     ? GET_MODE (sh_compare_op0)
7490                                     : GET_MODE (sh_compare_op1),
7491                                     sh_compare_op1);
7492
7493       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7494
7495       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
7496       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7497
7498       DONE;
7499     }
7500   operands[1] = prepare_scc_operands (LEU);
7501 }")
7502
7503 (define_expand "sgeu"
7504   [(set (match_operand:SI 0 "arith_reg_operand" "")
7505         (match_dup 1))]
7506   ""
7507   "
7508 {
7509   if (TARGET_SHMEDIA)
7510     {
7511       rtx tmp;
7512
7513       if (GET_MODE (operands[0]) != DImode)
7514         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7515       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7516       if (sh_compare_op1 != const0_rtx)
7517         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7518                                     ? GET_MODE (sh_compare_op0)
7519                                     : GET_MODE (sh_compare_op1),
7520                                     sh_compare_op1);
7521
7522       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7523
7524       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
7525       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7526
7527       DONE;
7528     }
7529
7530   operands[1] = prepare_scc_operands (GEU);
7531 }")
7532
7533 ;; sne moves the complement of the T reg to DEST like this:
7534 ;;      cmp/eq ...
7535 ;;      mov    #-1,temp
7536 ;;      negc   temp,dest
7537 ;;   This is better than xoring compare result with 1 because it does
7538 ;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
7539 ;;   loop.
7540
7541 (define_expand "sne"
7542   [(set (match_dup 2) (const_int -1))
7543    (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
7544                    (neg:SI (plus:SI (match_dup 1)
7545                                     (match_dup 2))))
7546               (set (reg:SI T_REG)
7547                    (ne:SI (ior:SI (match_dup 1) (match_dup 2))
7548                           (const_int 0)))])]
7549   ""
7550   "
7551 {
7552   if (TARGET_SHMEDIA)
7553     {
7554       rtx tmp;
7555
7556       if (GET_MODE (operands[0]) != DImode)
7557         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7558
7559       if (! TARGET_SHMEDIA_FPU && GET_MODE (sh_compare_op0) != DImode)
7560         FAIL;
7561
7562       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7563       if (sh_compare_op1 != const0_rtx)
7564         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7565                                     ? GET_MODE (sh_compare_op0)
7566                                     : GET_MODE (sh_compare_op1),
7567                                     sh_compare_op1);
7568
7569       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7570
7571       emit_insn (gen_seq (tmp));
7572       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7573
7574       DONE;
7575     }
7576
7577    operands[1] = prepare_scc_operands (EQ);
7578    operands[2] = gen_reg_rtx (SImode);
7579 }")
7580
7581 (define_expand "sunordered"
7582   [(set (match_operand:DI 0 "arith_reg_operand" "")
7583         (unordered:DI (match_dup 1) (match_dup 2)))]
7584   "TARGET_SHMEDIA_FPU"
7585   "
7586 {
7587   operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7588   operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
7589 }")
7590
7591 ;; Use the same trick for FP sle / sge
7592 (define_expand "movnegt"
7593   [(set (match_dup 2) (const_int -1))
7594    (parallel [(set (match_operand 0 "" "")
7595                    (neg:SI (plus:SI (match_dup 1)
7596                                     (match_dup 2))))
7597               (set (reg:SI T_REG)
7598                    (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
7599                           (const_int 0)))])]
7600   "TARGET_SH1"
7601   "operands[2] = gen_reg_rtx (SImode);")
7602
7603 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
7604 ;; This prevents a regression that occurred when we switched from xor to
7605 ;; mov/neg for sne.
7606
7607 (define_split
7608   [(set (match_operand:SI 0 "arith_reg_operand" "")
7609         (plus:SI (reg:SI T_REG)
7610                  (const_int -1)))]
7611   "TARGET_SH1"
7612   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
7613    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
7614   "")
7615
7616 ;; -------------------------------------------------------------------------
7617 ;; Instructions to cope with inline literal tables
7618 ;; -------------------------------------------------------------------------
7619
7620 ; 2 byte integer in line
7621
7622 (define_insn "consttable_2"
7623  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7624                     (match_operand 1 "" "")]
7625                    UNSPECV_CONST2)]
7626  ""
7627  "*
7628 {
7629   if (operands[1] != const0_rtx)
7630     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
7631   return \"\";
7632 }"
7633  [(set_attr "length" "2")
7634  (set_attr "in_delay_slot" "no")])
7635
7636 ; 4 byte integer in line
7637
7638 (define_insn "consttable_4"
7639  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7640                     (match_operand 1 "" "")]
7641                    UNSPECV_CONST4)]
7642  ""
7643  "*
7644 {
7645   if (operands[1] != const0_rtx)
7646     assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
7647   return \"\";
7648 }"
7649  [(set_attr "length" "4")
7650   (set_attr "in_delay_slot" "no")])
7651
7652 ; 8 byte integer in line
7653
7654 (define_insn "consttable_8"
7655  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7656                     (match_operand 1 "" "")]
7657                    UNSPECV_CONST8)]
7658  ""
7659  "*
7660 {
7661   if (operands[1] != const0_rtx)
7662     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
7663   return \"\";
7664 }"
7665  [(set_attr "length" "8")
7666   (set_attr "in_delay_slot" "no")])
7667
7668 ; 4 byte floating point
7669
7670 (define_insn "consttable_sf"
7671  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
7672                     (match_operand 1 "" "")]
7673                    UNSPECV_CONST4)]
7674  ""
7675  "*
7676 {
7677   if (operands[1] != const0_rtx)
7678     {
7679       REAL_VALUE_TYPE d;
7680       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
7681       assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
7682     }
7683   return \"\";
7684 }"
7685  [(set_attr "length" "4")
7686   (set_attr "in_delay_slot" "no")])
7687
7688 ; 8 byte floating point
7689
7690 (define_insn "consttable_df"
7691  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
7692                     (match_operand 1 "" "")]
7693                    UNSPECV_CONST8)]
7694  ""
7695  "*
7696 {
7697   if (operands[1] != const0_rtx)
7698     {
7699       REAL_VALUE_TYPE d;
7700       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
7701       assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
7702     }
7703   return \"\";
7704 }"
7705  [(set_attr "length" "8")
7706   (set_attr "in_delay_slot" "no")])
7707
7708 ;; Alignment is needed for some constant tables; it may also be added for
7709 ;; Instructions at the start of loops, or after unconditional branches.
7710 ;; ??? We would get more accurate lengths if we did instruction
7711 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
7712 ;; here is too conservative.
7713
7714 ; align to a two byte boundary
7715
7716 (define_expand "align_2"
7717  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
7718  ""
7719  "")
7720
7721 ; align to a four byte boundary
7722 ;; align_4 and align_log are instructions for the starts of loops, or
7723 ;; after unconditional branches, which may take up extra room.
7724
7725 (define_expand "align_4"
7726  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
7727  ""
7728  "")
7729
7730 ; align to a cache line boundary
7731
7732 (define_insn "align_log"
7733  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
7734  ""
7735  ""
7736  [(set_attr "length" "0")
7737   (set_attr "in_delay_slot" "no")])
7738
7739 ; emitted at the end of the literal table, used to emit the
7740 ; 32bit branch labels if needed.
7741
7742 (define_insn "consttable_end"
7743   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
7744   ""
7745   "* return output_jump_label_table ();"
7746   [(set_attr "in_delay_slot" "no")])
7747
7748 ; emitted at the end of the window in the literal table.
7749
7750 (define_insn "consttable_window_end"
7751   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
7752   ""
7753   ""
7754   [(set_attr "length" "0")
7755    (set_attr "in_delay_slot" "no")])
7756
7757 ;; -------------------------------------------------------------------------
7758 ;; Misc
7759 ;; -------------------------------------------------------------------------
7760
7761 ;; String/block move insn.
7762
7763 (define_expand "movstrsi"
7764   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
7765                    (mem:BLK (match_operand:BLK 1 "" "")))
7766               (use (match_operand:SI 2 "nonmemory_operand" ""))
7767               (use (match_operand:SI 3 "immediate_operand" ""))
7768               (clobber (reg:SI PR_REG))
7769               (clobber (reg:SI R4_REG))
7770               (clobber (reg:SI R5_REG))
7771               (clobber (reg:SI R0_REG))])]
7772   "TARGET_SH1 && ! TARGET_SH5"
7773   "
7774 {
7775   if(expand_block_move (operands))
7776      DONE;
7777   else FAIL;
7778 }")
7779
7780 (define_insn "block_move_real"
7781   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7782                    (mem:BLK (reg:SI R5_REG)))
7783               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7784               (clobber (reg:SI PR_REG))
7785               (clobber (reg:SI R0_REG))])]
7786   "TARGET_SH1 && ! TARGET_HARD_SH4"
7787   "jsr  @%0%#"
7788   [(set_attr "type" "sfunc")
7789    (set_attr "needs_delay_slot" "yes")])
7790
7791 (define_insn "block_lump_real"
7792   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7793                    (mem:BLK (reg:SI R5_REG)))
7794               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7795               (use (reg:SI R6_REG))
7796               (clobber (reg:SI PR_REG))
7797               (clobber (reg:SI T_REG))
7798               (clobber (reg:SI R4_REG))
7799               (clobber (reg:SI R5_REG))
7800               (clobber (reg:SI R6_REG))
7801               (clobber (reg:SI R0_REG))])]
7802   "TARGET_SH1 && ! TARGET_HARD_SH4"
7803   "jsr  @%0%#"
7804   [(set_attr "type" "sfunc")
7805    (set_attr "needs_delay_slot" "yes")])
7806
7807 (define_insn "block_move_real_i4"
7808   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7809                    (mem:BLK (reg:SI R5_REG)))
7810               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7811               (clobber (reg:SI PR_REG))
7812               (clobber (reg:SI R0_REG))
7813               (clobber (reg:SI R1_REG))
7814               (clobber (reg:SI R2_REG))])]
7815   "TARGET_HARD_SH4"
7816   "jsr  @%0%#"
7817   [(set_attr "type" "sfunc")
7818    (set_attr "needs_delay_slot" "yes")])
7819
7820 (define_insn "block_lump_real_i4"
7821   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7822                    (mem:BLK (reg:SI R5_REG)))
7823               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7824               (use (reg:SI R6_REG))
7825               (clobber (reg:SI PR_REG))
7826               (clobber (reg:SI T_REG))
7827               (clobber (reg:SI R4_REG))
7828               (clobber (reg:SI R5_REG))
7829               (clobber (reg:SI R6_REG))
7830               (clobber (reg:SI R0_REG))
7831               (clobber (reg:SI R1_REG))
7832               (clobber (reg:SI R2_REG))
7833               (clobber (reg:SI R3_REG))])]
7834   "TARGET_HARD_SH4"
7835   "jsr  @%0%#"
7836   [(set_attr "type" "sfunc")
7837    (set_attr "needs_delay_slot" "yes")])
7838 \f
7839 ;; -------------------------------------------------------------------------
7840 ;; Floating point instructions.
7841 ;; -------------------------------------------------------------------------
7842
7843 ;; ??? All patterns should have a type attribute.
7844
7845 (define_expand "fpu_switch0"
7846   [(set (match_operand:SI 0 "" "") (match_dup 2))
7847    (set (match_dup 1) (mem:PSI (match_dup 0)))]
7848   "TARGET_SH4"
7849   "
7850 {
7851   operands[1] = get_fpscr_rtx ();
7852   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
7853   if (flag_pic)
7854     operands[2] = legitimize_pic_address (operands[2], SImode,
7855                                           no_new_pseudos ? operands[0] : 0);
7856 }")
7857
7858 (define_expand "fpu_switch1"
7859   [(set (match_operand:SI 0 "" "") (match_dup 2))
7860    (set (match_dup 3) (plus:SI (match_dup 0) (const_int 4)))
7861    (set (match_dup 1) (mem:PSI (match_dup 3)))]
7862   "TARGET_SH4"
7863   "
7864 {
7865   operands[1] = get_fpscr_rtx ();
7866   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
7867   if (flag_pic)
7868     operands[2] = legitimize_pic_address (operands[2], SImode,
7869                                           no_new_pseudos ? operands[0] : 0);
7870   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
7871 }")
7872
7873 (define_expand "movpsi"
7874   [(set (match_operand:PSI 0 "register_operand" "")
7875         (match_operand:PSI 1 "general_movsrc_operand" ""))]
7876   "TARGET_SH4"
7877   "")
7878
7879 ;; The c / m alternative is a fake to guide reload to load directly into
7880 ;; fpscr, since reload doesn't know how to use post-increment.
7881 ;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
7882 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
7883 ;; predicate after reload.
7884 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
7885 ;; like a mac -> gpr move.
7886 (define_insn "fpu_switch"
7887   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
7888         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
7889   "TARGET_SH3E
7890    && (! reload_completed
7891        || true_regnum (operands[0]) != FPSCR_REG
7892        || GET_CODE (operands[1]) != MEM
7893        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
7894   "@
7895         ! precision stays the same
7896         lds.l   %1,fpscr
7897         mov.l   %1,%0
7898         #
7899         lds     %1,fpscr
7900         mov     %1,%0
7901         mov.l   %1,%0
7902         sts     fpscr,%0
7903         sts.l   fpscr,%0"
7904   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
7905    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,store")])
7906
7907 (define_split
7908   [(set (reg:PSI FPSCR_REG)
7909         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
7910   "TARGET_SH4 && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
7911   [(set (match_dup 0) (match_dup 0))]
7912   "
7913 {
7914   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
7915                                         gen_rtx (MEM, PSImode,
7916                                                  gen_rtx (POST_INC, Pmode,
7917                                                           operands[0]))));
7918   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[0], NULL_RTX);
7919 }")
7920
7921 (define_split
7922   [(set (reg:PSI FPSCR_REG)
7923         (mem:PSI (match_operand:SI 0 "register_operand" "")))]
7924   "TARGET_SH4"
7925   [(set (match_dup 0) (plus:SI (match_dup 0) (const_int -4)))]
7926   "
7927 {
7928   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
7929                                         gen_rtx (MEM, PSImode,
7930                                                  gen_rtx (POST_INC, Pmode,
7931                                                           operands[0]))));
7932   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[0], NULL_RTX);
7933 }")
7934
7935 ;; ??? This uses the fp unit, but has no type indicating that.
7936 ;; If we did that, this would either give a bogus latency or introduce
7937 ;; a bogus FIFO constraint.
7938 ;; Since this insn is currently only used for prologues/epilogues,
7939 ;; it is probably best to claim no function unit, which matches the
7940 ;; current setting.
7941 (define_insn "toggle_sz"
7942   [(set (reg:PSI FPSCR_REG)
7943         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
7944   "TARGET_SH4"
7945   "fschg")
7946
7947 (define_expand "addsf3"
7948   [(set (match_operand:SF 0 "arith_reg_operand" "")
7949         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
7950                  (match_operand:SF 2 "arith_reg_operand" "")))]
7951   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7952   "
7953 {
7954   if (TARGET_SH3E)
7955     {
7956       expand_sf_binop (&gen_addsf3_i, operands);
7957       DONE;
7958     }
7959 }")
7960
7961 (define_insn "*addsf3_media"
7962   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7963         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
7964                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7965   "TARGET_SHMEDIA_FPU"
7966   "fadd.s       %1, %2, %0"
7967   [(set_attr "type" "fparith_media")])
7968
7969 (define_insn_and_split "unary_sf_op"
7970   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
7971         (vec_select:V2SF
7972          (vec_concat:V2SF
7973           (vec_select:SF
7974            (match_dup 0)
7975            (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
7976           (match_operator:SF 2 "unary_float_operator"
7977             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
7978                             (parallel [(match_operand 4
7979                                         "const_int_operand" "n")]))]))
7980          (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
7981   "TARGET_SHMEDIA_FPU"
7982   "#"
7983   "TARGET_SHMEDIA_FPU && reload_completed"
7984   [(set (match_dup 5) (match_dup 6))]
7985   "
7986 {
7987   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
7988   rtx op1 = gen_rtx_REG (SFmode,
7989                          (true_regnum (operands[1])
7990                           + (INTVAL (operands[4]) ^ endian)));
7991
7992   operands[7] = gen_rtx_REG (SFmode,
7993                              (true_regnum (operands[0])
7994                               + (INTVAL (operands[3]) ^ endian)));
7995   operands[6] = gen_rtx (GET_CODE (operands[2]), SFmode, op1);
7996 }"
7997   [(set_attr "type" "fparith_media")])
7998
7999 (define_insn_and_split "binary_sf_op"
8000   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
8001         (vec_select:V2SF
8002          (vec_concat:V2SF
8003           (vec_select:SF
8004            (match_dup 0)
8005            (parallel [(not:BI (match_operand 4 "const_int_operand" "n"))]))
8006           (match_operator:SF 3 "binary_float_operator"
8007             [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
8008                             (parallel [(match_operand 5
8009                                         "const_int_operand" "n")]))
8010              (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
8011                             (parallel [(match_operand 6
8012                                         "const_int_operand" "n")]))]))
8013          (parallel [(not:BI (match_dup 4)) (match_dup 4)])))]
8014   "TARGET_SHMEDIA_FPU"
8015   "#"
8016   "TARGET_SHMEDIA_FPU && reload_completed"
8017   [(set (match_dup 7) (match_dup 8))]
8018   "
8019 {
8020   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
8021   rtx op1 = gen_rtx_REG (SFmode,
8022                          (true_regnum (operands[1])
8023                           + (INTVAL (operands[5]) ^ endian)));
8024   rtx op2 = gen_rtx_REG (SFmode,
8025                          (true_regnum (operands[2])
8026                           + (INTVAL (operands[6]) ^ endian)));
8027
8028   operands[7] = gen_rtx_REG (SFmode,
8029                              (true_regnum (operands[0])
8030                               + (INTVAL (operands[4]) ^ endian)));
8031   operands[8] = gen_rtx (GET_CODE (operands[3]), SFmode, op1, op2);
8032 }"
8033   [(set_attr "type" "fparith_media")])
8034
8035 (define_insn "addsf3_i"
8036   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
8037         (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0")
8038                  (match_operand:SF 2 "arith_reg_operand" "f")))
8039    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8040   "TARGET_SH3E"
8041   "fadd %2,%0"
8042   [(set_attr "type" "fp")
8043    (set_attr "fp_mode" "single")])
8044
8045 (define_expand "subsf3"
8046   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8047         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
8048                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
8049   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8050   "
8051 {
8052   if (TARGET_SH3E)
8053     {
8054       expand_sf_binop (&gen_subsf3_i, operands);
8055       DONE;
8056     }
8057 }")
8058
8059 (define_insn "*subsf3_media"
8060   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8061         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
8062                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8063   "TARGET_SHMEDIA_FPU"
8064   "fsub.s       %1, %2, %0"
8065   [(set_attr "type" "fparith_media")])
8066
8067 (define_insn "subsf3_i"
8068   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8069         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
8070                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
8071    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8072   "TARGET_SH3E"
8073   "fsub %2,%0"
8074   [(set_attr "type" "fp")
8075    (set_attr "fp_mode" "single")])
8076
8077 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
8078 ;; register in feeding fp instructions.  Thus, we cannot generate fmac for
8079 ;; mixed-precision SH4 targets.  To allow it to be still generated for the
8080 ;; SH3E, we use a separate insn for SH3E mulsf3.
8081
8082 (define_expand "mulsf3"
8083   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8084         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
8085                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
8086   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8087   "
8088 {
8089   if (TARGET_SH4)
8090     expand_sf_binop (&gen_mulsf3_i4, operands);
8091   else if (TARGET_SH3E)
8092     emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2]));
8093   if (! TARGET_SHMEDIA)
8094     DONE;
8095 }")
8096
8097 (define_insn "*mulsf3_media"
8098   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8099         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8100                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8101   "TARGET_SHMEDIA_FPU"
8102   "fmul.s       %1, %2, %0"
8103   [(set_attr "type" "fparith_media")])
8104
8105 (define_insn "mulsf3_i4"
8106   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8107         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
8108                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
8109    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8110   "TARGET_SH3E"
8111   "fmul %2,%0"
8112   [(set_attr "type" "fp")
8113    (set_attr "fp_mode" "single")])
8114
8115 (define_insn "mulsf3_ie"
8116   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8117         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
8118                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8119   "TARGET_SH3E && ! TARGET_SH4"
8120   "fmul %2,%0"
8121   [(set_attr "type" "fp")])
8122
8123 (define_insn "*mac_media"
8124   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8125         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
8126                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
8127                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
8128   "TARGET_SHMEDIA_FPU"
8129   "fmac.s %1, %2, %0"
8130   [(set_attr "type" "fparith_media")])
8131
8132 (define_insn "*macsf3"
8133   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8134         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
8135                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
8136                  (match_operand:SF 3 "arith_reg_operand" "0")))
8137    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
8138   "TARGET_SH3E && ! TARGET_SH4"
8139   "fmac fr0,%2,%0"
8140   [(set_attr "type" "fp")
8141    (set_attr "fp_mode" "single")])
8142
8143 (define_expand "divsf3"
8144   [(set (match_operand:SF 0 "arith_reg_operand" "")
8145         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
8146                 (match_operand:SF 2 "arith_reg_operand" "")))]
8147   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8148   "
8149 {
8150   if (TARGET_SH3E)
8151     {
8152       expand_sf_binop (&gen_divsf3_i, operands);
8153       DONE;
8154     }
8155 }")
8156
8157 (define_insn "*divsf3_media"
8158   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8159         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
8160                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8161   "TARGET_SHMEDIA_FPU"
8162   "fdiv.s       %1, %2, %0"
8163   [(set_attr "type" "fdiv_media")])
8164
8165 (define_insn "divsf3_i"
8166   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
8167         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
8168                  (match_operand:SF 2 "arith_reg_operand" "f")))
8169    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8170   "TARGET_SH3E"
8171   "fdiv %2,%0"
8172   [(set_attr "type" "fdiv")
8173    (set_attr "fp_mode" "single")])
8174
8175 (define_insn "floatdisf2"
8176   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8177         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
8178   "TARGET_SHMEDIA_FPU"
8179   "float.qs %1, %0"
8180   [(set_attr "type" "fpconv_media")])
8181
8182 (define_expand "floatsisf2"
8183   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8184         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
8185   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8186   "
8187 {
8188   if (TARGET_SH4)
8189     {
8190       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8191       DONE;
8192     }
8193 }")
8194
8195 (define_insn "*floatsisf2_media"
8196   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8197         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
8198   "TARGET_SHMEDIA_FPU"
8199   "float.ls     %1, %0"
8200   [(set_attr "type" "fpconv_media")])
8201
8202 (define_insn "floatsisf2_i4"
8203   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8204         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
8205    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8206   "TARGET_SH4"
8207   "float        %1,%0"
8208   [(set_attr "type" "fp")
8209    (set_attr "fp_mode" "single")])
8210
8211 (define_insn "*floatsisf2_ie"
8212   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8213         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
8214   "TARGET_SH3E && ! TARGET_SH4"
8215   "float        %1,%0"
8216   [(set_attr "type" "fp")])
8217
8218 (define_insn "fix_truncsfdi2"
8219   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
8220         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8221   "TARGET_SHMEDIA_FPU"
8222   "ftrc.sq %1, %0"
8223   [(set_attr "type" "fpconv_media")])
8224
8225 (define_expand "fix_truncsfsi2"
8226   [(set (match_operand:SI 0 "fpul_operand" "=y")
8227         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8228   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8229   "
8230 {
8231   if (TARGET_SH4)
8232     {
8233       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
8234       DONE;
8235     }
8236 }")
8237
8238 (define_insn "*fix_truncsfsi2_media"
8239   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
8240         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8241   "TARGET_SHMEDIA_FPU"
8242   "ftrc.sl      %1, %0"
8243   [(set_attr "type" "fpconv_media")])
8244
8245 (define_insn "fix_truncsfsi2_i4"
8246   [(set (match_operand:SI 0 "fpul_operand" "=y")
8247         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8248    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8249   "TARGET_SH4"
8250   "ftrc %1,%0"
8251   [(set_attr "type" "ftrc_s")
8252    (set_attr "fp_mode" "single")])
8253
8254 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
8255 ;; fix_truncsfsi2_i4.
8256 ;; (define_insn "fix_truncsfsi2_i4_2"
8257 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8258 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
8259 ;;   (use (reg:PSI FPSCR_REG))
8260 ;;   (clobber (reg:SI FPUL_REG))]
8261 ;;  "TARGET_SH4"
8262 ;;  "#"
8263 ;;  [(set_attr "length" "4")
8264 ;;   (set_attr "fp_mode" "single")])
8265
8266 ;;(define_split
8267 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8268 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
8269 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
8270 ;;   (clobber (reg:SI FPUL_REG))]
8271 ;;  "TARGET_SH4"
8272 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
8273 ;;            (use (match_dup 2))])
8274 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
8275
8276 (define_insn "*fixsfsi"
8277   [(set (match_operand:SI 0 "fpul_operand" "=y")
8278         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8279   "TARGET_SH3E && ! TARGET_SH4"
8280   "ftrc %1,%0"
8281   [(set_attr "type" "fp")])
8282
8283 (define_insn "cmpgtsf_t"
8284   [(set (reg:SI T_REG)
8285         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8286                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8287   "TARGET_SH3E && ! TARGET_SH4"
8288   "fcmp/gt      %1,%0"
8289   [(set_attr "type" "fp")
8290    (set_attr "fp_mode" "single")])
8291
8292 (define_insn "cmpeqsf_t"
8293   [(set (reg:SI T_REG)
8294         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8295                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8296   "TARGET_SH3E && ! TARGET_SH4"
8297   "fcmp/eq      %1,%0"
8298   [(set_attr "type" "fp")
8299    (set_attr "fp_mode" "single")])
8300
8301 (define_insn "ieee_ccmpeqsf_t"
8302   [(set (reg:SI T_REG)
8303         (ior:SI (reg:SI T_REG)
8304                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8305                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
8306   "TARGET_SH3E && TARGET_IEEE && ! TARGET_SH4"
8307   "* return output_ieee_ccmpeq (insn, operands);"
8308   [(set_attr "length" "4")])
8309
8310
8311 (define_insn "cmpgtsf_t_i4"
8312   [(set (reg:SI T_REG)
8313         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8314                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8315    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8316   "TARGET_SH4"
8317   "fcmp/gt      %1,%0"
8318   [(set_attr "type" "fp")
8319    (set_attr "fp_mode" "single")])
8320
8321 (define_insn "cmpeqsf_t_i4"
8322   [(set (reg:SI T_REG)
8323         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8324                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
8325    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8326   "TARGET_SH4"
8327   "fcmp/eq      %1,%0"
8328   [(set_attr "type" "fp")
8329    (set_attr "fp_mode" "single")])
8330
8331 (define_insn "*ieee_ccmpeqsf_t_4"
8332   [(set (reg:SI T_REG)
8333         (ior:SI (reg:SI T_REG)
8334                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
8335                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
8336    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8337   "TARGET_IEEE && TARGET_SH4"
8338   "* return output_ieee_ccmpeq (insn, operands);"
8339   [(set_attr "length" "4")
8340    (set_attr "fp_mode" "single")])
8341
8342 (define_insn "cmpeqsf_media"
8343   [(set (match_operand:DI 0 "register_operand" "=r")
8344         (eq:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8345                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8346   "TARGET_SHMEDIA_FPU"
8347   "fcmpeq.s     %1, %2, %0"
8348   [(set_attr "type" "fcmp_media")])
8349
8350 (define_insn "cmpgtsf_media"
8351   [(set (match_operand:DI 0 "register_operand" "=r")
8352         (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8353                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8354   "TARGET_SHMEDIA_FPU"
8355   "fcmpgt.s     %1, %2, %0"
8356   [(set_attr "type" "fcmp_media")])
8357
8358 (define_insn "cmpgesf_media"
8359   [(set (match_operand:DI 0 "register_operand" "=r")
8360         (ge:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8361                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8362   "TARGET_SHMEDIA_FPU"
8363   "fcmpge.s     %1, %2, %0"
8364   [(set_attr "type" "fcmp_media")])
8365
8366 (define_insn "cmpunsf_media"
8367   [(set (match_operand:DI 0 "register_operand" "=r")
8368         (unordered:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
8369                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
8370   "TARGET_SHMEDIA_FPU"
8371   "fcmpun.s     %1, %2, %0"
8372   [(set_attr "type" "fcmp_media")])
8373
8374 (define_expand "cmpsf"
8375   [(set (reg:SI T_REG)
8376         (compare (match_operand:SF 0 "arith_operand" "")
8377                  (match_operand:SF 1 "arith_operand" "")))]
8378   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8379   "
8380 {
8381   sh_compare_op0 = operands[0];
8382   sh_compare_op1 = operands[1];
8383   DONE;
8384 }")
8385
8386 (define_expand "negsf2"
8387   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8388         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8389   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8390   "
8391 {
8392   if (TARGET_SH3E)
8393     {
8394       expand_sf_unop (&gen_negsf2_i, operands);
8395       DONE;
8396     }
8397 }")
8398
8399 (define_insn "*negsf2_media"
8400   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8401         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8402   "TARGET_SHMEDIA_FPU"
8403   "fneg.s       %1, %0"
8404   [(set_attr "type" "fmove_media")])
8405
8406 (define_insn "negsf2_i"
8407   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8408         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8409    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8410   "TARGET_SH3E"
8411   "fneg %0"
8412   [(set_attr "type" "fmove")
8413    (set_attr "fp_mode" "single")])
8414
8415 (define_expand "sqrtsf2"
8416   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8417         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8418   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8419   "
8420 {
8421   if (TARGET_SH3E)
8422     {
8423       expand_sf_unop (&gen_sqrtsf2_i, operands);
8424       DONE;
8425     }
8426 }")
8427
8428 (define_insn "*sqrtsf2_media"
8429   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8430         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8431   "TARGET_SHMEDIA_FPU"
8432   "fsqrt.s      %1, %0"
8433   [(set_attr "type" "fdiv_media")])
8434
8435 (define_insn "sqrtsf2_i"
8436   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8437         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8438    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8439   "TARGET_SH3E"
8440   "fsqrt        %0"
8441   [(set_attr "type" "fdiv")
8442    (set_attr "fp_mode" "single")])
8443
8444 (define_expand "abssf2"
8445   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
8446         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
8447   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
8448   "
8449 {
8450   if (TARGET_SH3E)
8451     {
8452       expand_sf_unop (&gen_abssf2_i, operands);
8453       DONE;
8454     }
8455 }")
8456
8457 (define_insn "*abssf2_media"
8458   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8459         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8460   "TARGET_SHMEDIA_FPU"
8461   "fabs.s       %1, %0"
8462   [(set_attr "type" "fmove_media")])
8463
8464 (define_insn "abssf2_i"
8465   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8466         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
8467    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8468   "TARGET_SH3E"
8469   "fabs %0"
8470   [(set_attr "type" "fmove")
8471    (set_attr "fp_mode" "single")])
8472
8473 (define_expand "adddf3"
8474   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8475         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8476                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8477   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8478   "
8479 {
8480   if (TARGET_SH4)
8481     {
8482       expand_df_binop (&gen_adddf3_i, operands);
8483       DONE;
8484     }
8485 }")
8486
8487 (define_insn "*adddf3_media"
8488   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8489         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
8490                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8491   "TARGET_SHMEDIA_FPU"
8492   "fadd.d       %1, %2, %0"
8493   [(set_attr "type" "dfparith_media")])
8494
8495 (define_insn "adddf3_i"
8496   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8497         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
8498                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8499    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8500   "TARGET_SH4"
8501   "fadd %2,%0"
8502   [(set_attr "type" "dfp_arith")
8503    (set_attr "fp_mode" "double")])
8504
8505 (define_expand "subdf3"
8506   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8507         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8508                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8509   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8510   "
8511 {
8512   if (TARGET_SH4)
8513     {
8514       expand_df_binop (&gen_subdf3_i, operands);
8515       DONE;
8516     }
8517 }")
8518
8519 (define_insn "*subdf3_media"
8520   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8521         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
8522                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8523   "TARGET_SHMEDIA_FPU"
8524   "fsub.d       %1, %2, %0"
8525   [(set_attr "type" "dfparith_media")])
8526
8527 (define_insn "subdf3_i"
8528   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8529         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
8530                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8531    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8532   "TARGET_SH4"
8533   "fsub %2,%0"
8534   [(set_attr "type" "dfp_arith")
8535    (set_attr "fp_mode" "double")])
8536
8537 (define_expand "muldf3"
8538   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8539         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8540                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8541   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8542   "
8543 {
8544   if (TARGET_SH4)
8545     {
8546       expand_df_binop (&gen_muldf3_i, operands);
8547       DONE;
8548     }
8549 }")
8550
8551 (define_insn "*muldf3_media"
8552   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8553         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
8554                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8555   "TARGET_SHMEDIA_FPU"
8556   "fmul.d       %1, %2, %0"
8557   [(set_attr "type" "dfmul_media")])
8558
8559 (define_insn "muldf3_i"
8560   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8561         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
8562                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8563    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8564   "TARGET_SH4"
8565   "fmul %2,%0"
8566   [(set_attr "type" "dfp_arith")
8567    (set_attr "fp_mode" "double")])
8568
8569 (define_expand "divdf3"
8570   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8571         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
8572                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
8573   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8574   "
8575 {
8576   if (TARGET_SH4)
8577     {
8578       expand_df_binop (&gen_divdf3_i, operands);
8579       DONE;
8580     }
8581 }")
8582
8583 (define_insn "*divdf3_media"
8584   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8585         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
8586                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8587   "TARGET_SHMEDIA_FPU"
8588   "fdiv.d       %1, %2, %0"
8589   [(set_attr "type" "dfdiv_media")])
8590
8591 (define_insn "divdf3_i"
8592   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8593         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
8594                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8595    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8596   "TARGET_SH4"
8597   "fdiv %2,%0"
8598   [(set_attr "type" "dfdiv")
8599    (set_attr "fp_mode" "double")])
8600
8601 (define_insn "floatdidf2"
8602   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8603         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
8604   "TARGET_SHMEDIA_FPU"
8605   "float.qd     %1, %0"
8606   [(set_attr "type" "dfpconv_media")])
8607
8608 (define_expand "floatsidf2"
8609   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8610         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
8611   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8612   "
8613 {
8614   if (TARGET_SH4)
8615     {
8616       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
8617                                       get_fpscr_rtx ()));
8618       DONE;
8619     }
8620 }")
8621
8622 (define_insn "*floatsidf2_media"
8623   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8624         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
8625   "TARGET_SHMEDIA_FPU"
8626   "float.ld     %1, %0"
8627   [(set_attr "type" "dfpconv_media")])
8628
8629 (define_insn "floatsidf2_i"
8630   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8631         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
8632    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8633   "TARGET_SH4"
8634   "float        %1,%0"
8635   [(set_attr "type" "dfp_conv")
8636    (set_attr "fp_mode" "double")])
8637
8638 (define_insn "fix_truncdfdi2"
8639   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
8640         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8641   "TARGET_SHMEDIA_FPU"
8642   "ftrc.dq      %1, %0"
8643   [(set_attr "type" "dfpconv_media")])
8644
8645 (define_expand "fix_truncdfsi2"
8646   [(set (match_operand:SI 0 "fpul_operand" "")
8647         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
8648   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8649   "
8650 {
8651   if (TARGET_SH4)
8652     {
8653       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
8654                                           get_fpscr_rtx ()));
8655       DONE;
8656     }
8657 }")
8658
8659 (define_insn "*fix_truncdfsi2_media"
8660   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
8661         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8662   "TARGET_SHMEDIA_FPU"
8663   "ftrc.dl      %1, %0"
8664   [(set_attr "type" "dfpconv_media")])
8665
8666 (define_insn "fix_truncdfsi2_i"
8667   [(set (match_operand:SI 0 "fpul_operand" "=y")
8668         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
8669    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8670   "TARGET_SH4"
8671   "ftrc %1,%0"
8672   [(set_attr "type" "dfp_conv")
8673    (set_attr "dfp_comp" "no")
8674    (set_attr "fp_mode" "double")])
8675
8676 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
8677 ;; fix_truncdfsi2_i.
8678 ;; (define_insn "fix_truncdfsi2_i4"
8679 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8680 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
8681 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
8682 ;;    (clobber (reg:SI FPUL_REG))]
8683 ;;   "TARGET_SH4"
8684 ;;   "#"
8685 ;;   [(set_attr "length" "4")
8686 ;;    (set_attr "fp_mode" "double")])
8687 ;;
8688 ;; (define_split
8689 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8690 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
8691 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
8692 ;;    (clobber (reg:SI FPUL_REG))]
8693 ;;   "TARGET_SH4"
8694 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
8695 ;;            (use (match_dup 2))])
8696 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
8697
8698 (define_insn "cmpgtdf_t"
8699   [(set (reg:SI T_REG)
8700         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
8701                (match_operand:DF 1 "arith_reg_operand" "f")))
8702    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8703   "TARGET_SH4"
8704   "fcmp/gt      %1,%0"
8705   [(set_attr "type" "dfp_cmp")
8706    (set_attr "fp_mode" "double")])
8707
8708 (define_insn "cmpeqdf_t"
8709   [(set (reg:SI T_REG)
8710         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
8711                (match_operand:DF 1 "arith_reg_operand" "f")))
8712    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8713   "TARGET_SH4"
8714   "fcmp/eq      %1,%0"
8715   [(set_attr "type" "dfp_cmp")
8716    (set_attr "fp_mode" "double")])
8717
8718 (define_insn "*ieee_ccmpeqdf_t"
8719   [(set (reg:SI T_REG)
8720         (ior:SI (reg:SI T_REG)
8721                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
8722                        (match_operand:DF 1 "arith_reg_operand" "f"))))
8723    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8724   "TARGET_IEEE && TARGET_SH4"
8725   "* return output_ieee_ccmpeq (insn, operands);"
8726   [(set_attr "length" "4")
8727    (set_attr "fp_mode" "double")])
8728
8729 (define_insn "cmpeqdf_media"
8730   [(set (match_operand:DI 0 "register_operand" "=r")
8731         (eq:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8732                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8733   "TARGET_SHMEDIA_FPU"
8734   "fcmpeq.d     %1,%2,%0"
8735   [(set_attr "type" "fcmp_media")])
8736
8737 (define_insn "cmpgtdf_media"
8738   [(set (match_operand:DI 0 "register_operand" "=r")
8739         (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8740                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8741   "TARGET_SHMEDIA_FPU"
8742   "fcmpgt.d     %1,%2,%0"
8743   [(set_attr "type" "fcmp_media")])
8744
8745 (define_insn "cmpgedf_media"
8746   [(set (match_operand:DI 0 "register_operand" "=r")
8747         (ge:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8748                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8749   "TARGET_SHMEDIA_FPU"
8750   "fcmpge.d     %1,%2,%0"
8751   [(set_attr "type" "fcmp_media")])
8752
8753 (define_insn "cmpundf_media"
8754   [(set (match_operand:DI 0 "register_operand" "=r")
8755         (unordered:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8756                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8757   "TARGET_SHMEDIA_FPU"
8758   "fcmpun.d     %1,%2,%0"
8759   [(set_attr "type" "fcmp_media")])
8760
8761 (define_expand "cmpdf"
8762   [(set (reg:SI T_REG)
8763         (compare (match_operand:DF 0 "arith_operand" "")
8764                  (match_operand:DF 1 "arith_operand" "")))]
8765   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8766   "
8767 {
8768   sh_compare_op0 = operands[0];
8769   sh_compare_op1 = operands[1];
8770   DONE;
8771 }")
8772
8773 (define_expand "negdf2"
8774   [(set (match_operand:DF 0 "arith_reg_operand" "")
8775         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
8776   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8777   "
8778 {
8779   if (TARGET_SH4)
8780     {
8781       expand_df_unop (&gen_negdf2_i, operands);
8782       DONE;
8783     }
8784 }")
8785
8786 (define_insn "*negdf2_media"
8787   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8788         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8789   "TARGET_SHMEDIA_FPU"
8790   "fneg.d       %1, %0"
8791   [(set_attr "type" "fmove_media")])
8792
8793 (define_insn "negdf2_i"
8794   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
8795         (neg:DF (match_operand:DF 1 "arith_reg_operand" "0")))
8796    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8797   "TARGET_SH4"
8798   "fneg %0"
8799   [(set_attr "type" "fmove")
8800    (set_attr "fp_mode" "double")])
8801
8802 (define_expand "sqrtdf2"
8803   [(set (match_operand:DF 0 "arith_reg_operand" "")
8804         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
8805   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8806   "
8807 {
8808   if (TARGET_SH4)
8809     {
8810       expand_df_unop (&gen_sqrtdf2_i, operands);
8811       DONE;
8812     }
8813 }")
8814
8815 (define_insn "*sqrtdf2_media"
8816   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8817         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8818   "TARGET_SHMEDIA_FPU"
8819   "fsqrt.d      %1, %0"
8820   [(set_attr "type" "dfdiv_media")])
8821
8822 (define_insn "sqrtdf2_i"
8823   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
8824         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "0")))
8825    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8826   "TARGET_SH4"
8827   "fsqrt        %0"
8828   [(set_attr "type" "dfdiv")
8829    (set_attr "fp_mode" "double")])
8830
8831 (define_expand "absdf2"
8832   [(set (match_operand:DF 0 "arith_reg_operand" "")
8833         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
8834   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8835   "
8836 {
8837   if (TARGET_SH4)
8838     {
8839       expand_df_unop (&gen_absdf2_i, operands);
8840       DONE;
8841     }
8842 }")
8843
8844 (define_insn "*absdf2_media"
8845   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8846         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8847   "TARGET_SHMEDIA_FPU"
8848   "fabs.d       %1, %0"
8849   [(set_attr "type" "fmove_media")])
8850
8851 (define_insn "absdf2_i"
8852   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
8853         (abs:DF (match_operand:DF 1 "arith_reg_operand" "0")))
8854    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8855   "TARGET_SH4"
8856   "fabs %0"
8857   [(set_attr "type" "fmove")
8858    (set_attr "fp_mode" "double")])
8859
8860 (define_expand "extendsfdf2"
8861   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8862         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
8863   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8864   "
8865 {
8866   if (TARGET_SH4)
8867     {
8868       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
8869                                         get_fpscr_rtx ()));
8870       DONE;
8871     }
8872 }")
8873
8874 (define_insn "*extendsfdf2_media"
8875   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8876         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8877   "TARGET_SHMEDIA_FPU"
8878   "fcnv.sd      %1, %0"
8879   [(set_attr "type" "dfpconv_media")])
8880
8881 (define_insn "extendsfdf2_i4"
8882   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8883         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
8884    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8885   "TARGET_SH4"
8886   "fcnvsd  %1,%0"
8887   [(set_attr "type" "fp")
8888    (set_attr "fp_mode" "double")])
8889
8890 (define_expand "truncdfsf2"
8891   [(set (match_operand:SF 0 "fpul_operand" "")
8892         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
8893   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8894   "
8895 {
8896   if (TARGET_SH4)
8897     {
8898       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
8899                                        get_fpscr_rtx ()));
8900       DONE;
8901     }
8902 }")
8903
8904 (define_insn "*truncdfsf2_media"
8905   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8906         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8907   "TARGET_SHMEDIA_FPU"
8908   "fcnv.ds      %1, %0"
8909   [(set_attr "type" "dfpconv_media")])
8910
8911 (define_insn "truncdfsf2_i4"
8912   [(set (match_operand:SF 0 "fpul_operand" "=y")
8913         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
8914    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8915   "TARGET_SH4"
8916   "fcnvds  %1,%0"
8917   [(set_attr "type" "fp")
8918    (set_attr "fp_mode" "double")])
8919 \f
8920 ;; Bit field extract patterns.  These give better code for packed bitfields,
8921 ;; because they allow auto-increment addresses to be generated.
8922
8923 (define_expand "insv"
8924   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
8925                          (match_operand:SI 1 "immediate_operand" "")
8926                          (match_operand:SI 2 "immediate_operand" ""))
8927         (match_operand:SI 3 "general_operand" ""))]
8928   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
8929   "
8930 {
8931   rtx addr_target, orig_address, shift_reg, qi_val;
8932   HOST_WIDE_INT bitsize, size, v;
8933   rtx x = operands[3];
8934
8935   /* ??? expmed doesn't care for non-register predicates.  */
8936   if (! memory_operand (operands[0], VOIDmode)
8937       || ! immediate_operand (operands[1], VOIDmode)
8938       || ! immediate_operand (operands[2], VOIDmode)
8939       || ! general_operand (x, VOIDmode))
8940     FAIL;
8941   /* If this isn't a 16 / 24 / 32 bit field, or if
8942      it doesn't start on a byte boundary, then fail.  */
8943   bitsize = INTVAL (operands[1]);
8944   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
8945       || (INTVAL (operands[2]) % 8) != 0)
8946     FAIL;
8947
8948   size = bitsize / 8;
8949   orig_address = XEXP (operands[0], 0);
8950   shift_reg = gen_reg_rtx (SImode);
8951   if (GET_CODE (x) == CONST_INT)
8952     {
8953       v = INTVAL (x);
8954       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
8955     }
8956   else
8957     {
8958       emit_insn (gen_movsi (shift_reg, operands[3]));
8959       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
8960     }
8961   addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
8962
8963   operands[0] = replace_equiv_address (operands[0], addr_target);
8964   emit_insn (gen_movqi (operands[0], qi_val));
8965
8966   while (size -= 1)
8967     {
8968       if (GET_CODE (x) == CONST_INT)
8969         qi_val
8970           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
8971       else
8972         {
8973           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
8974           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
8975         }
8976       emit_insn (gen_addsi3 (addr_target, addr_target, GEN_INT (-1)));
8977       emit_insn (gen_movqi (operands[0], qi_val));
8978     }
8979
8980   DONE;
8981 }")
8982 \f
8983 ;; -------------------------------------------------------------------------
8984 ;; Peepholes
8985 ;; -------------------------------------------------------------------------
8986
8987 ;; This matches cases where a stack pointer increment at the start of the
8988 ;; epilogue combines with a stack slot read loading the return value.
8989
8990 (define_peephole
8991   [(set (match_operand:SI 0 "arith_reg_operand" "")
8992         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
8993    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
8994   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
8995   "mov.l        @%1+,%0")
8996
8997 ;; See the comment on the dt combiner pattern above.
8998
8999 (define_peephole
9000   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
9001         (plus:SI (match_dup 0)
9002                  (const_int -1)))
9003    (set (reg:SI T_REG)
9004         (eq:SI (match_dup 0)
9005                (const_int 0)))]
9006   "TARGET_SH2"
9007   "dt   %0")
9008
9009 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
9010 ;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
9011 ;; reload when the constant is too large for a reg+offset address.
9012
9013 ;; ??? We would get much better code if this was done in reload.  This would
9014 ;; require modifying find_reloads_address to recognize that if the constant
9015 ;; is out-of-range for an immediate add, then we get better code by reloading
9016 ;; the constant into a register than by reloading the sum into a register,
9017 ;; since the former is one instruction shorter if the address does not need
9018 ;; to be offsettable.  Unfortunately this does not work, because there is
9019 ;; only one register, r0, that can be used as an index register.  This register
9020 ;; is also the function return value register.  So, if we try to force reload
9021 ;; to use double-reg addresses, then we end up with some instructions that
9022 ;; need to use r0 twice.  The only way to fix this is to change the calling
9023 ;; convention so that r0 is not used to return values.
9024
9025 (define_peephole
9026   [(set (match_operand:SI 0 "register_operand" "=r")
9027         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9028    (set (mem:SI (match_dup 0))
9029         (match_operand:SI 2 "general_movsrc_operand" ""))]
9030   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9031   "mov.l        %2,@(%0,%1)")
9032
9033 (define_peephole
9034   [(set (match_operand:SI 0 "register_operand" "=r")
9035         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9036    (set (match_operand:SI 2 "general_movdst_operand" "")
9037         (mem:SI (match_dup 0)))]
9038   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9039   "mov.l        @(%0,%1),%2")
9040
9041 (define_peephole
9042   [(set (match_operand:SI 0 "register_operand" "=r")
9043         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9044    (set (mem:HI (match_dup 0))
9045         (match_operand:HI 2 "general_movsrc_operand" ""))]
9046   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9047   "mov.w        %2,@(%0,%1)")
9048
9049 (define_peephole
9050   [(set (match_operand:SI 0 "register_operand" "=r")
9051         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9052    (set (match_operand:HI 2 "general_movdst_operand" "")
9053         (mem:HI (match_dup 0)))]
9054   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9055   "mov.w        @(%0,%1),%2")
9056
9057 (define_peephole
9058   [(set (match_operand:SI 0 "register_operand" "=r")
9059         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9060    (set (mem:QI (match_dup 0))
9061         (match_operand:QI 2 "general_movsrc_operand" ""))]
9062   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9063   "mov.b        %2,@(%0,%1)")
9064
9065 (define_peephole
9066   [(set (match_operand:SI 0 "register_operand" "=r")
9067         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9068    (set (match_operand:QI 2 "general_movdst_operand" "")
9069         (mem:QI (match_dup 0)))]
9070   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
9071   "mov.b        @(%0,%1),%2")
9072
9073 (define_peephole
9074   [(set (match_operand:SI 0 "register_operand" "=r")
9075         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9076    (set (mem:SF (match_dup 0))
9077         (match_operand:SF 2 "general_movsrc_operand" ""))]
9078   "TARGET_SH1 && REGNO (operands[0]) == 0
9079    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
9080        || (GET_CODE (operands[2]) == SUBREG
9081            && REGNO (SUBREG_REG (operands[2])) < 16))
9082    && reg_unused_after (operands[0], insn)"
9083   "mov.l        %2,@(%0,%1)")
9084
9085 (define_peephole
9086   [(set (match_operand:SI 0 "register_operand" "=r")
9087         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9088    (set (match_operand:SF 2 "general_movdst_operand" "")
9089
9090         (mem:SF (match_dup 0)))]
9091   "TARGET_SH1 && REGNO (operands[0]) == 0
9092    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
9093        || (GET_CODE (operands[2]) == SUBREG
9094            && REGNO (SUBREG_REG (operands[2])) < 16))
9095    && reg_unused_after (operands[0], insn)"
9096   "mov.l        @(%0,%1),%2")
9097
9098 (define_peephole
9099   [(set (match_operand:SI 0 "register_operand" "=r")
9100         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9101    (set (mem:SF (match_dup 0))
9102         (match_operand:SF 2 "general_movsrc_operand" ""))]
9103   "TARGET_SH3E && REGNO (operands[0]) == 0
9104    && ((GET_CODE (operands[2]) == REG
9105         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
9106        || (GET_CODE (operands[2]) == SUBREG
9107            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
9108    && reg_unused_after (operands[0], insn)"
9109   "fmov{.s|}    %2,@(%0,%1)")
9110
9111 (define_peephole
9112   [(set (match_operand:SI 0 "register_operand" "=r")
9113         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
9114    (set (match_operand:SF 2 "general_movdst_operand" "")
9115
9116         (mem:SF (match_dup 0)))]
9117   "TARGET_SH3E && REGNO (operands[0]) == 0
9118    && ((GET_CODE (operands[2]) == REG
9119         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
9120        || (GET_CODE (operands[2]) == SUBREG
9121            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
9122    && reg_unused_after (operands[0], insn)"
9123   "fmov{.s|}    @(%0,%1),%2")
9124
9125 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
9126 (define_insn "sp_switch_1"
9127   [(const_int 1)]
9128   "TARGET_SH1"
9129   "*
9130 {
9131   rtx xoperands[1];
9132
9133   xoperands[0] = sp_switch;
9134   output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", xoperands);
9135   output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", xoperands);
9136   return \"mov r0,r15\";
9137 }"
9138   [(set_attr "length" "10")])
9139
9140 ;; Switch back to the original stack for interrupt functions with the
9141 ;; sp_switch attribute.  */
9142 (define_insn "sp_switch_2"
9143   [(const_int 2)]
9144   "TARGET_SH1"
9145   "mov.l @r15+,r15\;mov.l @r15+,r0"
9146   [(set_attr "length" "4")])
9147
9148 ;; Integer vector moves
9149
9150 (define_expand "movv8qi"
9151   [(set (match_operand:V8QI 0 "general_movdst_operand" "")
9152         (match_operand:V8QI 1 "general_movsrc_operand" ""))]
9153   "TARGET_SHMEDIA"
9154   "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
9155
9156 (define_insn "movv8qi_i"
9157   [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
9158         (match_operand:V8QI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))]
9159   "TARGET_SHMEDIA
9160    && (register_operand (operands[0], V8QImode)
9161        || register_operand (operands[1], V8QImode))"
9162   "@
9163         add     %1, r63, %0
9164         movi    %1, %0
9165         #
9166         ld%M1.q %m1, %0
9167         st%M0.q %m0, %1"
9168   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9169    (set_attr "length" "4,4,16,4,4")])
9170
9171 (define_split
9172   [(set (match_operand:V8QI 0 "arith_reg_dest" "")
9173         (subreg:V8QI (const_int 0) 0))]
9174   "TARGET_SHMEDIA"
9175   [(set (match_dup 0)
9176         (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
9177                             (const_int 0) (const_int 0) (const_int 0)
9178                             (const_int 0) (const_int 0)]))])
9179
9180 (define_split
9181   [(set (match_operand 0 "arith_reg_dest" "")
9182         (match_operand 1 "sh_rep_vec" ""))]
9183   "TARGET_SHMEDIA && reload_completed
9184    && GET_MODE (operands[0]) == GET_MODE (operands[1])
9185    && VECTOR_MODE_SUPPORTED_P (GET_MODE (operands[0]))
9186    && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
9187    && (XVECEXP (operands[1], 0, 0) != const0_rtx
9188        || XVECEXP (operands[1], 0, 1) != const0_rtx)
9189    && (XVECEXP (operands[1], 0, 0) != constm1_rtx
9190        || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
9191   [(set (match_dup 0) (match_dup 1))
9192    (match_dup 2)]
9193   "
9194 {
9195   int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
9196   rtx elt1 = XVECEXP (operands[1], 0, 1);
9197
9198   if (unit_size > 2)
9199     operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
9200   else
9201     {
9202       if (unit_size < 2)
9203         operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
9204       operands[2] = gen_mperm_w0 (operands[0], operands[0]);
9205     }
9206   operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
9207   operands[1] = XVECEXP (operands[1], 0, 0);
9208   if (unit_size < 2)
9209     {
9210       if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (elt1) == CONST_INT)
9211         operands[1] = GEN_INT (TARGET_LITTLE_ENDIAN
9212                                ? INTVAL (operands[1]) + (INTVAL (elt1) << 8)
9213                                : (INTVAL (operands[1]) << 8) + INTVAL (elt1));
9214       else
9215         {
9216           operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
9217           operands[1]
9218             = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
9219         }
9220     }
9221 }")
9222
9223 (define_split
9224   [(set (match_operand 0 "arith_reg_dest" "")
9225         (match_operand 1 "sh_const_vec" ""))]
9226   "TARGET_SHMEDIA && reload_completed
9227    && GET_MODE (operands[0]) == GET_MODE (operands[1])
9228    && VECTOR_MODE_SUPPORTED_P (GET_MODE (operands[0]))
9229    && operands[1] != CONST0_RTX (GET_MODE (operands[1]))"
9230   [(set (match_dup 0) (match_dup 1))]
9231   "
9232 {
9233   rtx v = operands[1];
9234   enum machine_mode new_mode
9235     = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
9236
9237   operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
9238   operands[1]
9239     = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
9240 }")
9241
9242 (define_expand "movv2hi"
9243   [(set (match_operand:V2HI 0 "general_movdst_operand" "")
9244         (match_operand:V2HI 1 "general_movsrc_operand" ""))]
9245   "TARGET_SHMEDIA"
9246   "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
9247
9248 (define_insn "movv2hi_i"
9249   [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
9250         (match_operand:V2HI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))]
9251   "TARGET_SHMEDIA
9252    && (register_operand (operands[0], V2HImode)
9253        || register_operand (operands[1], V2HImode))"
9254   "@
9255         addz.l  %1, r63, %0
9256         movi    %1, %0
9257         #
9258         ld%M1.l %m1, %0
9259         st%M0.l %m0, %1"
9260   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9261    (set_attr "length" "4,4,16,4,4")])
9262
9263 (define_expand "movv4hi"
9264   [(set (match_operand:V4HI 0 "general_movdst_operand" "")
9265         (match_operand:V4HI 1 "general_movsrc_operand" ""))]
9266   "TARGET_SHMEDIA"
9267   "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
9268
9269 (define_insn "movv4hi_i"
9270   [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
9271         (match_operand:V4HI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))]
9272   "TARGET_SHMEDIA
9273    && (register_operand (operands[0], V4HImode)
9274        || register_operand (operands[1], V4HImode))"
9275   "@
9276         add     %1, r63, %0
9277         movi    %1, %0
9278         #
9279         ld%M1.q %m1, %0
9280         st%M0.q %m0, %1"
9281   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9282    (set_attr "length" "4,4,16,4,4")])
9283
9284 (define_expand "movv2si"
9285   [(set (match_operand:V2SI 0 "general_movdst_operand" "")
9286         (match_operand:V2SI 1 "general_movsrc_operand" ""))]
9287   "TARGET_SHMEDIA"
9288   "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
9289
9290 (define_insn "movv2si_i"
9291   [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
9292         (match_operand:V2SI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))]
9293   "TARGET_SHMEDIA
9294    && (register_operand (operands[0], V2SImode)
9295        || register_operand (operands[1], V2SImode))"
9296   "@
9297         add     %1, r63, %0
9298         #
9299         #
9300         ld%M1.q %m1, %0
9301         st%M0.q %m0, %1"
9302   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
9303    (set_attr "length" "4,4,16,4,4")])
9304
9305 ;; Multimedia Intrinsics
9306
9307 (define_insn "absv2si2"
9308   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9309         (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
9310   "TARGET_SHMEDIA"
9311   "mabs.l       %1, %0"
9312   [(set_attr "type" "mcmp_media")])
9313
9314 (define_insn "absv4hi2"
9315   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9316         (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
9317   "TARGET_SHMEDIA"
9318   "mabs.w       %1, %0"
9319   [(set_attr "type" "mcmp_media")])
9320
9321 (define_insn "addv2si3"
9322   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9323         (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
9324                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9325   "TARGET_SHMEDIA"
9326   "madd.l       %1, %2, %0"
9327   [(set_attr "type" "arith_media")])
9328
9329 (define_insn "addv4hi3"
9330   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9331         (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
9332                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9333   "TARGET_SHMEDIA"
9334   "madd.w       %1, %2, %0"
9335   [(set_attr "type" "arith_media")])
9336
9337 (define_insn "ssaddv2si3"
9338   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9339         (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
9340                       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9341   "TARGET_SHMEDIA"
9342   "madds.l      %1, %2, %0"
9343   [(set_attr "type" "mcmp_media")])
9344
9345 (define_insn "usaddv8qi3"
9346   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9347         (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
9348                       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
9349   "TARGET_SHMEDIA"
9350   "madds.ub     %1, %2, %0"
9351   [(set_attr "type" "mcmp_media")])
9352
9353 (define_insn "ssaddv4hi3"
9354   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9355         (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
9356                       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9357   "TARGET_SHMEDIA"
9358   "madds.w      %1, %2, %0"
9359   [(set_attr "type" "mcmp_media")])
9360
9361 (define_insn "negcmpeqv8qi"
9362   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9363         (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rU")
9364                            (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))))]
9365   "TARGET_SHMEDIA"
9366   "mcmpeq.b     %N1, %N2, %0"
9367   [(set_attr "type" "mcmp_media")])
9368
9369 (define_insn "negcmpeqv2si"
9370   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9371         (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rU")
9372                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))))]
9373   "TARGET_SHMEDIA"
9374   "mcmpeq.l     %N1, %N2, %0"
9375   [(set_attr "type" "mcmp_media")])
9376
9377 (define_insn "negcmpeqv4hi"
9378   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9379         (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rU")
9380                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))]
9381   "TARGET_SHMEDIA"
9382   "mcmpeq.w     %N1, %N2, %0"
9383   [(set_attr "type" "mcmp_media")])
9384
9385 (define_insn "negcmpgtuv8qi"
9386   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9387         (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rU")
9388                             (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))))]
9389   "TARGET_SHMEDIA"
9390   "mcmpgt.ub    %N1, %N2, %0"
9391   [(set_attr "type" "mcmp_media")])
9392
9393 (define_insn "negcmpgtv2si"
9394   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9395         (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rU")
9396                            (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))))]
9397   "TARGET_SHMEDIA"
9398   "mcmpgt.l     %N1, %N2, %0"
9399   [(set_attr "type" "mcmp_media")])
9400
9401 (define_insn "negcmpgtv4hi"
9402   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9403         (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rU")
9404                            (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))]
9405   "TARGET_SHMEDIA"
9406   "mcmpgt.w     %N1, %N2, %0"
9407   [(set_attr "type" "mcmp_media")])
9408
9409 (define_insn "mcmv"
9410   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9411         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9412                         (match_operand:DI 2 "arith_reg_operand" "r"))
9413                 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
9414                         (not:DI (match_dup 2)))))]
9415   "TARGET_SHMEDIA"
9416   "mcmv %N1, %2, %0"
9417   [(set_attr "type" "arith_media")])
9418
9419 (define_insn "mcnvs_lw"
9420   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9421         (vec_concat:V4HI
9422          (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU"))
9423          (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))))]
9424   "TARGET_SHMEDIA"
9425   "mcnvs.lw     %N1, %N2, %0"
9426   [(set_attr "type" "mcmp_media")])
9427
9428 (define_insn "mcnvs_wb"
9429   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9430         (vec_concat:V8QI
9431          (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU"))
9432          (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))]
9433   "TARGET_SHMEDIA"
9434   "mcnvs.wb     %N1, %N2, %0"
9435   [(set_attr "type" "mcmp_media")])
9436
9437 (define_insn "mcnvs_wub"
9438   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
9439         (vec_concat:V8QI
9440          (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU"))
9441          (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))]
9442   "TARGET_SHMEDIA"
9443   "mcnvs.wub    %N1, %N2, %0"
9444   [(set_attr "type" "mcmp_media")])
9445
9446 (define_insn "mextr_rl"
9447   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9448         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9449                              (match_operand:HI 3 "mextr_bit_offset" "i"))
9450                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
9451                           (match_operand:HI 4 "mextr_bit_offset" "i"))))]
9452   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
9453   "*
9454 {
9455   static char templ[16];
9456
9457   sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
9458            (int) INTVAL (operands[3]) >> 3);
9459   return templ;
9460 }"
9461   [(set_attr "type" "arith_media")])
9462
9463 (define_insn "*mextr_lr"
9464   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9465         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9466                            (match_operand:HI 3 "mextr_bit_offset" "i"))
9467                (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
9468                             (match_operand:HI 4 "mextr_bit_offset" "i"))))]
9469   "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
9470   "*
9471 {
9472   static char templ[16];
9473
9474   sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
9475            (int) INTVAL (operands[4]) >> 3);
9476   return templ;
9477 }"
9478   [(set_attr "type" "arith_media")])
9479
9480 ; mextrN can be modelled with vec_select / vec_concat, but the selection
9481 ; vector then varies depending on endianness.
9482 (define_expand "mextr1"
9483   [(match_operand:DI 0 "arith_reg_dest" "")
9484    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9485    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9486   "TARGET_SHMEDIA"
9487   "
9488 {
9489   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9490                            GEN_INT (1 * 8), GEN_INT (7 * 8)));
9491   DONE;
9492 }")
9493
9494 (define_expand "mextr2"
9495   [(match_operand:DI 0 "arith_reg_dest" "")
9496    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9497    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9498   "TARGET_SHMEDIA"
9499   "
9500 {
9501   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9502                            GEN_INT (2 * 8), GEN_INT (6 * 8)));
9503   DONE;
9504 }")
9505
9506 (define_expand "mextr3"
9507   [(match_operand:DI 0 "arith_reg_dest" "")
9508    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9509    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9510   "TARGET_SHMEDIA"
9511   "
9512 {
9513   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9514                            GEN_INT (3 * 8), GEN_INT (5 * 8)));
9515   DONE;
9516 }")
9517
9518 (define_expand "mextr4"
9519   [(match_operand:DI 0 "arith_reg_dest" "")
9520    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9521    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9522   "TARGET_SHMEDIA"
9523   "
9524 {
9525   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9526                            GEN_INT (4 * 8), GEN_INT (4 * 8)));
9527   DONE;
9528 }")
9529
9530 (define_expand "mextr5"
9531   [(match_operand:DI 0 "arith_reg_dest" "")
9532    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9533    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9534   "TARGET_SHMEDIA"
9535   "
9536 {
9537   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9538                            GEN_INT (5 * 8), GEN_INT (3 * 8)));
9539   DONE;
9540 }")
9541
9542 (define_expand "mextr6"
9543   [(match_operand:DI 0 "arith_reg_dest" "")
9544    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9545    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9546   "TARGET_SHMEDIA"
9547   "
9548 {
9549   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9550                            GEN_INT (6 * 8), GEN_INT (2 * 8)));
9551   DONE;
9552 }")
9553
9554 (define_expand "mextr7"
9555   [(match_operand:DI 0 "arith_reg_dest" "")
9556    (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
9557    (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
9558   "TARGET_SHMEDIA"
9559   "
9560 {
9561   emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
9562                            GEN_INT (7 * 8), GEN_INT (1 * 8)));
9563   DONE;
9564 }")
9565
9566 (define_expand "mmacfx_wl"
9567   [(match_operand:V2SI 0 "arith_reg_dest" "")
9568    (match_operand:V2HI 1 "extend_reg_operand" "")
9569    (match_operand:V2HI 2 "extend_reg_operand" "")
9570    (match_operand:V2SI 3 "arith_reg_operand" "")]
9571   "TARGET_SHMEDIA"
9572   "
9573 {
9574   emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
9575                               operands[1], operands[2]));
9576   DONE;
9577 }")
9578
9579 (define_insn "mmacfx_wl_i"
9580   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9581         (ss_plus:V2SI
9582          (match_operand:V2SI 1 "arith_reg_operand" "0")
9583          (ss_truncate:V2SI
9584           (ashift:V2DI
9585            (sign_extend:V2DI
9586             (mult:V2SI
9587              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
9588              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
9589            (const_int 1)))))]
9590   "TARGET_SHMEDIA"
9591   "mmacfx.wl    %2, %3, %0"
9592   [(set_attr "type" "mac_media")])
9593
9594 (define_expand "mmacnfx_wl"
9595   [(match_operand:V2SI 0 "arith_reg_dest" "")
9596    (match_operand:V2HI 1 "extend_reg_operand" "")
9597    (match_operand:V2HI 2 "extend_reg_operand" "")
9598    (match_operand:V2SI 3 "arith_reg_operand" "")]
9599   "TARGET_SHMEDIA"
9600   "
9601 {
9602   emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
9603                                operands[1], operands[2]));
9604   DONE;
9605 }")
9606
9607 (define_insn "mmacnfx_wl_i"
9608   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9609         (ss_minus:V2SI
9610          (match_operand:V2SI 1 "arith_reg_operand" "0")
9611          (ss_truncate:V2SI
9612           (ashift:V2DI
9613            (sign_extend:V2DI
9614             (mult:V2SI
9615              (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
9616              (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
9617            (const_int 1)))))]
9618   "TARGET_SHMEDIA"
9619   "mmacnfx.wl   %2, %3, %0"
9620   [(set_attr "type" "mac_media")])
9621
9622 (define_insn "mulv2si3"
9623   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9624         (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
9625                    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
9626   "TARGET_SHMEDIA"
9627   "mmul.l       %1, %2, %0"
9628   [(set_attr "type" "d2mpy_media")])
9629
9630 (define_insn "mulv4hi3"
9631   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9632         (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
9633                    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
9634   "TARGET_SHMEDIA"
9635   "mmul.w       %1, %2, %0"
9636   [(set_attr "type" "dmpy_media")])
9637
9638 (define_insn "mmulfx_l"
9639   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9640         (ss_truncate:V2SI
9641          (ashiftrt:V2DI
9642           (mult:V2DI
9643            (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
9644            (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
9645           (const_int 31))))]
9646   "TARGET_SHMEDIA"
9647   "mmulfx.l     %1, %2, %0"
9648   [(set_attr "type" "d2mpy_media")])
9649
9650 (define_insn "mmulfx_w"
9651   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9652         (ss_truncate:V4HI
9653          (ashiftrt:V4SI
9654           (mult:V4SI
9655            (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9656            (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
9657           (const_int 15))))]
9658   "TARGET_SHMEDIA"
9659   "mmulfx.w     %1, %2, %0"
9660   [(set_attr "type" "dmpy_media")])
9661
9662 (define_insn "mmulfxrp_w"
9663   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9664         (ss_truncate:V4HI
9665          (ashiftrt:V4SI
9666           (plus:V4SI
9667            (mult:V4SI
9668             (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9669             (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
9670            (const_int 16384))
9671           (const_int 15))))]
9672   "TARGET_SHMEDIA"
9673   "mmulfxrp.w   %1, %2, %0"
9674   [(set_attr "type" "dmpy_media")])
9675
9676 (define_expand "mmulhi_wl"
9677   [(match_operand:V2SI 0 "arith_reg_dest" "")
9678    (match_operand:V4HI 1 "arith_reg_operand" "")
9679    (match_operand:V4HI 2 "arith_reg_operand" "")]
9680   "TARGET_SHMEDIA"
9681   "
9682 {
9683   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
9684              (operands[0], operands[1], operands[2]));
9685   DONE;
9686 }")
9687
9688 (define_expand "mmullo_wl"
9689   [(match_operand:V2SI 0 "arith_reg_dest" "")
9690    (match_operand:V4HI 1 "arith_reg_operand" "")
9691    (match_operand:V4HI 2 "arith_reg_operand" "")]
9692   "TARGET_SHMEDIA"
9693   "
9694 {
9695   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
9696              (operands[0], operands[1], operands[2]));
9697   DONE;
9698 }")
9699
9700 (define_insn "mmul23_wl"
9701   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9702         (vec_select:V2SI
9703          (mult:V4SI
9704           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9705           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
9706          (parallel [(const_int 2) (const_int 3)])))]
9707   "TARGET_SHMEDIA"
9708   "* return (TARGET_LITTLE_ENDIAN
9709              ? \"mmulhi.wl      %1, %2, %0\"
9710              : \"mmullo.wl      %1, %2, %0\");"
9711   [(set_attr "type" "dmpy_media")])
9712
9713 (define_insn "mmul01_wl"
9714   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9715         (vec_select:V2SI
9716          (mult:V4SI
9717           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9718           (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
9719          (parallel [(const_int 0) (const_int 1)])))]
9720   "TARGET_SHMEDIA"
9721   "* return (TARGET_LITTLE_ENDIAN
9722              ? \"mmullo.wl      %1, %2, %0\"
9723              : \"mmulhi.wl      %1, %2, %0\");"
9724   [(set_attr "type" "dmpy_media")])
9725
9726 (define_expand "mmulsum_wq"
9727   [(match_operand:DI 0 "arith_reg_dest" "")
9728    (match_operand:V4HI 1 "arith_reg_operand" "")
9729    (match_operand:V4HI 2 "arith_reg_operand" "")
9730    (match_operand:DI 3 "arith_reg_operand" "")]
9731   "TARGET_SHMEDIA"
9732   "
9733 {
9734   emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
9735                                operands[1], operands[2]));
9736   DONE;
9737 }")
9738
9739 (define_insn "mmulsum_wq_i"
9740   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9741         (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
9742          (plus:DI
9743           (plus:DI
9744            (vec_select:DI
9745             (mult:V4DI
9746              (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
9747              (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
9748             (parallel [(const_int 0)]))
9749            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
9750                                      (sign_extend:V4DI (match_dup 3)))
9751                           (parallel [(const_int 1)])))
9752           (plus:DI
9753            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
9754                                      (sign_extend:V4DI (match_dup 3)))
9755                           (parallel [(const_int 2)]))
9756            (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
9757                                      (sign_extend:V4DI (match_dup 3)))
9758                           (parallel [(const_int 3)]))))))]
9759   "TARGET_SHMEDIA"
9760   "mmulsum.wq   %2, %3, %0"
9761   [(set_attr "type" "mac_media")])
9762
9763 (define_expand "mperm_w"
9764   [(match_operand:V4HI 0 "arith_reg_dest" "=r")
9765    (match_operand:V4HI 1 "arith_reg_operand" "r")
9766    (match_operand:QI 2 "extend_reg_or_0_operand" "rU")]
9767   "TARGET_SHMEDIA"
9768   "
9769 {
9770   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
9771              (operands[0], operands[1], operands[2]));
9772   DONE;
9773 }")
9774
9775 ; This use of vec_select isn't exactly correct according to rtl.texi
9776 ; (because not constant), but it seems a straightforward extension.
9777 (define_insn "mperm_w_little"
9778   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9779         (vec_select:V4HI
9780          (match_operand:V4HI 1 "arith_reg_operand" "r")
9781          (parallel
9782           [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rU")
9783                             (const_int 2) (const_int 0))
9784            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
9785            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
9786            (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
9787   "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
9788   "mperm.w      %1, %N2, %0"
9789   [(set_attr "type" "arith_media")])
9790
9791 (define_insn "mperm_w_big"
9792   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9793         (vec_select:V4HI
9794          (match_operand:V4HI 1 "arith_reg_operand" "r")
9795          (parallel
9796           [(zero_extract:QI (not:QI (match_operand:QI 2
9797                                      "extend_reg_or_0_operand" "rU"))
9798                             (const_int 2) (const_int 0))
9799            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
9800            (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
9801            (zero_extract:QI (not:QI (match_dup 2))
9802                             (const_int 2) (const_int 6))])))]
9803   "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
9804   "mperm.w      %1, %N2, %0"
9805   [(set_attr "type" "arith_media")])
9806
9807 (define_insn "mperm_w0"
9808   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9809         (vec_duplicate:V4HI (truncate:HI (match_operand 1
9810                                           "trunc_hi_operand" "r"))))]
9811   "TARGET_SHMEDIA"
9812   "mperm.w      %1, r63, %0"
9813   [(set_attr "type" "arith_media")])
9814
9815 (define_expand "msad_ubq"
9816   [(match_operand:DI 0 "arith_reg_dest" "")
9817    (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
9818    (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
9819    (match_operand:DI 3 "arith_reg_operand" "")]
9820   "TARGET_SHMEDIA"
9821   "
9822 {
9823   emit_insn (gen_msad_ubq_i (operands[0], operands[3],
9824                              operands[1], operands[2]));
9825   DONE;
9826 }")
9827
9828 (define_insn "msad_ubq_i"
9829   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
9830         (plus:DI
9831          (plus:DI
9832           (plus:DI
9833            (plus:DI
9834             (match_operand:DI 1 "arith_reg_operand" "0")
9835             (abs:DI (vec_select:DI
9836                      (minus:V8DI
9837                       (zero_extend:V8DI
9838                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "r"))
9839                       (zero_extend:V8DI
9840                        (match_operand:V8QI 3 "arith_reg_or_0_operand" "r")))
9841                      (parallel [(const_int 0)]))))
9842            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9843                                               (zero_extend:V8DI (match_dup 3)))
9844                                   (parallel [(const_int 1)]))))
9845           (plus:DI
9846            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9847                                               (zero_extend:V8DI (match_dup 3)))
9848                                   (parallel [(const_int 2)])))
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 3)])))))
9852          (plus:DI
9853           (plus:DI
9854            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9855                                               (zero_extend:V8DI (match_dup 3)))
9856                                   (parallel [(const_int 4)])))
9857            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9858                                               (zero_extend:V8DI (match_dup 3)))
9859                                   (parallel [(const_int 5)]))))
9860           (plus:DI
9861            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9862                                               (zero_extend:V8DI (match_dup 3)))
9863                                   (parallel [(const_int 6)])))
9864            (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
9865                                               (zero_extend:V8DI (match_dup 3)))
9866                                   (parallel [(const_int 7)])))))))]
9867   "TARGET_SHMEDIA"
9868   "msad.ubq     %N2, %N3, %0"
9869   [(set_attr "type" "mac_media")])
9870
9871 (define_insn "mshalds_l"
9872   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9873         (ss_truncate:V2SI
9874          (ashift:V2DI
9875           (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
9876           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
9877                   (const_int 31)))))]
9878   "TARGET_SHMEDIA"
9879   "mshalds.l    %1, %2, %0"
9880   [(set_attr "type" "mcmp_media")])
9881
9882 (define_insn "mshalds_w"
9883   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9884         (ss_truncate:V4HI
9885          (ashift:V4SI
9886           (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
9887           (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
9888                   (const_int 15)))))]
9889   "TARGET_SHMEDIA"
9890   "mshalds.w    %1, %2, %0"
9891   [(set_attr "type" "mcmp_media")])
9892
9893 (define_insn "ashrv2si3"
9894   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9895         (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
9896                        (match_operand:DI 2 "arith_reg_operand" "r")))]
9897   "TARGET_SHMEDIA"
9898   "mshard.l     %1, %2, %0"
9899   [(set_attr "type" "arith_media")])
9900
9901 (define_insn "ashrv4hi3"
9902   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
9903         (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
9904                        (match_operand:DI 2 "arith_reg_operand" "r")))]
9905   "TARGET_SHMEDIA"
9906   "mshard.w     %1, %2, %0"
9907   [(set_attr "type" "arith_media")])
9908
9909 (define_insn "mshards_q"
9910   [(set (match_operand:HI 0 "arith_reg_dest" "=r")
9911         (ss_truncate:HI
9912          (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
9913                       (match_operand:DI 2 "arith_reg_or_0_operand" "rU"))))]
9914   "TARGET_SHMEDIA"
9915   "mshards.q    %1, %N2, %0"
9916   [(set_attr "type" "mcmp_media")])
9917
9918 (define_expand "mshfhi_b"
9919   [(match_operand:V8QI 0 "arith_reg_dest" "")
9920    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
9921    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
9922   "TARGET_SHMEDIA"
9923   "
9924 {
9925   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
9926              (operands[0], operands[1], operands[2]));
9927   DONE;
9928 }")
9929
9930 (define_expand "mshflo_b"
9931   [(match_operand:V8QI 0 "arith_reg_dest" "")
9932    (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
9933    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
9934   "TARGET_SHMEDIA"
9935   "
9936 {
9937   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
9938              (operands[0], operands[1], operands[2]));
9939   DONE;
9940 }")
9941
9942 (define_insn "mshf4_b"
9943   [(set
9944     (match_operand:V8QI 0 "arith_reg_dest" "=r")
9945     (vec_select:V8QI
9946      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
9947                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))
9948      (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
9949                 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
9950   "TARGET_SHMEDIA"
9951   "* return (TARGET_LITTLE_ENDIAN
9952              ? \"mshfhi.b       %N1, %N2, %0\"
9953              : \"mshflo.b       %N1, %N2, %0\");"
9954   [(set_attr "type" "arith_media")])
9955
9956 (define_insn "mshf0_b"
9957   [(set
9958     (match_operand:V8QI 0 "arith_reg_dest" "=r")
9959     (vec_select:V8QI
9960      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
9961                        (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))
9962      (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
9963                 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
9964   "TARGET_SHMEDIA"
9965   "* return (TARGET_LITTLE_ENDIAN
9966              ? \"mshflo.b       %N1, %N2, %0\"
9967              : \"mshfhi.b       %N1, %N2, %0\");"
9968   [(set_attr "type" "arith_media")])
9969
9970 (define_expand "mshfhi_l"
9971   [(match_operand:V2SI 0 "arith_reg_dest" "")
9972    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
9973    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU")]
9974   "TARGET_SHMEDIA"
9975   "
9976 {
9977   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
9978              (operands[0], operands[1], operands[2]));
9979   DONE;
9980 }")
9981
9982 (define_expand "mshflo_l"
9983   [(match_operand:V2SI 0 "arith_reg_dest" "")
9984    (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
9985    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU")]
9986   "TARGET_SHMEDIA"
9987   "
9988 {
9989   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
9990              (operands[0], operands[1], operands[2]));
9991   DONE;
9992 }")
9993
9994 (define_insn "mshf4_l"
9995   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
9996         (vec_select:V2SI
9997          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
9998                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))
9999          (parallel [(const_int 1) (const_int 3)])))]
10000   "TARGET_SHMEDIA"
10001   "* return (TARGET_LITTLE_ENDIAN
10002              ? \"mshfhi.l       %N1, %N2, %0\"
10003              : \"mshflo.l       %N1, %N2, %0\");"
10004   [(set_attr "type" "arith_media")])
10005
10006 (define_insn "mshf0_l"
10007   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10008         (vec_select:V2SI
10009          (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
10010                           (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))
10011          (parallel [(const_int 0) (const_int 2)])))]
10012   "TARGET_SHMEDIA"
10013   "* return (TARGET_LITTLE_ENDIAN
10014              ? \"mshflo.l       %N1, %N2, %0\"
10015              : \"mshfhi.l       %N1, %N2, %0\");"
10016   [(set_attr "type" "arith_media")])
10017
10018 (define_expand "mshfhi_w"
10019   [(match_operand:V4HI 0 "arith_reg_dest" "")
10020    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10021    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU")]
10022   "TARGET_SHMEDIA"
10023   "
10024 {
10025   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
10026              (operands[0], operands[1], operands[2]));
10027   DONE;
10028 }")
10029
10030 (define_expand "mshflo_w"
10031   [(match_operand:V4HI 0 "arith_reg_dest" "")
10032    (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10033    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU")]
10034   "TARGET_SHMEDIA"
10035   "
10036 {
10037   emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
10038              (operands[0], operands[1], operands[2]));
10039   DONE;
10040 }")
10041
10042 (define_insn "mshf4_w"
10043   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10044         (vec_select:V4HI
10045          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10046                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))
10047          (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
10048   "TARGET_SHMEDIA"
10049   "* return (TARGET_LITTLE_ENDIAN
10050              ? \"mshfhi.w       %N1, %N2, %0\"
10051              : \"mshflo.w       %N1, %N2, %0\");"
10052   [(set_attr "type" "arith_media")])
10053
10054 (define_insn "mshf0_w"
10055   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10056         (vec_select:V4HI
10057          (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10058                           (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))
10059          (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
10060   "TARGET_SHMEDIA"
10061   "* return (TARGET_LITTLE_ENDIAN
10062              ? \"mshflo.w       %N1, %N2, %0\"
10063              : \"mshfhi.w       %N1, %N2, %0\");"
10064   [(set_attr "type" "arith_media")])
10065
10066 (define_insn "mshflo_w_x"
10067   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10068         (vec_select:V4HI
10069          (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rU")
10070                           (match_operand:V2HI 2 "extend_reg_or_0_operand" "rU"))
10071          (parallel [(const_int 0) (const_int 2) (const_int 1) (const_int 3)])))]
10072   "TARGET_SHMEDIA"
10073   "mshflo.w     %N1, %N2, %0"
10074   [(set_attr "type" "arith_media")])
10075
10076 /* These are useful to expand ANDs and as combiner patterns.  */
10077 (define_insn_and_split "mshfhi_l_di"
10078   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
10079         (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU,f")
10080                              (const_int 32))
10081                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU,?f")
10082                         (const_int -4294967296))))]
10083   "TARGET_SHMEDIA"
10084   "@
10085         mshfhi.l        %N1, %N2, %0
10086         #"
10087   "TARGET_SHMEDIA && reload_completed
10088    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
10089   [(set (match_dup 3) (match_dup 4))
10090    (set (match_dup 5) (match_dup 6))]
10091   "
10092 {
10093   operands[3] = gen_lowpart (SImode, operands[0]);
10094   operands[4] = gen_highpart (SImode, operands[1]);
10095   operands[5] = gen_highpart (SImode, operands[0]);
10096   operands[6] = gen_highpart (SImode, operands[2]);
10097 }"
10098   [(set_attr "type" "arith_media")])
10099
10100 (define_insn "*mshfhi_l_di_rev"
10101   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10102         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
10103                         (const_int -4294967296))
10104                 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
10105                              (const_int 32))))]
10106   "TARGET_SHMEDIA"
10107   "mshfhi.l     %N2, %N1, %0"
10108   [(set_attr "type" "arith_media")])
10109
10110 (define_split
10111   [(set (match_operand:DI 0 "arith_reg_dest" "")
10112         (ior:DI (zero_extend:DI (match_operand:SI 1
10113                                               "extend_reg_or_0_operand" ""))
10114                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
10115                         (const_int -4294967296))))
10116    (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
10117   "TARGET_SHMEDIA"
10118   [(const_int 0)]
10119   "
10120 {
10121   emit_insn (gen_ashldi3_media (operands[3],
10122                                 simplify_gen_subreg (DImode, operands[1],
10123                                                      SImode, 0),
10124                                 GEN_INT (32)));
10125   emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
10126   DONE;
10127 }")
10128
10129 (define_insn "mshflo_l_di"
10130   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10131         (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
10132                         (const_int 4294967295))
10133                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
10134                            (const_int 32))))]
10135                                 
10136   "TARGET_SHMEDIA"
10137   "mshflo.l     %N1, %N2, %0"
10138   [(set_attr "type" "arith_media")])
10139
10140 (define_insn "*mshflo_l_di_rev"
10141   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10142         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
10143                            (const_int 32))
10144                 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
10145                         (const_int 4294967295))))]
10146                                 
10147   "TARGET_SHMEDIA"
10148   "mshflo.l     %N2, %N1, %0"
10149   [(set_attr "type" "arith_media")])
10150
10151 ;; Combiner pattern for trampoline initialization.
10152 (define_insn_and_split "*double_shori"
10153   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10154         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
10155                            (const_int 32))
10156                 (match_operand:DI 2 "const_int_operand" "n")))]
10157   "TARGET_SHMEDIA
10158    && INTVAL (operands[2]) == trunc_int_for_mode (INTVAL (operands[2]), SImode)"
10159   "#"
10160   "rtx_equal_p (operands[0], operands[1])"
10161   [(const_int 0)]
10162   "
10163 {
10164   HOST_WIDE_INT v = INTVAL (operands[2]);
10165
10166   emit_insn (gen_shori_media (operands[0], operands[0],
10167              gen_int_mode (INTVAL (operands[2]) >> 16, HImode)));
10168   emit_insn (gen_shori_media (operands[0], operands[0],
10169                               gen_int_mode (v, HImode)));
10170   DONE;
10171 }")
10172
10173
10174 (define_insn "*mshflo_l_di_x"
10175   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10176         (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
10177                                  "rU"))
10178                 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
10179                            (const_int 32))))]
10180                                 
10181   "TARGET_SHMEDIA"
10182   "mshflo.l     %N1, %N2, %0"
10183   [(set_attr "type" "arith_media")])
10184
10185 (define_insn_and_split "concat_v2sf"
10186   [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
10187 ;;      (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rU,0,f")
10188         (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rU,f,f")
10189                          (match_operand:SF 2 "register_operand" "rU,f,f")))]
10190                                 
10191   "TARGET_SHMEDIA"
10192   "@
10193         mshflo.l        %N1, %N2, %0
10194         #
10195         #"
10196   "TARGET_SHMEDIA && reload_completed
10197    && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
10198   [(set (match_dup 3) (match_dup 1))
10199    (set (match_dup 4) (match_dup 2))]
10200   "
10201 {
10202   operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
10203   operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
10204 }"
10205   [(set_attr "type" "arith_media")])
10206
10207 (define_insn "*mshflo_l_di_x_rev"
10208   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10209         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
10210                            (const_int 32))
10211                 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rU"))))]
10212                                 
10213   "TARGET_SHMEDIA"
10214   "mshflo.l     %N2, %N1, %0"
10215   [(set_attr "type" "arith_media")])
10216
10217 (define_insn "ashlv2si3"
10218   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10219         (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10220                      (match_operand:DI 2 "arith_reg_operand" "r")))]
10221   "TARGET_SHMEDIA"
10222   "mshlld.l     %1, %2, %0"
10223   [(set_attr "type" "arith_media")])
10224
10225 (define_insn "ashlv4hi3"
10226   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10227         (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10228                      (match_operand:DI 2 "arith_reg_operand" "r")))]
10229   "TARGET_SHMEDIA"
10230   "mshlld.w     %1, %2, %0"
10231   [(set_attr "type" "arith_media")])
10232
10233 (define_insn "lshrv2si3"
10234   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10235         (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
10236                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10237   "TARGET_SHMEDIA"
10238   "mshlrd.l     %1, %2, %0"
10239   [(set_attr "type" "arith_media")])
10240
10241 (define_insn "lshrv4hi3"
10242   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10243         (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
10244                        (match_operand:DI 2 "arith_reg_operand" "r")))]
10245   "TARGET_SHMEDIA"
10246   "mshlrd.w     %1, %2, %0"
10247   [(set_attr "type" "arith_media")])
10248
10249 (define_insn "subv2si3"
10250   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10251         (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
10252                     (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10253   "TARGET_SHMEDIA"
10254   "msub.l       %N1, %2, %0"
10255   [(set_attr "type" "arith_media")])
10256
10257 (define_insn "subv4hi3"
10258   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10259         (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10260                     (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10261   "TARGET_SHMEDIA"
10262   "msub.w       %N1, %2, %0"
10263   [(set_attr "type" "arith_media")])
10264
10265 (define_insn "sssubv2si3"
10266   [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
10267         (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
10268                        (match_operand:V2SI 2 "arith_reg_operand" "r")))]
10269   "TARGET_SHMEDIA"
10270   "msubs.l      %N1, %2, %0"
10271   [(set_attr "type" "mcmp_media")])
10272
10273 (define_insn "ussubv8qi3"
10274   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
10275         (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
10276                        (match_operand:V8QI 2 "arith_reg_operand" "r")))]
10277   "TARGET_SHMEDIA"
10278   "msubs.ub     %1, %2, %0"
10279   [(set_attr "type" "mcmp_media")])
10280
10281 (define_insn "sssubv4hi3"
10282   [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
10283         (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
10284                        (match_operand:V4HI 2 "arith_reg_operand" "r")))]
10285   "TARGET_SHMEDIA"
10286   "msubs.w      %N1, %2, %0"
10287   [(set_attr "type" "mcmp_media")])
10288
10289 ;; Floating Point Intrinsics
10290
10291 (define_insn "fcosa_s"
10292   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10293         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
10294                    UNSPEC_FCOSA))]
10295   "TARGET_SHMEDIA"
10296   "fcosa.s      %1, %0"
10297   [(set_attr "type" "atrans_media")])
10298
10299 (define_insn "fsina_s"
10300   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10301         (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
10302                    UNSPEC_FSINA))]
10303   "TARGET_SHMEDIA"
10304   "fsina.s      %1, %0"
10305   [(set_attr "type" "atrans_media")])
10306
10307 (define_insn "fipr"
10308   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10309         (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
10310                                                     "fp_arith_reg_operand" "f")
10311                                                    (match_operand:V4SF 2
10312                                                     "fp_arith_reg_operand" "f"))
10313                                          (parallel [(const_int 0)]))
10314                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10315                                          (parallel [(const_int 1)])))
10316                  (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10317                                          (parallel [(const_int 2)]))
10318                           (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
10319                                          (parallel [(const_int 3)])))))]
10320   "TARGET_SHMEDIA"
10321   "fipr %1, %2, %0"
10322   [(set_attr "type" "fparith_media")])
10323
10324 (define_insn "fsrra_s"
10325   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10326         (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
10327                    UNSPEC_FSRRA))]
10328   "TARGET_SHMEDIA"
10329   "fsrra.s      %1, %0"
10330   [(set_attr "type" "atrans_media")])
10331
10332 (define_insn "ftrv"
10333   [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
10334         (plus:V4SF
10335          (plus:V4SF
10336           (mult:V4SF
10337            (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
10338                             (parallel [(const_int 0) (const_int 5)
10339                                        (const_int 10) (const_int 15)]))
10340            (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
10341           (mult:V4SF
10342            (vec_select:V4SF (match_dup 1)
10343                             (parallel [(const_int 4) (const_int 9)
10344                                        (const_int 14) (const_int 3)]))
10345            (vec_select:V4SF (match_dup 2)
10346                             (parallel [(const_int 1) (const_int 2)
10347                                       (const_int 3) (const_int 0)]))))
10348          (plus:V4SF
10349           (mult:V4SF
10350            (vec_select:V4SF (match_dup 1)
10351                             (parallel [(const_int 8) (const_int 13)
10352                                        (const_int 2) (const_int 7)]))
10353            (vec_select:V4SF (match_dup 2)
10354                             (parallel [(const_int 2) (const_int 3)
10355                                        (const_int 0) (const_int 1)])))
10356           (mult:V4SF
10357            (vec_select:V4SF (match_dup 1)
10358                             (parallel [(const_int 12) (const_int 1)
10359                                        (const_int 6) (const_int 11)]))
10360            (vec_select:V4SF (match_dup 2)
10361                             (parallel [(const_int 3) (const_int 0)
10362                                        (const_int 1) (const_int 2)]))))))]
10363   "TARGET_SHMEDIA"
10364   "ftrv %1, %2, %0"
10365   [(set_attr "type" "fparith_media")])
10366
10367 (define_insn "nsb"
10368   [(set (match_operand:QI 0 "arith_reg_dest" "=r")
10369         (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10370                    UNSPEC_NSB))]
10371   "TARGET_SHMEDIA"
10372   "nsb  %1, %0"
10373   [(set_attr "type" "arith_media")])
10374
10375 (define_insn "nsbsi"
10376   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
10377         (zero_extend:SI
10378          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10379                     UNSPEC_NSB)))]
10380   "TARGET_SHMEDIA"
10381   "nsb  %1, %0"
10382   [(set_attr "type" "arith_media")])
10383
10384 (define_insn "nsbdi"
10385   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10386         (zero_extend:DI
10387          (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
10388                     UNSPEC_NSB)))]
10389   "TARGET_SHMEDIA"
10390   "nsb  %1, %0"
10391   [(set_attr "type" "arith_media")])
10392
10393 (define_expand "ffsdi2"
10394   [(set (match_operand:DI 0 "arith_reg_dest" "")
10395         (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
10396   "TARGET_SHMEDIA"
10397   "
10398 {
10399   rtx scratch = gen_reg_rtx (DImode);
10400   rtx last;
10401
10402   emit_insn (gen_adddi3 (scratch, operands[1], GEN_INT (-1)));
10403   emit_insn (gen_xordi3 (scratch, operands[1], scratch));
10404   emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
10405   emit_insn (gen_nsbdi (scratch, scratch));
10406   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
10407   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
10408   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
10409   REG_NOTES (last)
10410     = gen_rtx_EXPR_LIST (REG_EQUAL,
10411                          gen_rtx_FFS (DImode, operands[0]), REG_NOTES (last));
10412   DONE;
10413 }")
10414
10415 (define_expand "ffssi2"
10416   [(set (match_operand:SI 0 "arith_reg_dest" "")
10417         (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
10418   "TARGET_SHMEDIA"
10419   "
10420 {
10421   rtx scratch = gen_reg_rtx (SImode);
10422   rtx discratch = gen_reg_rtx (DImode);
10423   rtx last;
10424
10425   emit_insn (gen_adddi3 (discratch,
10426                          simplify_gen_subreg (DImode, operands[1], SImode, 0),
10427                          GEN_INT (-1)));
10428   emit_insn (gen_andcdi3 (discratch,
10429                           simplify_gen_subreg (DImode, operands[1], SImode, 0),
10430                           discratch));
10431   emit_insn (gen_nsbsi (scratch, discratch));
10432   last = emit_insn (gen_subsi3 (operands[0],
10433                                 force_reg (SImode, GEN_INT (63)), scratch));
10434   REG_NOTES (last)
10435     = gen_rtx_EXPR_LIST (REG_EQUAL,
10436                          gen_rtx_FFS (SImode, operands[0]), REG_NOTES (last));
10437   DONE;
10438 }")
10439
10440 (define_insn "byterev"
10441   [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
10442         (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
10443                          (parallel [(const_int 7) (const_int 6) (const_int 5)
10444                                     (const_int 4) (const_int 3) (const_int 2)
10445                                     (const_int 1) (const_int 0)])))]
10446   "TARGET_SHMEDIA"
10447   "byterev      %1, %0"
10448   [(set_attr "type" "arith_media")])
10449
10450 ;; The following description  models the
10451 ;; SH4 pipeline using the DFA based scheduler. 
10452 ;; The DFA based description is better way to model 
10453 ;; a superscalar pipeline as compared to function unit
10454 ;; reservation model.   
10455 ;; 1. The function unit based model is oriented to describe at most one 
10456 ;;    unit reservation by each insn. It is difficult to model unit reservations in multiple 
10457 ;;    pipeline units by same insn. This can be done using DFA based description.
10458 ;; 2. The execution performance of DFA based scheduler does not depend on processor complexity.
10459 ;; 3. Writing all unit reservations for an instruction class is more natural description 
10460 ;;    of the pipeline and makes interface of the hazard recognizer simpler than the 
10461 ;;    old function unit based model.
10462 ;; 4. The DFA model is richer and is a part of greater overall framework of RCSP.
10463
10464
10465 ;; Two automata are defined to reduce number of states
10466 ;; which a single large automaton will have.(Factoring)
10467
10468 (define_automaton "inst_pipeline,fpu_pipe")
10469
10470 ;; This unit is basically the decode unit of the processor.
10471 ;; Since SH4 is a dual issue machine,it is as if there are two 
10472 ;; units so that any insn can be processed by either one
10473 ;; of the decoding unit.
10474
10475 (define_cpu_unit "pipe_01,pipe_02" "inst_pipeline")
10476
10477
10478 ;; The fixed point arithmetic calculator(?? EX Unit).
10479
10480 (define_cpu_unit  "int" "inst_pipeline")
10481
10482 ;; f1_1 and f1_2 are floating point units.Actually there is
10483 ;; a f1 unit which can overlap with other f1 unit but
10484 ;; not another F1 unit.It is as though there were two
10485 ;; f1 units.
10486
10487 (define_cpu_unit "f1_1,f1_2" "fpu_pipe")
10488
10489 ;; The floating point units (except FS - F2 always precedes it.)
10490
10491 (define_cpu_unit "F0,F1,F2,F3" "fpu_pipe")
10492
10493 ;; This is basically the MA unit of SH4
10494 ;; used in LOAD/STORE pipeline.
10495
10496 (define_cpu_unit "memory" "inst_pipeline")
10497
10498 ;; However, there are LS group insns that don't use it, even ones that
10499 ;; complete in 0 cycles.  So we use an extra unit for the issue of LS insns.
10500 (define_cpu_unit "load_store" "inst_pipeline")
10501
10502 ;; The address calculator used for branch instructions.
10503 ;; This will be reserved after "issue" of branch instructions
10504 ;; and this is to make sure that no two branch instructions 
10505 ;; can be issued in parallel. 
10506
10507 (define_cpu_unit "pcr_addrcalc" "inst_pipeline")
10508
10509 ;; ----------------------------------------------------
10510 ;; This reservation is to simplify the dual issue description.
10511
10512 (define_reservation  "issue"  "pipe_01|pipe_02")
10513
10514 ;; This is to express the locking of D stage.
10515 ;; Note that the issue of a CO group insn also effectively locks the D stage.
10516
10517 (define_reservation  "d_lock" "pipe_01+pipe_02")
10518
10519 ;; Every FE instruction but fipr / ftrv starts with issue and this.
10520 (define_reservation "F01" "F0+F1")
10521
10522 ;; This is to simplify description where F1,F2,FS
10523 ;; are used simultaneously.
10524
10525 (define_reservation "fpu" "F1+F2")
10526
10527 ;; This is to highlight the fact that f1 
10528 ;; cannot overlap with F1.
10529
10530 (exclusion_set  "f1_1,f1_2" "F1")
10531
10532 (define_insn_reservation "nil" 0 (eq_attr "type" "nil") "nothing")
10533
10534 ;; Although reg moves have a latency of zero 
10535 ;; we need to highlight that they use D stage
10536 ;; for one cycle.
10537
10538 ;; Group:       MT
10539
10540 (define_insn_reservation "reg_mov" 0
10541   (and (eq_attr "pipe_model" "sh4")
10542        (eq_attr "type" "move"))
10543   "issue")
10544
10545 ;; Group:       LS
10546
10547 (define_insn_reservation "freg_mov" 0
10548   (and (eq_attr "pipe_model" "sh4")
10549        (eq_attr "type" "fmove"))
10550   "issue+load_store")
10551
10552 ;; We don't model all pipeline stages; we model the issue ('D') stage
10553 ;; inasmuch as we allow only two instructions to issue simultanously,
10554 ;; and CO instructions prevent any simultanous issue of another instruction.
10555 ;; (This uses pipe_01 and pipe_02).
10556 ;; Double issue of EX insns is prevented by using the int unit in the EX stage.
10557 ;; Double issue of EX / BR insns is prevented by using the int unit /
10558 ;; pcr_addrcalc unit in the EX stage.
10559 ;; Double issue of BR / LS instructions is prevented by using the
10560 ;; pcr_addrcalc / load_store unit in the issue cycle.
10561 ;; Double issue of FE instructions is prevented by using F0 in the first
10562 ;; pipeline stage after the first D stage.
10563 ;; There is no need to describe the [ES]X / [MN]A / S stages after a D stage
10564 ;; (except in the cases outlined above), nor to describe the FS stage after
10565 ;; the F2 stage.
10566
10567 ;; Other MT  group intructions(1 step operations)
10568 ;; Group:       MT
10569 ;; Latency:     1
10570 ;; Issue Rate:  1
10571
10572 (define_insn_reservation "mt" 1
10573   (and (eq_attr "pipe_model" "sh4")
10574        (eq_attr "type" "mt_group"))
10575   "issue")
10576
10577 ;; Fixed Point Arithmetic Instructions(1 step operations)
10578 ;; Group:       EX
10579 ;; Latency:     1
10580 ;; Issue Rate:  1
10581
10582 (define_insn_reservation "sh4_simple_arith" 1 
10583   (and (eq_attr "pipe_model" "sh4")
10584        (eq_attr "insn_class" "ex_group"))
10585   "issue,int")
10586
10587 ;; Load and store instructions have no alignment peculiarities for the SH4,
10588 ;; but they use the load-store unit, which they share with the fmove type
10589 ;; insns (fldi[01]; fmov frn,frm; flds; fsts; fabs; fneg) .
10590 ;; Loads have a latency of two.
10591 ;; However, call insns can only paired with a preceding insn, and have
10592 ;; a delay slot, so that we want two more insns to be scheduled between the
10593 ;; load of the function address and the call.  This is equivalent to a
10594 ;; latency of three.
10595 ;; ADJUST_COST can only properly handle reductions of the cost, so we
10596 ;; use a latency of three here, which gets multiplied by 10 to yield 30.
10597 ;; We only do this for SImode loads of general registers, to make the work
10598 ;; for ADJUST_COST easier.
10599
10600 ;; Load Store instructions. (MOV.[BWL]@(d,GBR)
10601 ;; Group:       LS
10602 ;; Latency:     2
10603 ;; Issue Rate:  1
10604
10605 (define_insn_reservation "sh4_load" 2
10606   (and (eq_attr "pipe_model" "sh4")
10607        (eq_attr "type" "load,pcload"))
10608   "issue+load_store,nothing,memory")
10609
10610 ;; calls / sfuncs need an extra instruction for their delay slot.
10611 ;; Moreover, estimating the latency for SImode loads as 3 will also allow
10612 ;; adjust_cost to meaningfully bump it back up to 3 if they load the shift
10613 ;; count of a dynamic shift.
10614 (define_insn_reservation "sh4_load_si" 3
10615   (and (eq_attr "pipe_model" "sh4")
10616        (eq_attr "type" "load_si,pcload_si"))
10617   "issue+load_store,nothing,memory")
10618
10619 ;; (define_bypass 2 "sh4_load_si" "!sh4_call")
10620
10621 ;; The load latency is upped to three higher if the dependent insn does
10622 ;; double precision computation.  We want the 'default' latency to reflect
10623 ;; that increased latency because otherwise the insn priorities won't
10624 ;; allow proper scheduling.
10625 (define_insn_reservation "sh4_fload" 3
10626   (and (eq_attr "pipe_model" "sh4")
10627        (eq_attr "type" "fload,pcfload"))
10628   "issue+load_store,nothing,memory")
10629
10630 ;; (define_bypass 2 "sh4_fload" "!")
10631
10632 (define_insn_reservation "sh4_store" 1
10633   (and (eq_attr "pipe_model" "sh4")
10634        (eq_attr "type" "store"))
10635   "issue+load_store,nothing,memory")
10636
10637 ;; Load Store instructions.
10638 ;; Group:       LS
10639 ;; Latency:     1
10640 ;; Issue Rate:  1
10641
10642 (define_insn_reservation "sh4_gp_fpul" 1
10643   (and (eq_attr "pipe_model" "sh4")
10644        (eq_attr "type" "gp_fpul"))
10645   "issue+load_store")
10646
10647 ;; Load Store instructions.
10648 ;; Group:       LS
10649 ;; Latency:     3
10650 ;; Issue Rate:  1
10651
10652 (define_insn_reservation "sh4_fpul_gp" 3
10653   (and (eq_attr "pipe_model" "sh4")
10654        (eq_attr "type" "fpul_gp"))
10655   "issue+load_store")
10656
10657 ;; Branch (BF,BF/S,BT,BT/S,BRA)
10658 ;; Group:       BR
10659 ;; Latency when taken:  2 (or 1)
10660 ;; Issue Rate:  1
10661 ;; The latency is 1 when displacement is 0.
10662 ;; We can't really do much with the latency, even if we could express it,
10663 ;; but the pairing restrictions are useful to take into account.
10664 ;; ??? If the branch is likely, we might want to fill the delay slot;
10665 ;; if the branch is likely, but not very likely, should we pretend to use
10666 ;; a resource that CO instructions use, to get a pairable delay slot insn?
10667
10668 (define_insn_reservation "sh4_branch"  1
10669   (and (eq_attr "pipe_model" "sh4")
10670        (eq_attr "type" "cbranch,jump"))
10671   "issue+pcr_addrcalc")
10672
10673 ;; Branch Far (JMP,RTS,BRAF)
10674 ;; Group:       CO
10675 ;; Latency:     3
10676 ;; Issue Rate:  2
10677 ;; ??? Scheduling happens before branch shortening, and hence jmp and braf
10678 ;; can't be distinguished from bra for the "jump" pattern.
10679
10680 (define_insn_reservation "sh4_return" 3
10681   (and (eq_attr "pipe_model" "sh4")
10682        (eq_attr "type" "return,jump_ind"))
10683          "d_lock*2")
10684
10685 ;; RTE
10686 ;; Group:       CO
10687 ;; Latency:     5
10688 ;; Issue Rate:  5
10689 ;; this instruction can be executed in any of the pipelines 
10690 ;; and blocks the pipeline for next 4 stages.
10691
10692 (define_insn_reservation "sh4_return_from_exp" 5
10693   (and (eq_attr "pipe_model" "sh4")
10694        (eq_attr "type" "rte"))
10695   "d_lock*5")
10696
10697 ;; OCBP, OCBWB
10698 ;; Group:       CO
10699 ;; Latency:     1-5
10700 ;; Issue Rate:  1
10701
10702 ;; cwb is used for the sequence ocbwb @%0; extu.w %0,%2; or %1,%2; mov.l %0,@%2
10703 ;; ocbwb on its own would be "d_lock,nothing,memory*5"
10704 (define_insn_reservation "ocbwb"  6
10705   (and (eq_attr "pipe_model" "sh4")
10706        (eq_attr "type" "cwb"))
10707   "d_lock*2,(d_lock+memory)*3,issue+load_store+memory,memory*2")
10708                 
10709 ;; LDS to PR,JSR
10710 ;; Group:       CO
10711 ;; Latency:     3
10712 ;; Issue Rate:  2
10713 ;; The SX stage is blocked for last 2 cycles.
10714 ;; OTOH, the only time that has an effect for insns generated by the compiler
10715 ;; is when lds to PR is followed by sts from PR - and that is highly unlikely -
10716 ;; or when we are doing a function call - and we don't do inter-function
10717 ;; scheduling.  For the function call case, it's really best that we end with
10718 ;; something that models an rts.
10719
10720 (define_insn_reservation "sh4_lds_to_pr" 3 
10721   (and (eq_attr "pipe_model" "sh4")
10722        (eq_attr "type" "prset") )
10723   "d_lock*2")
10724
10725 ;; calls introduce a longisch delay that is likely to flush the pipelines
10726 ;; of the caller's instructions.  Ordinary functions tend to end with a
10727 ;; load to restore a register (in the delay slot of rts), while sfuncs
10728 ;; tend to end with an EX or MT insn.  But that is not actually relevant,
10729 ;; since there are no instructions that contend for memory access early.
10730 ;; We could, of course, provide exact scheduling information for specific
10731 ;; sfuncs, if that should prove useful.
10732
10733 (define_insn_reservation "sh4_call" 16 
10734   (and (eq_attr "pipe_model" "sh4")
10735        (eq_attr "type" "call,sfunc"))
10736   "d_lock*16")
10737
10738 ;; LDS.L to PR 
10739 ;; Group:       CO
10740 ;; Latency:     3
10741 ;; Issue Rate:  2
10742 ;; The SX unit is blocked for last 2 cycles.
10743  
10744 (define_insn_reservation "ldsmem_to_pr"  3
10745   (and (eq_attr "pipe_model" "sh4")
10746        (eq_attr "type" "pload"))
10747   "d_lock*2")
10748
10749 ;; STS from PR
10750 ;; Group:       CO
10751 ;; Latency:     2
10752 ;; Issue Rate:  2
10753 ;; The SX unit in second and third cycles.
10754
10755 (define_insn_reservation "sts_from_pr" 2
10756   (and (eq_attr "pipe_model" "sh4")
10757        (eq_attr "type" "prget"))
10758   "d_lock*2")
10759
10760 ;; STS.L from PR
10761 ;; Group:       CO
10762 ;; Latency:     2
10763 ;; Issue Rate:  2
10764
10765 (define_insn_reservation "sh4_prstore_mem" 2 
10766   (and (eq_attr "pipe_model" "sh4")
10767        (eq_attr "type" "pstore"))
10768   "d_lock*2,nothing,memory")
10769
10770 ;; LDS to FPSCR
10771 ;; Group:       CO
10772 ;; Latency:     4
10773 ;; Issue Rate:  1
10774 ;; F1 is blocked for last three cycles. 
10775
10776 (define_insn_reservation "fpscr_load" 4
10777   (and (eq_attr "pipe_model" "sh4")
10778        (eq_attr "type" "gp_fpscr"))
10779   "d_lock,nothing,F1*3")
10780
10781 ;; LDS.L to FPSCR
10782 ;; Group:       CO
10783 ;; Latency:     1 / 4
10784 ;; Latency to update Rn is 1 and latency to update FPSCR is 4
10785 ;; Issue Rate:  1
10786 ;; F1 is blocked for last three cycles.
10787
10788 (define_insn_reservation "fpscr_load_mem" 4
10789   (and (eq_attr "pipe_model" "sh4")
10790        (eq_attr "type"  "mem_fpscr"))
10791   "d_lock,nothing,(F1+memory),F1*2")
10792
10793 \f
10794 ;; Fixed point multiplication (DMULS.L DMULU.L MUL.L MULS.W,MULU.W)
10795 ;; Group:       CO
10796 ;; Latency:     4 / 4
10797 ;; Issue Rate:  1
10798
10799 (define_insn_reservation "multi" 4
10800   (and (eq_attr "pipe_model" "sh4")
10801        (eq_attr "type" "smpy,dmpy"))
10802   "d_lock,(d_lock+f1_1),(f1_1|f1_2)*3,F2")
10803
10804 ;; Fixed STS from MACL / MACH
10805 ;; Group:       CO
10806 ;; Latency:     3
10807 ;; Issue Rate:  1
10808
10809 (define_insn_reservation "sh4_mac_gp" 3
10810   (and (eq_attr "pipe_model" "sh4")
10811        (eq_attr "type" "mac_gp"))
10812   "d_lock")
10813
10814
10815 ;; Single precision floating point computation FCMP/EQ,
10816 ;; FCMP/GT, FADD, FLOAT, FMAC, FMUL, FSUB, FTRC, FRVHG, FSCHG
10817 ;; Group:       FE
10818 ;; Latency:     3/4
10819 ;; Issue Rate:  1
10820
10821 (define_insn_reservation "fp_arith"  3
10822   (and (eq_attr "pipe_model" "sh4")
10823        (eq_attr "type" "fp"))
10824   "issue,F01,F2")
10825
10826 (define_insn_reservation "fp_arith_ftrc"  3
10827   (and (eq_attr "pipe_model" "sh4")
10828        (eq_attr "type" "ftrc_s"))
10829   "issue,F01,F2")
10830
10831 (define_bypass 1 "fp_arith_ftrc" "sh4_fpul_gp")
10832
10833 ;; Single Precision FDIV/SQRT
10834 ;; Group:       FE
10835 ;; Latency:     12/13 (FDIV); 11/12 (FSQRT)
10836 ;; Issue Rate:  1
10837 ;; We describe fdiv here; fsqrt is actually one cycle faster.
10838
10839 (define_insn_reservation "fp_div" 12
10840   (and (eq_attr "pipe_model" "sh4")
10841        (eq_attr "type" "fdiv"))
10842   "issue,F01+F3,F2+F3,F3*7,F1+F3,F2")
10843
10844 ;; Double Precision floating point computation
10845 ;; (FCNVDS, FCNVSD, FLOAT, FTRC)
10846 ;; Group:       FE
10847 ;; Latency:     (3,4)/5
10848 ;; Issue Rate:  1
10849
10850 (define_insn_reservation "dp_float" 4
10851   (and (eq_attr "pipe_model" "sh4")
10852        (eq_attr "type" "dfp_conv"))
10853   "issue,F01,F1+F2,F2")
10854
10855 ;; Double-precision floating-point (FADD,FMUL,FSUB) 
10856 ;; Group:       FE
10857 ;; Latency:     (7,8)/9
10858 ;; Issue Rate:  1
10859
10860 (define_insn_reservation "fp_double_arith" 8
10861   (and (eq_attr "pipe_model" "sh4")
10862        (eq_attr "type" "dfp_arith"))
10863   "issue,F01,F1+F2,fpu*4,F2")
10864
10865 ;; Double-precision FCMP (FCMP/EQ,FCMP/GT) 
10866 ;; Group:       CO
10867 ;; Latency:     3/5
10868 ;; Issue Rate:  2
10869
10870 (define_insn_reservation "fp_double_cmp" 3 
10871   (and (eq_attr "pipe_model" "sh4")
10872        (eq_attr "type" "dfp_cmp"))
10873   "d_lock,(d_lock+F01),F1+F2,F2")
10874
10875 ;; Double precision FDIV/SQRT
10876 ;; Group:       FE
10877 ;; Latency:     (24,25)/26
10878 ;; Issue Rate:  1
10879
10880 (define_insn_reservation "dp_div" 25
10881   (and (eq_attr "pipe_model" "sh4")
10882        (eq_attr "type" "dfdiv"))
10883   "issue,F01+F3,F1+F2+F3,F2+F3,F3*16,F1+F3,(fpu+F3)*2,F2")
10884
10885
10886 ;; Use the branch-not-taken case to model arith3 insns.  For the branch taken
10887 ;; case, we'd get a d_lock instead of issue at the end.
10888 (define_insn_reservation "arith3" 3
10889   (and (eq_attr "pipe_model" "sh4")
10890        (eq_attr "type" "arith3"))
10891   "issue,d_lock+pcr_addrcalc,issue")
10892
10893 ;; arith3b insns schedule the same no matter if the branch is taken or not.
10894 (define_insn_reservation "arith3b" 2
10895   (and (eq_attr "pipe_model" "sh4")
10896        (eq_attr "type" "arith3"))
10897   "issue,d_lock+pcr_addrcalc")