OSDN Git Service

* c4x.c (c4x_fp_reglist): Const-ify.
[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
103   (DR0_REG      64)
104   (DR2_REG      66)
105   (DR4_REG      68)
106
107   (TR0_REG      128)
108   (TR1_REG      129)
109   (TR2_REG      130)
110
111   (XD0_REG      136)
112
113   ;; These are used with unspec.
114   (UNSPEC_COMPACT_ARGS  0)
115   (UNSPEC_MOVA          1)
116   (UNSPEC_CASESI        2)
117   (UNSPEC_DATALABEL     3)
118   (UNSPEC_BBR           4)
119   (UNSPEC_SFUNC         5)
120   (UNSPEC_PIC           6)
121   (UNSPEC_GOT           7)
122   (UNSPEC_GOTOFF        8)
123   (UNSPEC_PLT           9)
124   (UNSPEC_CALLER        10)
125   (UNSPEC_GOTPLT        11)
126   (UNSPEC_ICACHE        12)
127
128   ;; These are used with unspec_volatile.
129   (UNSPECV_BLOCKAGE     0)
130   (UNSPECV_ALIGN        1)
131   (UNSPECV_CONST2       2)
132   (UNSPECV_CONST4       4)
133   (UNSPECV_CONST8       6)
134   (UNSPECV_WINDOW_END   10)
135   (UNSPECV_CONST_END    11)
136 ])  
137
138 ;; -------------------------------------------------------------------------
139 ;; Attributes
140 ;; -------------------------------------------------------------------------
141
142 ;; Target CPU.
143
144 (define_attr "cpu"
145  "sh1,sh2,sh3,sh3e,sh4,sh5"
146   (const (symbol_ref "sh_cpu_attr")))
147
148 (define_attr "endian" "big,little"
149  (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
150                       (const_string "little") (const_string "big"))))
151
152 ;; Indicate if the default fpu mode is single precision.
153 (define_attr "fpu_single" "yes,no"
154   (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
155                          (const_string "yes") (const_string "no"))))
156
157 (define_attr "fmovd" "yes,no"
158   (const (if_then_else (symbol_ref "TARGET_FMOVD")
159                        (const_string "yes") (const_string "no"))))
160 ;; issues/clock
161 (define_attr "issues" "1,2"
162   (const (if_then_else (symbol_ref "TARGET_SUPERSCALAR") (const_string "2") (const_string "1"))))
163
164 ;; cbranch      conditional branch instructions
165 ;; jump         unconditional jumps
166 ;; arith        ordinary arithmetic
167 ;; arith3       a compound insn that behaves similarly to a sequence of
168 ;;              three insns of type arith
169 ;; arith3b      like above, but might end with a redirected branch
170 ;; load         from memory
171 ;; load_si      Likewise, SImode variant for general register.
172 ;; store        to memory
173 ;; move         register to register
174 ;; fmove        register to register, floating point
175 ;; smpy         word precision integer multiply
176 ;; dmpy         longword or doublelongword precision integer multiply
177 ;; return       rts
178 ;; pload        load of pr reg, which can't be put into delay slot of rts
179 ;; prset        copy register to pr reg, ditto
180 ;; pstore       store of pr reg, which can't be put into delay slot of jsr
181 ;; prget        copy pr to register, ditto
182 ;; pcload       pc relative load of constant value
183 ;; pcload_si    Likewise, SImode variant for general register.
184 ;; rte          return from exception
185 ;; sfunc        special function call with known used registers
186 ;; call         function call
187 ;; fp           floating point
188 ;; fdiv         floating point divide (or square root)
189 ;; gp_fpul      move between general purpose register and fpul
190 ;; dfp_arith, dfp_cmp,dfp_conv
191 ;; dfdiv        double precision floating point divide (or square root)
192 ;; nil          no-op move, will be deleted.
193
194 (define_attr "type"
195  "cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,other,load,load_si,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pt,ptabs,rte,sfunc,call,fp,fdiv,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,nil"
196   (const_string "other"))
197
198 ;; Indicate what precision must be selected in fpscr for this insn, if any.
199
200 (define_attr "fp_mode" "single,double,none" (const_string "none"))
201
202 ; If a conditional branch destination is within -252..258 bytes away
203 ; from the instruction it can be 2 bytes long.  Something in the
204 ; range -4090..4100 bytes can be 6 bytes long.  All other conditional
205 ; branches are initially assumed to be 16 bytes long.
206 ; In machine_dependent_reorg, we split all branches that are longer than
207 ; 2 bytes.
208
209 ;; The maximum range used for SImode constant pool entries is 1018.  A final
210 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
211 ;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
212 ;; instruction around the pool table, 2 bytes of alignment before the table,
213 ;; and 30 bytes of alignment after the table.  That gives a maximum total
214 ;; pool size of 1058 bytes.
215 ;; Worst case code/pool content size ratio is 1:2 (using asms).
216 ;; Thus, in the worst case, there is one instruction in front of a maximum
217 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
218 ;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
219 ;; If we have a forward branch, the initial table will be put after the
220 ;; unconditional branch.
221 ;;
222 ;; ??? We could do much better by keeping track of the actual pcloads within
223 ;; the branch range and in the pcload range in front of the branch range.
224
225 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
226 ;; inside an le.
227 (define_attr "short_cbranch_p" "no,yes"
228   (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
229          (const_string "no")
230          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
231          (const_string "yes")
232          (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
233          (const_string "no")
234          (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
235          (const_string "yes")
236          ] (const_string "no")))
237
238 (define_attr "med_branch_p" "no,yes"
239   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
240               (const_int 1988))
241          (const_string "yes")
242          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
243          (const_string "no")
244          (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
245               (const_int 8186))
246          (const_string "yes")
247          ] (const_string "no")))
248
249 (define_attr "med_cbranch_p" "no,yes"
250   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
251               (const_int 1986))
252          (const_string "yes")
253          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
254          (const_string "no")
255          (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
256                (const_int 8184))
257          (const_string "yes")
258          ] (const_string "no")))
259
260 (define_attr "braf_branch_p" "no,yes"
261   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
262          (const_string "no")
263          (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
264               (const_int 20660))
265          (const_string "yes")
266          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
267          (const_string "no")
268          (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
269               (const_int 65530))
270          (const_string "yes")
271          ] (const_string "no")))
272
273 (define_attr "braf_cbranch_p" "no,yes"
274   (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
275          (const_string "no")
276          (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
277               (const_int 20658))
278          (const_string "yes")
279          (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
280          (const_string "no")
281          (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
282               (const_int 65528))
283          (const_string "yes")
284          ] (const_string "no")))
285
286 ; An unconditional jump in the range -4092..4098 can be 2 bytes long.
287 ; For wider ranges, we need a combination of a code and a data part.
288 ; If we can get a scratch register for a long range jump, the code
289 ; part can be 4 bytes long; otherwise, it must be 8 bytes long.
290 ; If the jump is in the range -32764..32770, the data part can be 2 bytes
291 ; long; otherwise, it must be 6 bytes long.
292
293 ; All other instructions are two bytes long by default.
294
295 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
296 ;; but getattrtab doesn't understand this.
297 (define_attr "length" ""
298   (cond [(eq_attr "type" "cbranch")
299          (cond [(eq_attr "short_cbranch_p" "yes")
300                 (const_int 2)
301                 (eq_attr "med_cbranch_p" "yes")
302                 (const_int 6)
303                 (eq_attr "braf_cbranch_p" "yes")
304                 (const_int 12)
305 ;; ??? using pc is not computed transitively.
306                 (ne (match_dup 0) (match_dup 0))
307                 (const_int 14)
308                 (ne (symbol_ref ("flag_pic")) (const_int 0))
309                 (const_int 24)
310                 ] (const_int 16))
311          (eq_attr "type" "jump")
312          (cond [(eq_attr "med_branch_p" "yes")
313                 (const_int 2)
314                 (and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))")
315                          (symbol_ref "INSN"))
316                      (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))")
317                          (symbol_ref "code_for_indirect_jump_scratch")))
318                 (if_then_else (eq_attr "braf_branch_p" "yes")
319                               (const_int 6)
320                               (const_int 10))
321                 (eq_attr "braf_branch_p" "yes")
322                 (const_int 10)
323 ;; ??? using pc is not computed transitively.
324                 (ne (match_dup 0) (match_dup 0))
325                 (const_int 12)
326                 (ne (symbol_ref ("flag_pic")) (const_int 0))
327                 (const_int 22)
328                 ] (const_int 14))
329          (eq_attr "type" "pt")
330          (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
331                        (const_int 20) (const_int 12))
332          ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
333                          (const_int 4)
334                          (const_int 2))))
335
336 ;; (define_function_unit {name} {num-units} {n-users} {test}
337 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
338
339 ;; Load and store instructions save a cycle if they are aligned on a
340 ;; four byte boundary.  Using a function unit for stores encourages
341 ;; gcc to separate load and store instructions by one instruction,
342 ;; which makes it more likely that the linker will be able to word
343 ;; align them when relaxing.
344
345 ;; Loads have a latency of two.
346 ;; However, call insns can have a delay slot, so that we want one more
347 ;; insn to be scheduled between the load of the function address and the call.
348 ;; This is equivalent to a latency of three.
349 ;; We cannot use a conflict list for this, because we need to distinguish
350 ;; between the actual call address and the function arguments.
351 ;; ADJUST_COST can only properly handle reductions of the cost, so we
352 ;; use a latency of three here.
353 ;; We only do this for SImode loads of general registers, to make the work
354 ;; for ADJUST_COST easier.
355 (define_function_unit "memory" 1 0
356   (and (eq_attr "issues" "1")
357        (eq_attr "type" "load_si,pcload_si"))
358   3 2)
359 (define_function_unit "memory" 1 0
360   (and (eq_attr "issues" "1")
361        (eq_attr "type" "load,pcload,pload,store,pstore"))
362   2 2)
363
364 (define_function_unit "int"    1 0
365   (and (eq_attr "issues" "1") (eq_attr "type" "arith3,arith3b")) 3 3)
366
367 (define_function_unit "int"    1 0
368   (and (eq_attr "issues" "1") (eq_attr "type" "dyn_shift")) 2 2)
369
370 (define_function_unit "int"    1 0
371   (and (eq_attr "issues" "1") (eq_attr "type" "!arith3,arith3b,dyn_shift")) 1 1)
372
373 ;; ??? These are approximations.
374 (define_function_unit "mpy"    1 0
375   (and (eq_attr "issues" "1") (eq_attr "type" "smpy")) 2 2)
376 (define_function_unit "mpy"    1 0
377   (and (eq_attr "issues" "1") (eq_attr "type" "dmpy")) 3 3)
378
379 (define_function_unit "fp"     1 0
380   (and (eq_attr "issues" "1") (eq_attr "type" "fp,fmove")) 2 1)
381 (define_function_unit "fp"     1 0
382   (and (eq_attr "issues" "1") (eq_attr "type" "fdiv")) 13 12)
383
384
385 ;; SH4 scheduling
386 ;; The SH4 is a dual-issue implementation, thus we have to multiply all
387 ;; costs by at least two.
388 ;; There will be single increments of the modeled that don't correspond
389 ;; to the actual target ;; whenever two insns to be issued depend one a
390 ;; single resource, and the scheduler picks to be the first one.
391 ;; If we multiplied the costs just by two, just two of these single
392 ;; increments would amount to an actual cycle.  By picking a larger
393 ;; factor, we can ameliorate the effect; However, we then have to make sure
394 ;; that only two insns are modeled as issued per actual cycle.
395 ;; Moreover, we need a way to specify the latency of insns that don't
396 ;; use an actual function unit.
397 ;; We use an 'issue' function unit to do that, and a cost factor of 10.
398
399 (define_function_unit "issue" 2 0
400   (and (eq_attr "issues" "2") (eq_attr "type" "!nil,arith3"))
401   10 10)
402
403 (define_function_unit "issue" 2 0
404   (and (eq_attr "issues" "2") (eq_attr "type" "arith3"))
405   30 30)
406
407 ;; There is no point in providing exact scheduling information about branches,
408 ;; because they are at the starts / ends of basic blocks anyways.
409
410 ;; Some insns cannot be issued before/after another insn in the same cycle,
411 ;; irrespective of the type of the other insn.
412
413 ;; default is dual-issue, but can't be paired with an insn that
414 ;; uses multiple function units.
415 (define_function_unit "single_issue"     1 0
416   (and (eq_attr "issues" "2")
417        (eq_attr "type" "!smpy,dmpy,pload,pstore,dfp_cmp,gp_fpul,call,sfunc,arith3,arith3b"))
418   1 10
419   [(eq_attr "type" "smpy,dmpy,pload,pstore,dfp_cmp,gp_fpul")])
420
421 (define_function_unit "single_issue"     1 0
422   (and (eq_attr "issues" "2")
423        (eq_attr "type" "smpy,dmpy,pload,pstore,dfp_cmp,gp_fpul"))
424   10 10
425   [(const_int 1)])
426
427 ;; arith3 insns are always pairable at the start, but not inecessarily at
428 ;; the end; however, there doesn't seem to be a way to express that.
429 (define_function_unit "single_issue"     1 0
430   (and (eq_attr "issues" "2")
431        (eq_attr "type" "arith3"))
432   30 20
433   [(const_int 1)])
434
435 ;; arith3b insn are pairable at the end and have latency that prevents pairing
436 ;; with the following branch, but we don't want this latency be respected;
437 ;; When the following branch is immediately adjacent, we can redirect the
438 ;; internal branch, which is likly to be a larger win.
439 (define_function_unit "single_issue"     1 0
440   (and (eq_attr "issues" "2")
441        (eq_attr "type" "arith3b"))
442   20 20
443   [(const_int 1)])
444
445 ;; calls introduce a longisch delay that is likely to flush the pipelines.
446 (define_function_unit "single_issue"     1 0
447   (and (eq_attr "issues" "2")
448        (eq_attr "type" "call,sfunc"))
449   160 160
450   [(eq_attr "type" "!call") (eq_attr "type" "call")])
451
452 ;; Load and store instructions have no alignment peculiarities for the SH4,
453 ;; but they use the load-store unit, which they share with the fmove type
454 ;; insns (fldi[01]; fmov frn,frm; flds; fsts; fabs; fneg) .
455 ;; Loads have a latency of two.
456 ;; However, call insns can only paired with a preceding insn, and have
457 ;; a delay slot, so that we want two more insns to be scheduled between the
458 ;; load of the function address and the call.  This is equivalent to a
459 ;; latency of three.
460 ;; We cannot use a conflict list for this, because we need to distinguish
461 ;; between the actual call address and the function arguments.
462 ;; ADJUST_COST can only properly handle reductions of the cost, so we
463 ;; use a latency of three here, which gets multiplied by 10 to yield 30.
464 ;; We only do this for SImode loads of general registers, to make the work
465 ;; for ADJUST_COST easier.
466
467 ;; When specifying different latencies for different insns using the
468 ;; the same function unit, genattrtab.c assumes a 'FIFO constraint'
469 ;; so that the blockage is at least READY-COST (E) + 1 - READY-COST (C)
470 ;; for an executing insn E and a candidate insn C.
471 ;; Therefore, we define three different function units for load_store:
472 ;; load_store, load and load_si.
473
474 (define_function_unit "load_si" 1 0
475   (and (eq_attr "issues" "2")
476        (eq_attr "type" "load_si,pcload_si")) 30 10)
477 (define_function_unit "load" 1 0
478   (and (eq_attr "issues" "2")
479        (eq_attr "type" "load,pcload,pload")) 20 10)
480 (define_function_unit "load_store" 1 0
481   (and (eq_attr "issues" "2")
482        (eq_attr "type" "load_si,pcload_si,load,pcload,pload,store,pstore,fmove"))
483   10 10)
484
485 (define_function_unit "int"    1 0
486   (and (eq_attr "issues" "2") (eq_attr "type" "arith,dyn_shift")) 10 10)
487
488 ;; Again, we have to pretend a lower latency for the "int" unit to avoid a
489 ;; spurious FIFO constraint; the multiply instructions use the "int"
490 ;; unit actually only for two cycles.
491 (define_function_unit "int"    1 0
492   (and (eq_attr "issues" "2") (eq_attr "type" "smpy,dmpy")) 20 20)
493
494 ;; We use a fictous "mpy" unit to express the actual latency.
495 (define_function_unit "mpy"    1 0
496   (and (eq_attr "issues" "2") (eq_attr "type" "smpy,dmpy")) 40 20)
497
498 ;; Again, we have to pretend a lower latency for the "int" unit to avoid a
499 ;; spurious FIFO constraint.
500 (define_function_unit "int"     1 0
501   (and (eq_attr "issues" "2") (eq_attr "type" "gp_fpul")) 10 10)
502
503 ;; We use a fictous "gp_fpul" unit to express the actual latency.
504 (define_function_unit "gp_fpul"     1 0
505   (and (eq_attr "issues" "2") (eq_attr "type" "gp_fpul")) 20 10)
506
507 ;; ??? multiply uses the floating point unit, but with a two cycle delay.
508 ;; Thus, a simple single-precision fp operation could finish if issued in
509 ;; the very next cycle, but stalls when issued two or three cycles later.
510 ;; Similarily, a divide / sqrt can work without stalls if issued in
511 ;; the very next cycle, while it would have to block if issued two or
512 ;; three cycles later.
513 ;; There is no way to model this with gcc's function units.  This problem is
514 ;; actually mentioned in md.texi.  Tackling this problem requires first that
515 ;; it is possible to speak about the target in an open discussion.
516 ;; 
517 ;; However, simple double-precision operations always conflict.
518
519 (define_function_unit "fp"    1 0
520   (and (eq_attr "issues" "2") (eq_attr "type" "smpy,dmpy")) 40 40
521   [(eq_attr "type" "dfp_cmp,dfp_conv,dfp_arith")])
522
523 ;; The "fp" unit is for pipeline stages F1 and F2.
524
525 (define_function_unit "fp"     1 0
526   (and (eq_attr "issues" "2") (eq_attr "type" "fp")) 30 10)
527
528 ;; Again, we have to pretend a lower latency for the "fp" unit to avoid a
529 ;; spurious FIFO constraint; the bulk of the fdiv type insns executes in
530 ;; the F3 stage.
531 (define_function_unit "fp"     1 0
532   (and (eq_attr "issues" "2") (eq_attr "type" "fdiv")) 30 10)
533
534 ;; The "fdiv" function unit models the aggregate effect of the F1, F2 and F3
535 ;; pipeline stages on the pipelining of fdiv/fsqrt insns.
536 ;; We also use it to give the actual latency here.
537 ;; fsqrt is actually one cycle faster than fdiv (and the value used here),
538 ;; but that will hardly matter in practice for scheduling.
539 (define_function_unit "fdiv"     1 0
540   (and (eq_attr "issues" "2") (eq_attr "type" "fdiv")) 120 100)
541
542 ;; There is again a late use of the "fp" unit by [d]fdiv type insns
543 ;; that we can't express.
544
545 (define_function_unit "fp"     1 0
546   (and (eq_attr "issues" "2") (eq_attr "type" "dfp_cmp,dfp_conv")) 40 20)
547
548 (define_function_unit "fp"     1 0
549   (and (eq_attr "issues" "2") (eq_attr "type" "dfp_arith")) 80 60)
550
551 (define_function_unit "fp"     1 0
552   (and (eq_attr "issues" "2") (eq_attr "type" "dfdiv")) 230 10)
553
554 (define_function_unit "fdiv"     1 0
555   (and (eq_attr "issues" "2") (eq_attr "type" "dfdiv")) 230 210)
556
557 ;; This should be enough for pt insns to be moved 5 insns ahead of
558 ;; corresponding branches.
559 (define_function_unit "pt" 1 0
560   (eq_attr "type" "pt,ptabs") 10 2)
561
562 ; Definitions for filling branch delay slots.
563
564 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
565
566 ;; ??? This should be (nil) instead of (const_int 0)
567 (define_attr "hit_stack" "yes,no"
568         (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
569                    (const_int 0))
570                (const_string "no")]
571               (const_string "yes")))
572
573 (define_attr "interrupt_function" "no,yes"
574   (const (symbol_ref "current_function_interrupt")))
575
576 (define_attr "in_delay_slot" "yes,no"
577   (cond [(eq_attr "type" "cbranch") (const_string "no")
578          (eq_attr "type" "pcload,pcload_si") (const_string "no")
579          (eq_attr "needs_delay_slot" "yes") (const_string "no")
580          (eq_attr "length" "2") (const_string "yes")
581          ] (const_string "no")))
582
583 (define_attr "is_sfunc" ""
584   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
585
586 (define_delay
587   (eq_attr "needs_delay_slot" "yes")
588   [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
589
590 ;; On the SH and SH2, the rte instruction reads the return pc from the stack,
591 ;; and thus we can't put a pop instruction in its delay slot.
592 ;; ??? On the SH3, the rte instruction does not use the stack, so a pop
593 ;; instruction can go in the delay slot.
594
595 ;; Since a normal return (rts) implicitly uses the PR register,
596 ;; we can't allow PR register loads in an rts delay slot.
597
598 (define_delay
599   (eq_attr "type" "return")
600   [(and (eq_attr "in_delay_slot" "yes")
601         (ior (and (eq_attr "interrupt_function" "no")
602                   (eq_attr "type" "!pload,prset"))
603              (and (eq_attr "interrupt_function" "yes")
604                   (ior
605                    (ne (symbol_ref "TARGET_SH3") (const_int 0))
606                    (eq_attr "hit_stack" "no"))))) (nil) (nil)])
607
608 ;; Since a call implicitly uses the PR register, we can't allow
609 ;; a PR register store in a jsr delay slot.
610
611 (define_delay
612   (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
613   [(and (eq_attr "in_delay_slot" "yes")
614         (eq_attr "type" "!pstore,prget")) (nil) (nil)])
615
616 ;; Say that we have annulled true branches, since this gives smaller and
617 ;; faster code when branches are predicted as not taken.
618
619 (define_delay
620   (and (eq_attr "type" "cbranch")
621        (ne (symbol_ref "TARGET_SH2") (const_int 0)))
622   [(eq_attr "in_delay_slot" "yes") (eq_attr "in_delay_slot" "yes") (nil)])
623 \f
624 ;; -------------------------------------------------------------------------
625 ;; SImode signed integer comparisons
626 ;; -------------------------------------------------------------------------
627
628 (define_insn ""
629   [(set (reg:SI T_REG)
630         (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
631                        (match_operand:SI 1 "arith_operand" "L,r"))
632                (const_int 0)))]
633   "TARGET_SH1"
634   "tst  %1,%0")
635
636 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
637 ;; That would still allow reload to create cmpi instructions, but would
638 ;; perhaps allow forcing the constant into a register when that is better.
639 ;; Probably should use r0 for mem/imm compares, but force constant into a
640 ;; register for pseudo/imm compares.
641
642 (define_insn "cmpeqsi_t"
643   [(set (reg:SI T_REG)
644         (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
645                (match_operand:SI 1 "arith_operand" "N,rI,r")))]
646   "TARGET_SH1"
647   "@
648         tst     %0,%0
649         cmp/eq  %1,%0
650         cmp/eq  %1,%0")
651
652 (define_insn "cmpgtsi_t"
653   [(set (reg:SI T_REG)
654         (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
655                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
656   "TARGET_SH1"
657   "@
658         cmp/gt  %1,%0
659         cmp/pl  %0")
660
661 (define_insn "cmpgesi_t"
662   [(set (reg:SI T_REG)
663         (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
664                (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
665   "TARGET_SH1"
666   "@
667         cmp/ge  %1,%0
668         cmp/pz  %0")
669 \f
670 ;; -------------------------------------------------------------------------
671 ;; SImode unsigned integer comparisons
672 ;; -------------------------------------------------------------------------
673
674 (define_insn "cmpgeusi_t"
675   [(set (reg:SI T_REG)
676         (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
677                 (match_operand:SI 1 "arith_reg_operand" "r")))]
678   "TARGET_SH1"
679   "cmp/hs       %1,%0")
680
681 (define_insn "cmpgtusi_t"
682   [(set (reg:SI T_REG)
683         (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
684                 (match_operand:SI 1 "arith_reg_operand" "r")))]
685   "TARGET_SH1"
686   "cmp/hi       %1,%0")
687
688 ;; We save the compare operands in the cmpxx patterns and use them when
689 ;; we generate the branch.
690
691 (define_expand "cmpsi"
692   [(set (reg:SI T_REG)
693         (compare (match_operand:SI 0 "arith_operand" "")
694                  (match_operand:SI 1 "arith_operand" "")))]
695   "TARGET_SH1"
696   "
697 {
698   sh_compare_op0 = operands[0];
699   sh_compare_op1 = operands[1];
700   DONE;
701 }")
702 \f
703 ;; -------------------------------------------------------------------------
704 ;; DImode signed integer comparisons
705 ;; -------------------------------------------------------------------------
706
707 ;; ??? Could get better scheduling by splitting the initial test from the
708 ;; rest of the insn after reload.  However, the gain would hardly justify
709 ;; the sh.md size increase necessary to do that.
710
711 (define_insn ""
712   [(set (reg:SI T_REG)
713         (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
714                        (match_operand:DI 1 "arith_operand" "r"))
715                (const_int 0)))]
716   "TARGET_SH1"
717   "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
718                                  insn, operands);"
719   [(set_attr "length" "6")
720    (set_attr "type" "arith3b")])
721
722 (define_insn "cmpeqdi_t"
723   [(set (reg:SI T_REG)
724         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
725                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
726   "TARGET_SH1"
727   "@
728         tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
729         cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
730   [(set_attr "length" "6")
731    (set_attr "type" "arith3b")])
732
733 (define_split
734   [(set (reg:SI T_REG)
735         (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
736                (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
737 ;; If we applied this split when not optimizing, it would only be
738 ;; applied during the machine-dependent reorg, when no new basic blocks
739 ;; may be created.
740   "TARGET_SH1 && reload_completed && optimize"
741   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
742    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
743                            (label_ref (match_dup 6))
744                            (pc)))
745    (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
746    (match_dup 6)]
747   "
748 {
749   operands[2]
750     = gen_rtx_REG (SImode,
751                    true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
752   operands[3]
753     = (operands[1] == const0_rtx
754        ? const0_rtx
755        : gen_rtx_REG (SImode,
756                       true_regnum (operands[1])
757                       + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
758   operands[4] = gen_lowpart (SImode, operands[0]);
759   operands[5] = gen_lowpart (SImode, operands[1]);
760   operands[6] = gen_label_rtx ();
761 }")
762
763 (define_insn "cmpgtdi_t"
764   [(set (reg:SI T_REG)
765         (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
766                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
767   "TARGET_SH2"
768   "@
769         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
770         tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
771   [(set_attr "length" "8")
772    (set_attr "type" "arith3")])
773
774 (define_insn "cmpgedi_t"
775   [(set (reg:SI T_REG)
776         (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
777                (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
778   "TARGET_SH2"
779   "@
780         cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
781         cmp/pz\\t%S0"
782   [(set_attr "length" "8,2")
783    (set_attr "type" "arith3,arith")])
784 \f
785 ;; -------------------------------------------------------------------------
786 ;; DImode unsigned integer comparisons
787 ;; -------------------------------------------------------------------------
788
789 (define_insn "cmpgeudi_t"
790   [(set (reg:SI T_REG)
791         (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
792                 (match_operand:DI 1 "arith_reg_operand" "r")))]
793   "TARGET_SH2"
794   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
795   [(set_attr "length" "8")
796    (set_attr "type" "arith3")])
797
798 (define_insn "cmpgtudi_t"
799   [(set (reg:SI T_REG)
800         (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
801                 (match_operand:DI 1 "arith_reg_operand" "r")))]
802   "TARGET_SH2"
803   "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
804   [(set_attr "length" "8")
805    (set_attr "type" "arith3")])
806
807 (define_insn "cmpeqdi_media"
808   [(set (match_operand:DI 0 "register_operand" "=r,r")
809         (eq:DI (match_operand:DI 1 "register_operand" "%r,r")
810                (match_operand:DI 2 "arith_reg_or_0_operand" "N,r")))]
811   "TARGET_SHMEDIA"
812   "@
813         cmpeq   %1, r63, %0
814         cmpeq   %1, %2, %0")
815
816 (define_insn "cmpgtdi_media"
817   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
818         (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "N,r,r")
819                (match_operand:DI 2 "arith_reg_or_0_operand" "r,N,r")))]
820   "TARGET_SHMEDIA"
821   "@
822         cmpgt   r63, %2, %0
823         cmpgt   %1, r63, %0
824         cmpgt   %1, %2, %0")
825
826 (define_insn "cmpgtudi_media"
827   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
828         (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "N,r,r")
829                 (match_operand:DI 2 "arith_reg_or_0_operand" "r,N,r")))]
830   "TARGET_SHMEDIA"
831   "@
832         cmpgtu  r63, %2, %0
833         cmpgtu  %1, r63, %0
834         cmpgtu  %1, %2, %0")
835
836 ;; We save the compare operands in the cmpxx patterns and use them when
837 ;; we generate the branch.
838
839 (define_expand "cmpdi"
840   [(set (reg:SI T_REG)
841         (compare (match_operand:DI 0 "arith_operand" "")
842                  (match_operand:DI 1 "arith_operand" "")))]
843   "TARGET_SH2 || TARGET_SHMEDIA"
844   "
845 {
846   sh_compare_op0 = operands[0];
847   sh_compare_op1 = operands[1];
848   DONE;
849 }")
850 ;; -------------------------------------------------------------------------
851 ;; Conditional move instructions
852 ;; -------------------------------------------------------------------------
853
854 ;; The insn names may seem reversed, but note that cmveq performs the move
855 ;; if op1 == 0, and cmvne does it if op1 != 0.
856
857 (define_insn "movdicc_false"
858   [(set (match_operand:DI 0 "register_operand" "=r")
859         (if_then_else:DI (eq (match_operand:DI 1 "register_operand" "r")
860                              (const_int 0))
861          (match_operand:DI 2 "register_operand" "r")
862          (match_operand:DI 3 "register_operand" "0")))]
863   "TARGET_SHMEDIA"
864   "cmveq        %1, %2, %0")
865
866 (define_insn "movdicc_true"
867   [(set (match_operand:DI 0 "register_operand" "=r")
868         (if_then_else:DI (ne (match_operand:DI 1 "register_operand" "r")
869                              (const_int 0))
870          (match_operand:DI 2 "register_operand" "r")
871          (match_operand:DI 3 "register_operand" "0")))]
872   "TARGET_SHMEDIA"
873   "cmvne        %1, %2, %0")
874
875 (define_expand "movdicc"
876   [(set (match_operand:DI 0 "register_operand" "")
877         (if_then_else:DI (match_operand 1 "comparison_operator" "")
878                          (match_operand:DI 2 "register_operand" "")
879                          (match_operand:DI 3 "register_operand" "")))]
880   "TARGET_SHMEDIA"
881   "
882 {
883   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
884       && GET_MODE (sh_compare_op0) == DImode
885       && sh_compare_op1 == const0_rtx)
886     operands[1] = gen_rtx (GET_CODE (operands[1]), VOIDmode,
887                            sh_compare_op0, sh_compare_op1);
888   else
889     {
890       rtx tmp;
891
892       if (no_new_pseudos)
893         FAIL;
894
895       tmp = gen_reg_rtx (DImode);
896
897       switch (GET_CODE (operands[1]))
898         {
899         case EQ:
900           emit_insn (gen_seq (tmp));
901           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
902           break;
903
904         case NE:
905           emit_insn (gen_seq (tmp));
906           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
907           break;
908
909         case GT:
910           emit_insn (gen_sgt (tmp));
911           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
912           break;
913
914         case LT:
915           emit_insn (gen_slt (tmp));
916           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
917           break;
918
919         case GE:
920           emit_insn (gen_slt (tmp));
921           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
922           break;
923
924         case LE:
925           emit_insn (gen_sgt (tmp));
926           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
927           break;
928
929         case GTU:
930           emit_insn (gen_sgtu (tmp));
931           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
932           break;
933
934         case LTU:
935           emit_insn (gen_sltu (tmp));
936           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
937           break;
938
939         case GEU:
940           emit_insn (gen_sltu (tmp));
941           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
942           break;
943
944         case LEU:
945           emit_insn (gen_sgtu (tmp));
946           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
947           break;
948
949         case UNORDERED:
950           emit_insn (gen_sunordered (tmp));
951           operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
952           break;
953
954         case ORDERED:
955           emit_insn (gen_sunordered (tmp));
956           operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
957           break;
958
959         case UNEQ:
960         case UNGE:
961         case UNGT:
962         case UNLE:
963         case UNLT:
964         case LTGT:
965           FAIL;
966
967         default:
968           abort ();
969         }
970     }
971 }")
972 \f
973 ;; -------------------------------------------------------------------------
974 ;; Addition instructions
975 ;; -------------------------------------------------------------------------
976
977 (define_expand "adddi3"
978   [(set (match_operand:DI 0 "arith_reg_operand" "")
979         (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
980                  (match_operand:DI 2 "arith_operand" "")))]
981   ""
982   "
983 {
984   if (TARGET_SH1)
985     {
986       if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
987         FAIL;
988       operands[2] = force_reg (DImode, operands[2]);
989       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
990       DONE;
991     }
992 }")
993
994 (define_insn "*adddi3_media"
995   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
996         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
997                  (match_operand:DI 2 "arith_operand" "r,P")))]
998   "TARGET_SHMEDIA"
999   "@
1000         add     %1, %2, %0
1001         addi    %1, %2, %0")
1002
1003 (define_insn "*adddi3z_media"
1004   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
1005         (zero_extend:DI
1006          (plus:SI (match_operand:SI 1 "arith_reg_operand" "r,r")
1007                   (match_operand:SI 2 "arith_reg_or_0_operand" "r,n"))))]
1008   "TARGET_SHMEDIA"
1009   "@
1010         addz.l  %1, %2, %0
1011         addz.l  %1, r63, %0")
1012                  
1013 (define_insn "adddi3_compact"
1014   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1015         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1016                  (match_operand:DI 2 "arith_reg_operand" "r")))
1017    (clobber (reg:SI T_REG))]
1018   "TARGET_SH1"
1019   "#"
1020   [(set_attr "length" "6")])
1021
1022 (define_split
1023   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1024         (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1025                  (match_operand:DI 2 "arith_reg_operand" "r")))
1026    (clobber (reg:SI T_REG))]
1027   "TARGET_SH1 && reload_completed"
1028   [(const_int 0)]
1029   "
1030 {
1031   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1032   high0 = gen_rtx_REG (SImode,
1033                        true_regnum (operands[0])
1034                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1035   high2 = gen_rtx_REG (SImode,
1036                        true_regnum (operands[2])
1037                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1038   emit_insn (gen_clrt ());
1039   emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1040   emit_insn (gen_addc1 (high0, high0, high2));
1041   DONE;
1042 }")
1043
1044 (define_insn "addc"
1045   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1046         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1047                           (match_operand:SI 2 "arith_reg_operand" "r"))
1048                  (reg:SI T_REG)))
1049    (set (reg:SI T_REG)
1050         (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1051   "TARGET_SH1"
1052   "addc %2,%0"
1053   [(set_attr "type" "arith")])
1054
1055 (define_insn "addc1"
1056   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1057         (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1058                           (match_operand:SI 2 "arith_reg_operand" "r"))
1059                  (reg:SI T_REG)))
1060    (clobber (reg:SI T_REG))]
1061   "TARGET_SH1"
1062   "addc %2,%0"
1063   [(set_attr "type" "arith")])
1064
1065 (define_expand "addsi3"
1066   [(set (match_operand:SI 0 "arith_reg_operand" "")
1067         (plus:SI (match_operand:SI 1 "arith_operand" "")
1068                  (match_operand:SI 2 "arith_operand" "")))]
1069   ""
1070   "
1071 {
1072   if (TARGET_SHMEDIA)
1073     operands[1] = force_reg (SImode, operands[1]);
1074 }")
1075
1076 (define_insn "addsi3_media"
1077   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
1078         (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
1079                  (match_operand:SI 2 "arith_operand" "r,P")))]
1080   "TARGET_SHMEDIA"
1081   "@
1082         add.l   %1, %2, %0
1083         addi.l  %1, %2, %0")
1084   
1085 (define_insn "*addsi3_compact"
1086   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1087         (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1088                  (match_operand:SI 2 "arith_operand" "rI")))]
1089   "TARGET_SH1"
1090   "add  %2,%0"
1091   [(set_attr "type" "arith")])
1092 \f
1093 ;; -------------------------------------------------------------------------
1094 ;; Subtraction instructions
1095 ;; -------------------------------------------------------------------------
1096
1097 (define_expand "subdi3"
1098   [(set (match_operand:DI 0 "arith_reg_operand" "")
1099         (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1100                   (match_operand:DI 2 "arith_reg_operand" "")))]
1101   ""
1102   "
1103 {
1104   if (TARGET_SH1)
1105     {
1106       emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1107       DONE;
1108     }
1109 }")
1110   
1111 (define_insn "*subdi3_media"
1112   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1113         (minus:DI (match_operand:DI 1 "arith_reg_operand" "r")
1114                   (match_operand:DI 2 "arith_reg_operand" "r")))]
1115   "TARGET_SHMEDIA"
1116   "sub  %1, %2, %0")
1117   
1118 (define_insn "subdi3_compact"
1119   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1120         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1121                  (match_operand:DI 2 "arith_reg_operand" "r")))
1122    (clobber (reg:SI T_REG))]
1123   "TARGET_SH1"
1124   "#"
1125   [(set_attr "length" "6")])
1126
1127 (define_split
1128   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1129         (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1130                   (match_operand:DI 2 "arith_reg_operand" "r")))
1131    (clobber (reg:SI T_REG))]
1132   "TARGET_SH1 && reload_completed"
1133   [(const_int 0)]
1134   "
1135 {
1136   rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1137   high0 = gen_rtx_REG (SImode,
1138                        true_regnum (operands[0])
1139                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1140   high2 = gen_rtx_REG (SImode,
1141                        true_regnum (operands[2])
1142                        + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1143   emit_insn (gen_clrt ());
1144   emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1145   emit_insn (gen_subc1 (high0, high0, high2));
1146   DONE;
1147 }")
1148
1149 (define_insn "subc"
1150   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1151         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1152                             (match_operand:SI 2 "arith_reg_operand" "r"))
1153                   (reg:SI T_REG)))
1154    (set (reg:SI T_REG)
1155         (gtu:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1156   "TARGET_SH1"
1157   "subc %2,%0"
1158   [(set_attr "type" "arith")])
1159
1160 (define_insn "subc1"
1161   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1162         (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1163                             (match_operand:SI 2 "arith_reg_operand" "r"))
1164                   (reg:SI T_REG)))
1165    (clobber (reg:SI T_REG))]
1166   "TARGET_SH1"
1167   "subc %2,%0"
1168   [(set_attr "type" "arith")])
1169
1170 (define_insn "*subsi3_internal"
1171   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1172         (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1173                   (match_operand:SI 2 "arith_reg_operand" "r")))]
1174   "TARGET_SH1"
1175   "sub  %2,%0"
1176   [(set_attr "type" "arith")])
1177
1178 (define_insn "*subsi3_media"
1179   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1180         (minus:SI (match_operand:SI 1 "arith_reg_operand" "r")
1181                   (match_operand:SI 2 "arith_reg_operand" "r")))]
1182   "TARGET_SHMEDIA"
1183   "sub.l        %1, %2, %0")
1184
1185 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1186 ;; will sometimes save one instruction.  Otherwise we might get
1187 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1188 ;; are the same.
1189
1190 (define_expand "subsi3"
1191   [(set (match_operand:SI 0 "arith_reg_operand" "")
1192         (minus:SI (match_operand:SI 1 "arith_operand" "")
1193                   (match_operand:SI 2 "arith_reg_operand" "")))]
1194   ""
1195   "
1196 {
1197   if (TARGET_SH1 && GET_CODE (operands[1]) == CONST_INT)
1198     {
1199       emit_insn (gen_negsi2 (operands[0], operands[2]));
1200       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1201       DONE;
1202     }
1203   if (TARGET_SHMEDIA)
1204     {
1205       if (no_new_pseudos && ! arith_reg_operand (operands[1], SImode))
1206         FAIL;
1207       operands[1] = force_reg (SImode, operands[1]);
1208     }
1209 }")
1210 \f
1211 ;; -------------------------------------------------------------------------
1212 ;; Division instructions
1213 ;; -------------------------------------------------------------------------
1214
1215 ;; We take advantage of the library routines which don't clobber as many
1216 ;; registers as a normal function call would.
1217
1218 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1219 ;; also has an effect on the register that holds the address of the sfunc.
1220 ;; To make this work, we have an extra dummy insns that shows the use
1221 ;; of this register for reorg.
1222
1223 (define_insn "use_sfunc_addr"
1224   [(set (reg:SI PR_REG)
1225         (unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1226   "TARGET_SH1"
1227   ""
1228   [(set_attr "length" "0")])
1229
1230 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1231 ;; hard register 0.  If we used hard register 0, then the next instruction
1232 ;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1233 ;; gets allocated to a stack slot that needs its address reloaded, then
1234 ;; there is nothing to prevent reload from using r0 to reload the address.
1235 ;; This reload would clobber the value in r0 we are trying to store.
1236 ;; If we let reload allocate r0, then this problem can never happen.
1237
1238 (define_insn "udivsi3_i1"
1239   [(set (match_operand:SI 0 "register_operand" "=z")
1240         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1241    (clobber (reg:SI T_REG))
1242    (clobber (reg:SI PR_REG))
1243    (clobber (reg:SI R4_REG))
1244    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1245   "TARGET_SH1 && ! TARGET_SH4"
1246   "jsr  @%1%#"
1247   [(set_attr "type" "sfunc")
1248    (set_attr "needs_delay_slot" "yes")])
1249
1250 (define_insn "udivsi3_i1_media"
1251   [(set (match_operand:SI 0 "register_operand" "=z")
1252         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1253    (clobber (reg:SI T_MEDIA_REG))
1254    (clobber (reg:SI PR_MEDIA_REG))
1255    (clobber (reg:SI R4_REG))
1256    (clobber (reg:DI TR0_REG))
1257    (clobber (reg:DI TR1_REG))
1258    (clobber (reg:DI TR2_REG))
1259    (use (match_operand:DI 1 "target_operand" "b"))]
1260   "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
1261   "blink        %1, r18"
1262   [(set_attr "type" "sfunc")
1263    (set_attr "needs_delay_slot" "yes")])
1264
1265 (define_expand "udivsi3_i4_media"
1266   [(set (match_dup 2) (zero_extend:DI (reg:SI R4_REG)))
1267    (set (match_dup 3) (zero_extend:DI (reg:SI R5_REG)))
1268    (set (match_dup 4) (float:DF (match_dup 2)))
1269    (set (match_dup 5) (float:DF (match_dup 3)))
1270    (set (match_dup 6) (div:DF (match_dup 4) (match_dup 5)))
1271    (set (subreg:DI (match_operand:SI 0 "register_operand" "=r") 0)
1272         (fix:DI (match_dup 6)))]
1273   "TARGET_SHMEDIA_FPU"
1274   "
1275 {
1276   operands[2] = gen_reg_rtx (DImode);
1277   operands[3] = gen_reg_rtx (DImode);
1278   operands[4] = gen_reg_rtx (DFmode);
1279   operands[5] = gen_reg_rtx (DFmode);
1280   operands[6] = gen_reg_rtx (DFmode);
1281 }")
1282
1283 (define_insn "udivsi3_i4"
1284   [(set (match_operand:SI 0 "register_operand" "=y")
1285         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1286    (clobber (reg:SI T_REG))
1287    (clobber (reg:SI PR_REG))
1288    (clobber (reg:DF DR0_REG))
1289    (clobber (reg:DF DR2_REG))
1290    (clobber (reg:DF DR4_REG))
1291    (clobber (reg:SI R0_REG))
1292    (clobber (reg:SI R1_REG))
1293    (clobber (reg:SI R4_REG))
1294    (clobber (reg:SI R5_REG))
1295    (use (reg:PSI FPSCR_REG))
1296    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1297   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1298   "jsr  @%1%#"
1299   [(set_attr "type" "sfunc")
1300    (set_attr "fp_mode" "double")
1301    (set_attr "needs_delay_slot" "yes")])
1302
1303 (define_insn "udivsi3_i4_single"
1304   [(set (match_operand:SI 0 "register_operand" "=y")
1305         (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1306    (clobber (reg:SI T_REG))
1307    (clobber (reg:SI PR_REG))
1308    (clobber (reg:DF DR0_REG))
1309    (clobber (reg:DF DR2_REG))
1310    (clobber (reg:DF DR4_REG))
1311    (clobber (reg:SI R0_REG))
1312    (clobber (reg:SI R1_REG))
1313    (clobber (reg:SI R4_REG))
1314    (clobber (reg:SI R5_REG))
1315    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1316   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1317   "jsr  @%1%#"
1318   [(set_attr "type" "sfunc")
1319    (set_attr "needs_delay_slot" "yes")])
1320
1321 (define_expand "udivsi3"
1322   [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1323    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1324    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1325    (parallel [(set (match_operand:SI 0 "register_operand" "")
1326                    (udiv:SI (reg:SI R4_REG)
1327                             (reg:SI R5_REG)))
1328               (clobber (reg:SI T_REG))
1329               (clobber (reg:SI PR_REG))
1330               (clobber (reg:SI R4_REG))
1331               (use (match_dup 3))])]
1332   ""
1333   "
1334 {
1335   rtx first, last;
1336
1337   operands[3] = gen_reg_rtx (Pmode);
1338   /* Emit the move of the address to a pseudo outside of the libcall.  */
1339   if (TARGET_HARD_SH4 && TARGET_SH3E)
1340     {
1341       emit_move_insn (operands[3],
1342                       gen_rtx_SYMBOL_REF (SImode, \"__udivsi3_i4\"));
1343       if (TARGET_FPU_SINGLE)
1344         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1345       else
1346         last = gen_udivsi3_i4 (operands[0], operands[3]);
1347     }
1348   else if (TARGET_SHMEDIA_FPU)
1349     last = gen_udivsi3_i4_media (operands[0]);
1350   else if (TARGET_SH5)
1351     {
1352       emit_move_insn (operands[3],
1353                       gen_rtx_SYMBOL_REF (Pmode,
1354                                           (TARGET_FPU_ANY
1355                                            ? \"__udivsi3_i4\"
1356                                            : \"__udivsi3\")));
1357
1358       if (TARGET_SHMEDIA)
1359         last = gen_udivsi3_i1_media (operands[0],
1360                                      Pmode == DImode
1361                                      ? operands[3]
1362                                      : gen_rtx_SUBREG (DImode, operands[3],
1363                                                        0));
1364       else if (TARGET_FPU_ANY)
1365         last = gen_udivsi3_i4_single (operands[0], operands[3]);
1366       else
1367         last = gen_udivsi3_i1 (operands[0], operands[3]);
1368     }
1369   else
1370     {
1371       emit_move_insn (operands[3],
1372                       gen_rtx_SYMBOL_REF (SImode, \"__udivsi3\"));
1373       last = gen_udivsi3_i1 (operands[0], operands[3]);
1374     }
1375   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1376   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1377   last = emit_insn (last);
1378   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1379      invariant code motion can move it.  */
1380   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1381   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1382   DONE;
1383 }")
1384
1385 (define_insn "divsi3_i1"
1386   [(set (match_operand:SI 0 "register_operand" "=z")
1387         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1388    (clobber (reg:SI T_REG))
1389    (clobber (reg:SI PR_REG))
1390    (clobber (reg:SI R1_REG))
1391    (clobber (reg:SI R2_REG))
1392    (clobber (reg:SI R3_REG))
1393    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1394   "TARGET_SH1 && ! TARGET_SH4"
1395   "jsr  @%1%#"
1396   [(set_attr "type" "sfunc")
1397    (set_attr "needs_delay_slot" "yes")])
1398
1399 (define_insn "divsi3_i1_media"
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_MEDIA_REG))
1403    (clobber (reg:SI PR_MEDIA_REG))
1404    (clobber (reg:SI R1_REG))
1405    (clobber (reg:SI R2_REG))
1406    (clobber (reg:SI R3_REG))
1407    (clobber (reg:DI TR0_REG))
1408    (clobber (reg:DI TR1_REG))
1409    (clobber (reg:DI TR2_REG))
1410    (use (match_operand:DI 1 "target_operand" "b"))]
1411   "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
1412   "blink        %1, r18")
1413
1414 (define_expand "divsi3_i4_media"
1415   [(set (match_dup 2) (reg:SI R4_REG))
1416    (set (match_dup 3) (reg:SI R5_REG))
1417    (set (match_dup 4) (float:DF (match_dup 2)))
1418    (set (match_dup 5) (float:DF (match_dup 3)))
1419    (set (match_dup 6) (div:DF (match_dup 4) (match_dup 5)))
1420    (set (match_operand:SI 0 "register_operand" "=r")
1421         (fix:SI (match_dup 6)))]
1422   "TARGET_SHMEDIA_FPU"
1423   "
1424 {
1425   operands[2] = gen_reg_rtx (SImode);
1426   operands[3] = gen_reg_rtx (SImode);
1427   operands[4] = gen_reg_rtx (DFmode);
1428   operands[5] = gen_reg_rtx (DFmode);
1429   operands[6] = gen_reg_rtx (DFmode);
1430 }")
1431
1432 (define_insn "divsi3_i4"
1433   [(set (match_operand:SI 0 "register_operand" "=y")
1434         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1435    (clobber (reg:SI PR_REG))
1436    (clobber (reg:DF DR0_REG))
1437    (clobber (reg:DF DR2_REG))
1438    (use (reg:PSI FPSCR_REG))
1439    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1440   "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1441   "jsr  @%1%#"
1442   [(set_attr "type" "sfunc")
1443    (set_attr "fp_mode" "double")
1444    (set_attr "needs_delay_slot" "yes")])
1445
1446 (define_insn "divsi3_i4_single"
1447   [(set (match_operand:SI 0 "register_operand" "=y")
1448         (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1449    (clobber (reg:SI PR_REG))
1450    (clobber (reg:DF DR0_REG))
1451    (clobber (reg:DF DR2_REG))
1452    (clobber (reg:SI R2_REG))
1453    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1454   "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1455   "jsr  @%1%#"
1456   [(set_attr "type" "sfunc")
1457    (set_attr "needs_delay_slot" "yes")])
1458
1459 (define_expand "divsi3"
1460   [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
1461    (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1462    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1463    (parallel [(set (match_operand:SI 0 "register_operand" "")
1464                    (div:SI (reg:SI R4_REG)
1465                            (reg:SI R5_REG)))
1466               (clobber (reg:SI T_REG))
1467               (clobber (reg:SI PR_REG))
1468               (clobber (reg:SI R1_REG))
1469               (clobber (reg:SI R2_REG))
1470               (clobber (reg:SI R3_REG))
1471               (use (match_dup 3))])]
1472   ""
1473   "
1474 {
1475   rtx first, last;
1476
1477   operands[3] = gen_reg_rtx (Pmode);
1478   /* Emit the move of the address to a pseudo outside of the libcall.  */
1479   if (TARGET_HARD_SH4 && TARGET_SH3E)
1480     {
1481       emit_move_insn (operands[3],
1482                       gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3_i4\"));
1483       if (TARGET_FPU_SINGLE)
1484         last = gen_divsi3_i4_single (operands[0], operands[3]);
1485       else
1486         last = gen_divsi3_i4 (operands[0], operands[3]);
1487     }
1488   else if (TARGET_SHMEDIA_FPU)
1489     last = gen_divsi3_i4_media (operands[0]);
1490   else if (TARGET_SH5)
1491     {
1492       emit_move_insn (operands[3],
1493                       gen_rtx_SYMBOL_REF (Pmode,
1494                                           (TARGET_FPU_ANY
1495                                            ? \"__sdivsi3_i4\"
1496                                            : \"__sdivsi3\")));
1497
1498       if (TARGET_SHMEDIA)
1499         last = gen_divsi3_i1_media (operands[0], 
1500                                     Pmode == DImode
1501                                     ? operands[3]
1502                                     : gen_rtx_SUBREG (DImode, operands[3],
1503                                                       0));
1504       else if (TARGET_FPU_ANY)
1505         last = gen_divsi3_i4_single (operands[0], operands[3]);
1506       else
1507         last = gen_divsi3_i1 (operands[0], operands[3]);
1508     }
1509   else
1510     {
1511       emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\"));
1512       last = gen_divsi3_i1 (operands[0], operands[3]);
1513     }
1514   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1515   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1516   last = emit_insn (last);
1517   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1518      invariant code motion can move it.  */
1519   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1520   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1521   DONE;
1522 }")
1523 \f
1524 ;; -------------------------------------------------------------------------
1525 ;; Multiplication instructions
1526 ;; -------------------------------------------------------------------------
1527
1528 (define_insn "umulhisi3_i"
1529   [(set (reg:SI MACL_REG)
1530         (mult:SI (zero_extend:SI
1531                   (match_operand:HI 0 "arith_reg_operand" "r"))
1532                  (zero_extend:SI
1533                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
1534   "TARGET_SH1"
1535   "mulu.w       %1,%0"
1536   [(set_attr "type" "smpy")])
1537
1538 (define_insn "mulhisi3_i"
1539   [(set (reg:SI MACL_REG)
1540         (mult:SI (sign_extend:SI
1541                   (match_operand:HI 0 "arith_reg_operand" "r"))
1542                  (sign_extend:SI
1543                   (match_operand:HI 1 "arith_reg_operand" "r"))))]
1544   "TARGET_SH1"
1545   "muls.w       %1,%0"
1546   [(set_attr "type" "smpy")])
1547
1548 (define_expand "mulhisi3"
1549   [(set (reg:SI MACL_REG)
1550         (mult:SI (sign_extend:SI
1551                   (match_operand:HI 1 "arith_reg_operand" ""))
1552                  (sign_extend:SI
1553                   (match_operand:HI 2 "arith_reg_operand" ""))))
1554    (set (match_operand:SI 0 "arith_reg_operand" "")
1555         (reg:SI MACL_REG))]
1556   "TARGET_SH1"
1557   "
1558 {
1559   rtx first, last;
1560
1561   first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
1562   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
1563   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1564      invariant code motion can move it.  */
1565   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1566   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1567   DONE;
1568 }")
1569
1570 (define_expand "umulhisi3"
1571   [(set (reg:SI MACL_REG)
1572         (mult:SI (zero_extend:SI
1573                   (match_operand:HI 1 "arith_reg_operand" ""))
1574                  (zero_extend:SI
1575                   (match_operand:HI 2 "arith_reg_operand" ""))))
1576    (set (match_operand:SI 0 "arith_reg_operand" "")
1577         (reg:SI MACL_REG))]
1578   "TARGET_SH1"
1579   "
1580 {
1581   rtx first, last;
1582
1583   first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
1584   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
1585   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1586      invariant code motion can move it.  */
1587   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1588   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1589   DONE;
1590 }")
1591
1592 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
1593 ;; a call to a routine which clobbers known registers.
1594
1595 (define_insn ""
1596   [(set (match_operand:SI 1 "register_operand" "=z")
1597         (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1598    (clobber (reg:SI MACL_REG))
1599    (clobber (reg:SI T_REG))
1600    (clobber (reg:SI PR_REG))
1601    (clobber (reg:SI R3_REG))
1602    (clobber (reg:SI R2_REG))
1603    (clobber (reg:SI R1_REG))
1604    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
1605   "TARGET_SH1"
1606   "jsr  @%0%#"
1607   [(set_attr "type" "sfunc")
1608    (set_attr "needs_delay_slot" "yes")])
1609
1610 (define_expand "mulsi3_call"
1611   [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1612    (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1613    (parallel[(set (match_operand:SI 0 "register_operand" "")
1614                   (mult:SI (reg:SI R4_REG)
1615                            (reg:SI R5_REG)))
1616              (clobber (reg:SI MACL_REG))
1617              (clobber (reg:SI T_REG))
1618              (clobber (reg:SI PR_REG))
1619              (clobber (reg:SI R3_REG))
1620              (clobber (reg:SI R2_REG))
1621              (clobber (reg:SI R1_REG))
1622              (use (match_operand:SI 3 "register_operand" ""))])]
1623   "TARGET_SH1"
1624   "")
1625
1626 (define_insn "mul_l"
1627   [(set (reg:SI MACL_REG)
1628         (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
1629                  (match_operand:SI 1 "arith_reg_operand" "r")))]
1630   "TARGET_SH2"
1631   "mul.l        %1,%0"
1632   [(set_attr "type" "dmpy")])
1633
1634 (define_expand "mulsi3"
1635   [(set (reg:SI MACL_REG)
1636         (mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
1637                   (match_operand:SI 2 "arith_reg_operand" "")))
1638    (set (match_operand:SI 0 "arith_reg_operand" "")
1639         (reg:SI MACL_REG))]
1640   "TARGET_SH1"
1641   "
1642 {
1643   rtx first, last;
1644
1645   if (!TARGET_SH2)
1646     {
1647       /* The address must be set outside the libcall,
1648          since it goes into a pseudo.  */
1649       rtx sym = gen_rtx_SYMBOL_REF (SImode, \"__mulsi3\");
1650       rtx addr = force_reg (SImode, sym);
1651       rtx insns = gen_mulsi3_call (operands[0], operands[1],
1652                                    operands[2], addr);
1653       first = XVECEXP (insns, 0, 0);
1654       last = XVECEXP (insns, 0, XVECLEN (insns, 0) - 1);
1655       emit_insn (insns);
1656     }
1657   else
1658     {
1659       rtx macl = gen_rtx_REG (SImode, MACL_REG);
1660
1661       first = emit_insn (gen_mul_l (operands[1], operands[2]));
1662       /* consec_sets_giv can only recognize the first insn that sets a
1663          giv as the giv insn.  So we must tag this also with a REG_EQUAL
1664          note.  */
1665       last = emit_insn (gen_movsi_i ((operands[0]), macl));
1666     }
1667   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1668      invariant code motion can move it.  */
1669   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1670   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1671   DONE;
1672 }")
1673
1674 (define_insn "mulsidi3_i"
1675   [(set (reg:SI MACH_REG)
1676         (truncate:SI
1677          (lshiftrt:DI
1678           (mult:DI
1679            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1680            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1681           (const_int 32))))
1682    (set (reg:SI MACL_REG)
1683         (mult:SI (match_dup 0)
1684                  (match_dup 1)))]
1685   "TARGET_SH2"
1686   "dmuls.l      %1,%0"
1687   [(set_attr "type" "dmpy")])
1688
1689 (define_expand "mulsidi3"
1690   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1691         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1692                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1693   "TARGET_SH2 || TARGET_SHMEDIA"
1694   "
1695 {
1696   if (TARGET_SH2)
1697     {
1698        emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
1699                                         operands[2]));
1700        DONE;
1701     }
1702 }")
1703
1704 (define_insn "mulsidi3_media"
1705   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1706         (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "%r"))
1707                  (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1708   "TARGET_SHMEDIA"
1709   "muls.l       %1, %2, %0")
1710   
1711 (define_insn "mulsidi3_compact"
1712   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1713         (mult:DI
1714          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1715          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
1716    (clobber (reg:SI MACH_REG))
1717    (clobber (reg:SI MACL_REG))]
1718   "TARGET_SH2"
1719   "#")
1720
1721 (define_split
1722   [(set (match_operand:DI 0 "arith_reg_operand" "")
1723         (mult:DI
1724          (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1725          (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
1726    (clobber (reg:SI MACH_REG))
1727    (clobber (reg:SI MACL_REG))]
1728   "TARGET_SH2"
1729   [(const_int 0)]
1730   "
1731 {
1732   rtx low_dst = gen_lowpart (SImode, operands[0]);
1733   rtx high_dst = gen_highpart (SImode, operands[0]);
1734
1735   emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
1736
1737   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
1738   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
1739   /* We need something to tag the possible REG_EQUAL notes on to.  */
1740   emit_move_insn (operands[0], operands[0]);
1741   DONE;
1742 }")
1743
1744 (define_insn "umulsidi3_i"
1745   [(set (reg:SI MACH_REG)
1746         (truncate:SI
1747          (lshiftrt:DI
1748           (mult:DI
1749            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1750            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1751           (const_int 32))))
1752    (set (reg:SI MACL_REG)
1753         (mult:SI (match_dup 0)
1754                  (match_dup 1)))]
1755   "TARGET_SH2"
1756   "dmulu.l      %1,%0"
1757   [(set_attr "type" "dmpy")])
1758
1759 (define_expand "umulsidi3"
1760   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1761         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1762                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1763   "TARGET_SH2 || TARGET_SHMEDIA"
1764   "
1765 {
1766   if (TARGET_SH2)
1767     {
1768        emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
1769                                          operands[2]));
1770        DONE;
1771     }
1772 }")
1773
1774 (define_insn "umulsidi3_media"
1775   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1776         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "%r"))
1777                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
1778   "TARGET_SHMEDIA"
1779   "mulu.l       %1, %2, %0")
1780   
1781 (define_insn "umulsidi3_compact"
1782   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1783         (mult:DI
1784          (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
1785          (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
1786    (clobber (reg:SI MACH_REG))
1787    (clobber (reg:SI MACL_REG))]
1788   "TARGET_SH2"
1789   "#")
1790
1791 (define_split
1792   [(set (match_operand:DI 0 "arith_reg_operand" "")
1793         (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1794                  (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
1795    (clobber (reg:SI MACH_REG))
1796    (clobber (reg:SI MACL_REG))]
1797   "TARGET_SH2"
1798   [(const_int 0)]
1799   "
1800 {
1801   rtx low_dst = gen_lowpart (SImode, operands[0]);
1802   rtx high_dst = gen_highpart (SImode, operands[0]);
1803
1804   emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
1805
1806   emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
1807   emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
1808   /* We need something to tag the possible REG_EQUAL notes on to.  */
1809   emit_move_insn (operands[0], operands[0]);
1810   DONE;
1811 }")
1812
1813 (define_insn "smulsi3_highpart_i"
1814   [(set (reg:SI MACH_REG)
1815         (truncate:SI
1816          (lshiftrt:DI
1817           (mult:DI
1818            (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1819            (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1820           (const_int 32))))
1821    (clobber (reg:SI MACL_REG))]
1822   "TARGET_SH2"
1823   "dmuls.l      %1,%0"
1824   [(set_attr "type" "dmpy")])
1825
1826 (define_expand "smulsi3_highpart"
1827   [(parallel
1828     [(set (reg:SI MACH_REG)
1829           (truncate:SI
1830            (lshiftrt:DI
1831             (mult:DI
1832              (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1833              (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
1834             (const_int 32))))
1835     (clobber (reg:SI MACL_REG))])
1836    (set (match_operand:SI 0 "arith_reg_operand" "")
1837         (reg:SI MACH_REG))]
1838   "TARGET_SH2"
1839   "
1840 {
1841   rtx first, last;
1842
1843   first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
1844   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
1845   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1846      invariant code motion can move it.  */
1847   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1848   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1849   /* expand_binop can't find a suitable code in mul_highpart_optab to
1850      make a REG_EQUAL note from, so make one here.
1851      ??? Alternatively, we could put this at the calling site of expand_binop,
1852      i.e. expand_mult_highpart.  */
1853   REG_NOTES (last)
1854     = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
1855                          REG_NOTES (last));
1856   DONE;
1857 }")
1858
1859 (define_insn "umulsi3_highpart_i"
1860   [(set (reg:SI MACH_REG)
1861         (truncate:SI
1862          (lshiftrt:DI
1863           (mult:DI
1864            (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
1865            (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
1866           (const_int 32))))
1867    (clobber (reg:SI MACL_REG))]
1868   "TARGET_SH2"
1869   "dmulu.l      %1,%0"
1870   [(set_attr "type" "dmpy")])
1871
1872 (define_expand "umulsi3_highpart"
1873   [(parallel
1874     [(set (reg:SI MACH_REG)
1875           (truncate:SI
1876            (lshiftrt:DI
1877             (mult:DI
1878              (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
1879              (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
1880             (const_int 32))))
1881     (clobber (reg:SI MACL_REG))])
1882    (set (match_operand:SI 0 "arith_reg_operand" "")
1883         (reg:SI MACH_REG))]
1884   "TARGET_SH2"
1885   "
1886 {
1887   rtx first, last;
1888
1889   first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
1890   last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
1891   /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
1892      invariant code motion can move it.  */
1893   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
1894   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
1895   DONE;
1896 }")
1897 \f
1898 ;; -------------------------------------------------------------------------
1899 ;; Logical operations
1900 ;; -------------------------------------------------------------------------
1901
1902 (define_insn ""
1903   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
1904         (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1905                 (match_operand:SI 2 "logical_operand" "r,L")))]
1906   "TARGET_SH1"
1907   "and  %2,%0"
1908   [(set_attr "type" "arith")])
1909
1910 ;; If the constant is 255, then emit a extu.b instruction instead of an
1911 ;; and, since that will give better code.
1912
1913 (define_expand "andsi3"
1914   [(set (match_operand:SI 0 "arith_reg_operand" "")
1915         (and:SI (match_operand:SI 1 "arith_reg_operand" "")
1916                 (match_operand:SI 2 "logical_operand" "")))]
1917   "TARGET_SH1"
1918   "
1919 {
1920   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)
1921     {
1922       emit_insn (gen_zero_extendqisi2 (operands[0],
1923                                        gen_lowpart (QImode, operands[1])));
1924       DONE;
1925     }
1926 }")
1927
1928 (define_insn "anddi3"
1929   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
1930         (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1931                 (match_operand:DI 2 "logical_operand" "r,P")))]
1932   "TARGET_SHMEDIA"
1933   "@
1934         and     %1, %2, %0
1935         andi    %1, %2, %0")
1936
1937 (define_insn "*andcdi3"
1938   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
1939         (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
1940                 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
1941   "TARGET_SHMEDIA"
1942   "andc %1,%2,%0")
1943
1944 (define_insn "iorsi3"
1945   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
1946         (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1947                 (match_operand:SI 2 "logical_operand" "r,L")))]
1948   "TARGET_SH1"
1949   "or   %2,%0"
1950   [(set_attr "type" "arith")])
1951
1952 (define_insn "iordi3"
1953   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
1954         (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1955                 (match_operand:DI 2 "logical_operand" "r,P")))]
1956   "TARGET_SHMEDIA"
1957   "@
1958         or      %1, %2, %0
1959         ori     %1, %2, %0")
1960
1961 (define_insn "xorsi3"
1962   [(set (match_operand:SI 0 "arith_reg_operand" "=z,r")
1963         (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
1964                 (match_operand:SI 2 "logical_operand" "L,r")))]
1965   "TARGET_SH1"
1966   "xor  %2,%0"
1967   [(set_attr "type" "arith")])
1968
1969 (define_insn "xordi3"
1970   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
1971         (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1972                 (match_operand:DI 2 "shmedia_6bit_operand" "r,O")))]
1973   "TARGET_SHMEDIA"
1974   "@
1975         xor     %1, %2, %0
1976         xori    %1, %2, %0")
1977 \f
1978 ;; -------------------------------------------------------------------------
1979 ;; Shifts and rotates
1980 ;; -------------------------------------------------------------------------
1981
1982 (define_insn "rotlsi3_1"
1983   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1984         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
1985                    (const_int 1)))
1986    (set (reg:SI T_REG)
1987         (lshiftrt:SI (match_dup 1) (const_int 31)))]
1988   "TARGET_SH1"
1989   "rotl %0"
1990   [(set_attr "type" "arith")])
1991
1992 (define_insn "rotlsi3_31"
1993   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
1994         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
1995                    (const_int 31)))
1996    (clobber (reg:SI T_REG))]
1997   "TARGET_SH1"
1998   "rotr %0"
1999   [(set_attr "type" "arith")])
2000
2001 (define_insn "rotlsi3_16"
2002   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2003         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
2004                    (const_int 16)))]
2005   "TARGET_SH1"
2006   "swap.w       %1,%0"
2007   [(set_attr "type" "arith")])
2008
2009 (define_expand "rotlsi3"
2010   [(set (match_operand:SI 0 "arith_reg_operand" "")
2011         (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
2012                    (match_operand:SI 2 "immediate_operand" "")))]
2013   "TARGET_SH1"
2014   "
2015 {
2016   static const char rot_tab[] = {
2017     000, 000, 000, 000, 000, 000, 010, 001,
2018     001, 001, 011, 013, 003, 003, 003, 003,
2019     003, 003, 003, 003, 003, 013, 012, 002,
2020     002, 002, 010, 000, 000, 000, 000, 000,
2021   };
2022
2023   int count, choice;
2024
2025   if (GET_CODE (operands[2]) != CONST_INT)
2026     FAIL;
2027   count = INTVAL (operands[2]);
2028   choice = rot_tab[count];
2029   if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
2030     FAIL;
2031   choice &= 7;
2032   switch (choice)
2033     {
2034     case 0:
2035       emit_move_insn (operands[0], operands[1]);
2036       count -= (count & 16) * 2;
2037       break;
2038     case 3:
2039      emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
2040      count -= 16;
2041      break;
2042     case 1:
2043     case 2:
2044       {
2045         rtx parts[2];
2046         parts[0] = gen_reg_rtx (SImode);
2047         parts[1] = gen_reg_rtx (SImode);
2048         emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
2049         parts[choice-1] = operands[1];
2050         emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
2051         emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
2052         emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
2053         count = (count & ~16) - 8;
2054       }
2055     }
2056
2057   for (; count > 0; count--)
2058     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
2059   for (; count < 0; count++)
2060     emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
2061
2062   DONE;
2063 }")
2064
2065 (define_insn "*rotlhi3_8"
2066   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
2067         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
2068                    (const_int 8)))]
2069   "TARGET_SH1"
2070   "swap.b       %1,%0"
2071   [(set_attr "type" "arith")])
2072
2073 (define_expand "rotlhi3"
2074   [(set (match_operand:HI 0 "arith_reg_operand" "")
2075         (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
2076                    (match_operand:HI 2 "immediate_operand" "")))]
2077   "TARGET_SH1"
2078   "
2079 {
2080   if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
2081     FAIL;
2082 }")
2083
2084 ;;
2085 ;; shift left
2086
2087 ;; This pattern is used by init_expmed for computing the costs of shift
2088 ;; insns.
2089
2090 (define_insn_and_split "ashlsi3_std"
2091   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r,r,r")
2092         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
2093                    (match_operand:SI 2 "nonmemory_operand" "r,M,K,?ri")))
2094    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
2095   "TARGET_SH3
2096    || (TARGET_SH1 && GET_CODE (operands[2]) == CONST_INT
2097        && CONST_OK_FOR_K (INTVAL (operands[2])))"
2098   "@
2099    shld %2,%0
2100    add  %0,%0
2101    shll%O2      %0
2102    #"
2103   "TARGET_SH3
2104    && reload_completed
2105    && GET_CODE (operands[2]) == CONST_INT
2106    && ! CONST_OK_FOR_K (INTVAL (operands[2]))"
2107   [(set (match_dup 3) (match_dup 2))
2108    (parallel
2109     [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
2110      (clobber (match_dup 4))])]
2111   "operands[4] = gen_rtx_SCRATCH (SImode);"
2112   [(set_attr "length" "*,*,*,4")
2113    (set_attr "type" "dyn_shift,arith,arith,arith")])
2114
2115 (define_insn "ashlhi3_k"
2116   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
2117         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
2118                    (match_operand:HI 2 "const_int_operand" "M,K")))]
2119   "TARGET_SH1 && CONST_OK_FOR_K (INTVAL (operands[2]))"
2120   "@
2121         add     %0,%0
2122         shll%O2 %0"
2123   [(set_attr "type" "arith")])
2124
2125 (define_insn "ashlsi3_n"
2126   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2127         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
2128                    (match_operand:SI 2 "const_int_operand" "n")))
2129    (clobber (reg:SI T_REG))]
2130   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
2131   "#"
2132   [(set (attr "length")
2133         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2134                (const_string "2")
2135                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2136                (const_string "4")
2137                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
2138                (const_string "6")]
2139               (const_string "8")))
2140    (set_attr "type" "arith")])
2141
2142 (define_split
2143   [(set (match_operand:SI 0 "arith_reg_operand" "")
2144         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
2145                    (match_operand:SI 2 "const_int_operand" "n")))
2146    (clobber (reg:SI T_REG))]
2147   "TARGET_SH1 && reload_completed"
2148   [(use (reg:SI R0_REG))]
2149   "
2150 {
2151   gen_shifty_op (ASHIFT, operands);
2152   DONE;
2153 }")
2154
2155 (define_insn "ashlsi3_media"
2156   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2157         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r,r")
2158                    (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2159   "TARGET_SHMEDIA"
2160   "@
2161         shlld.l %1, %2, %0
2162         shlli.l %1, %2, %0")
2163
2164 (define_expand "ashlsi3"
2165   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2166                    (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
2167                               (match_operand:SI 2 "nonmemory_operand" "")))
2168               (clobber (reg:SI T_REG))])]
2169   ""
2170   "
2171 {
2172   if (TARGET_SHMEDIA)
2173     {
2174       emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
2175       DONE;
2176     }
2177   if (GET_CODE (operands[2]) == CONST_INT
2178       && sh_dynamicalize_shift_p (operands[2]))
2179     operands[2] = force_reg (SImode, operands[2]);
2180   if (TARGET_SH3)
2181     {
2182       emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
2183       DONE;
2184     }
2185   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
2186     FAIL;
2187 }")
2188
2189 (define_insn "ashlhi3"
2190   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
2191         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
2192                    (match_operand:HI 2 "const_int_operand" "n")))
2193    (clobber (reg:SI T_REG))]
2194   "TARGET_SH1"
2195   "#"
2196   [(set (attr "length")
2197         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2198                (const_string "2")
2199                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2200                (const_string "4")]
2201               (const_string "6")))
2202    (set_attr "type" "arith")])
2203
2204 (define_split
2205   [(set (match_operand:HI 0 "arith_reg_operand" "")
2206         (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
2207                    (match_operand:HI 2 "const_int_operand" "n")))
2208    (clobber (reg:SI T_REG))]
2209   "TARGET_SH1 && reload_completed"
2210   [(use (reg:SI R0_REG))]
2211   "
2212 {
2213   gen_shifty_hi_op (ASHIFT, operands);
2214   DONE;
2215 }")
2216
2217 ;
2218 ; arithmetic shift right
2219 ;
2220
2221 (define_insn "ashrsi3_k"
2222   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2223         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2224                      (match_operand:SI 2 "const_int_operand" "M")))
2225    (clobber (reg:SI T_REG))]
2226   "TARGET_SH1 && INTVAL (operands[2]) == 1"
2227   "shar %0"
2228   [(set_attr "type" "arith")])
2229
2230 ;; We can't do HImode right shifts correctly unless we start out with an
2231 ;; explicit zero / sign extension; doing that would result in worse overall
2232 ;; code, so just let the machine independent code widen the mode.
2233 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
2234
2235
2236 ;; ??? This should be a define expand.
2237
2238 (define_insn "ashrsi2_16"
2239   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2240         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
2241                      (const_int 16)))]
2242   "TARGET_SH1"
2243   "#"
2244   [(set_attr "length" "4")])
2245
2246 (define_split
2247   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2248         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
2249                      (const_int 16)))]
2250   "TARGET_SH1"
2251   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
2252    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2253   "operands[2] = gen_lowpart (HImode, operands[0]);")
2254
2255 ;; ??? This should be a define expand.
2256
2257 (define_insn "ashrsi2_31"
2258   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2259         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2260                      (const_int 31)))
2261    (clobber (reg:SI T_REG))]
2262   "TARGET_SH1"
2263   "#"
2264   [(set_attr "length" "4")])
2265
2266 (define_split
2267   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2268         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2269                      (const_int 31)))
2270    (clobber (reg:SI T_REG))]
2271   "TARGET_SH1"
2272   [(const_int 0)]
2273   "
2274 {
2275   emit_insn (gen_ashlsi_c (operands[0], operands[1]));
2276   emit_insn (gen_subc1 (operands[0], operands[0], operands[0]));
2277   DONE;
2278 }")
2279
2280 (define_insn "ashlsi_c"
2281   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2282         (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
2283    (set (reg:SI T_REG)
2284         (lt:SI (match_dup 1) (const_int 0)))]
2285   "TARGET_SH1"
2286   "shll %0"
2287   [(set_attr "type" "arith")])
2288
2289 (define_insn "ashrsi3_d"
2290   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2291         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2292                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2293   "TARGET_SH3"
2294   "shad %2,%0"
2295   [(set_attr "type" "dyn_shift")])
2296
2297 (define_insn "ashrsi3_n"
2298   [(set (reg:SI R4_REG)
2299         (ashiftrt:SI (reg:SI R4_REG)
2300                      (match_operand:SI 0 "const_int_operand" "i")))
2301    (clobber (reg:SI T_REG))
2302    (clobber (reg:SI PR_REG))
2303    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2304   "TARGET_SH1"
2305   "jsr  @%1%#"
2306   [(set_attr "type" "sfunc")
2307    (set_attr "needs_delay_slot" "yes")])
2308
2309 (define_insn "ashrsi3_media"
2310   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2311         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r,r")
2312                      (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2313   "TARGET_SHMEDIA"
2314   "@
2315         shard.l %1, %2, %0
2316         shari.l %1, %2, %0")
2317
2318 (define_expand "ashrsi3"
2319   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2320                    (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2321                                 (match_operand:SI 2 "nonmemory_operand" "")))
2322               (clobber (reg:SI T_REG))])]
2323   ""
2324   "
2325 {
2326   if (TARGET_SHMEDIA)
2327     {
2328       emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
2329       DONE;
2330     }
2331   if (expand_ashiftrt (operands))
2332     DONE;
2333   else
2334     FAIL;
2335 }")
2336
2337 ;; logical shift right
2338
2339 (define_insn "lshrsi3_d"
2340   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2341         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2342                      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2343   "TARGET_SH3"
2344   "shld %2,%0"
2345   [(set_attr "type" "dyn_shift")])
2346
2347 ;;  Only the single bit shift clobbers the T bit.
2348
2349 (define_insn "lshrsi3_m"
2350   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2351         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2352                      (match_operand:SI 2 "const_int_operand" "M")))
2353    (clobber (reg:SI T_REG))]
2354   "TARGET_SH1 && CONST_OK_FOR_M (INTVAL (operands[2]))"
2355   "shlr %0"
2356   [(set_attr "type" "arith")])
2357
2358 (define_insn "lshrsi3_k"
2359   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2360         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2361                      (match_operand:SI 2 "const_int_operand" "K")))]
2362   "TARGET_SH1 && CONST_OK_FOR_K (INTVAL (operands[2]))
2363    && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
2364   "shlr%O2      %0"
2365   [(set_attr "type" "arith")])
2366
2367 (define_insn "lshrsi3_n"
2368   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2369         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2370                      (match_operand:SI 2 "const_int_operand" "n")))
2371    (clobber (reg:SI T_REG))]
2372   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
2373   "#"
2374   [(set (attr "length")
2375         (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
2376                (const_string "2")
2377                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
2378                (const_string "4")
2379                (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
2380                (const_string "6")]
2381               (const_string "8")))
2382    (set_attr "type" "arith")])
2383
2384 (define_split
2385   [(set (match_operand:SI 0 "arith_reg_operand" "")
2386         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2387                      (match_operand:SI 2 "const_int_operand" "n")))
2388    (clobber (reg:SI T_REG))]
2389   "TARGET_SH1 && reload_completed"
2390   [(use (reg:SI R0_REG))]
2391   "
2392 {
2393   gen_shifty_op (LSHIFTRT, operands);
2394   DONE;
2395 }")
2396
2397 (define_insn "lshrsi3_media"
2398   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2399         (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r,r")
2400                      (match_operand:SI 2 "nonmemory_operand" "r,n")))]
2401   "TARGET_SHMEDIA"
2402   "@
2403         shlrd.l %1, %2, %0
2404         shlri.l %1, %2, %0")
2405
2406 (define_expand "lshrsi3"
2407   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
2408                    (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
2409                                 (match_operand:SI 2 "nonmemory_operand" "")))
2410               (clobber (reg:SI T_REG))])]
2411   ""
2412   "
2413 {
2414   if (TARGET_SHMEDIA)
2415     {
2416       emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
2417       DONE;
2418     }
2419   if (GET_CODE (operands[2]) == CONST_INT
2420       && sh_dynamicalize_shift_p (operands[2]))
2421     operands[2] = force_reg (SImode, operands[2]);
2422   if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
2423     {
2424       rtx count = copy_to_mode_reg (SImode, operands[2]);
2425       emit_insn (gen_negsi2 (count, count));
2426       emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
2427       DONE;
2428     }
2429   if (! immediate_operand (operands[2], GET_MODE (operands[2])))
2430     FAIL;
2431 }")
2432
2433 ;; ??? This should be a define expand.
2434
2435 (define_insn "ashldi3_k"
2436   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2437         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
2438                    (const_int 1)))
2439    (clobber (reg:SI T_REG))]
2440   "TARGET_SH1"
2441   "shll %R0\;rotcl      %S0"
2442   [(set_attr "length" "4")
2443    (set_attr "type" "arith")])
2444
2445 (define_insn "ashldi3_media"
2446   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2447         (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2448                    (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2449   "TARGET_SHMEDIA"
2450   "@
2451         shlld   %1, %2, %0
2452         shlli   %1, %2, %0")
2453
2454 (define_expand "ashldi3"
2455   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2456                    (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
2457                               (match_operand:DI 2 "immediate_operand" "")))
2458               (clobber (reg:SI T_REG))])]
2459   ""
2460   "
2461 {
2462   if (TARGET_SHMEDIA)
2463     {
2464       emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
2465       DONE;
2466     }
2467   if (GET_CODE (operands[2]) != CONST_INT
2468       || INTVAL (operands[2]) != 1)
2469     FAIL;
2470 }")
2471
2472 ;; ??? This should be a define expand.
2473
2474 (define_insn "lshrdi3_k"
2475   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2476         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
2477                      (const_int 1)))
2478    (clobber (reg:SI T_REG))]
2479   "TARGET_SH1"
2480   "shlr %S0\;rotcr      %R0"
2481   [(set_attr "length" "4")
2482    (set_attr "type" "arith")])
2483
2484 (define_insn "lshrdi3_media"
2485   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2486         (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2487                      (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2488   "TARGET_SHMEDIA"
2489   "@
2490         shlrd   %1, %2, %0
2491         shlri   %1, %2, %0")
2492
2493 (define_expand "lshrdi3"
2494   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2495                    (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
2496                                (match_operand:DI 2 "immediate_operand" "")))
2497              (clobber (reg:SI T_REG))])]
2498   ""
2499   "
2500 {
2501   if (TARGET_SHMEDIA)
2502     {
2503       emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
2504       DONE;
2505     }
2506   if (GET_CODE (operands[2]) != CONST_INT
2507       || INTVAL (operands[2]) != 1)
2508     FAIL;
2509 }")
2510
2511 ;; ??? This should be a define expand.
2512
2513 (define_insn "ashrdi3_k"
2514   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2515         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
2516                      (const_int 1)))
2517    (clobber (reg:SI T_REG))]
2518   "TARGET_SH1"
2519   "shar %S0\;rotcr      %R0"
2520   [(set_attr "length" "4")
2521    (set_attr "type" "arith")])
2522
2523 (define_insn "ashrdi3_media"
2524   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
2525         (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
2526                      (match_operand:DI 2 "nonmemory_operand" "r,n")))]
2527   "TARGET_SHMEDIA"
2528   "@
2529         shard   %1, %2, %0
2530         shari   %1, %2, %0")
2531
2532 (define_expand "ashrdi3"
2533   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
2534                    (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
2535                                 (match_operand:DI 2 "immediate_operand" "")))
2536               (clobber (reg:SI T_REG))])]
2537   ""
2538   "
2539 {
2540   if (TARGET_SHMEDIA)
2541     {
2542       emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
2543       DONE;
2544     }
2545   if (GET_CODE (operands[2]) != CONST_INT
2546       || INTVAL (operands[2]) != 1)
2547     FAIL;
2548 }")
2549
2550 ;; combined left/right shift
2551
2552 (define_split
2553   [(set (match_operand:SI 0 "register_operand" "")
2554         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
2555                            (match_operand:SI 2 "const_int_operand" "n"))
2556                 (match_operand:SI 3 "const_int_operand" "n")))]
2557   "TARGET_SH1 && (unsigned)INTVAL (operands[2]) < 32"
2558   [(use (reg:SI R0_REG))]
2559   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
2560    DONE;")
2561
2562 (define_split
2563   [(set (match_operand:SI 0 "register_operand" "")
2564         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
2565                            (match_operand:SI 2 "const_int_operand" "n"))
2566                 (match_operand:SI 3 "const_int_operand" "n")))
2567    (clobber (reg:SI T_REG))]
2568   "TARGET_SH1 && (unsigned)INTVAL (operands[2]) < 32"
2569   [(use (reg:SI R0_REG))]
2570   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
2571    DONE;")
2572
2573 (define_insn ""
2574   [(set (match_operand:SI 0 "register_operand" "=r")
2575         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2576                            (match_operand:SI 2 "const_int_operand" "n"))
2577                 (match_operand:SI 3 "const_int_operand" "n")))
2578    (clobber (reg:SI T_REG))]
2579   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
2580  "#"
2581   [(set (attr "length")
2582         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
2583                (const_string "4")
2584                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
2585                (const_string "6")
2586                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
2587                (const_string "8")
2588                (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
2589                (const_string "10")
2590                (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
2591                (const_string "12")
2592                (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
2593                (const_string "14")
2594                (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
2595                (const_string "16")]
2596               (const_string "18")))
2597    (set_attr "type" "arith")])
2598
2599 (define_insn ""
2600   [(set (match_operand:SI 0 "register_operand" "=z")
2601         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
2602                            (match_operand:SI 2 "const_int_operand" "n"))
2603                 (match_operand:SI 3 "const_int_operand" "n")))
2604    (clobber (reg:SI T_REG))]
2605   "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
2606  "#"
2607   [(set (attr "length")
2608         (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
2609                (const_string "4")
2610                (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
2611                (const_string "6")
2612                (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
2613                (const_string "8")]
2614               (const_string "10")))
2615    (set_attr "type" "arith")])
2616
2617 ;; shift left / and combination with a scratch register: The combine pass
2618 ;; does not accept the individual instructions, even though they are
2619 ;; cheap.  But it needs a precise description so that it is usable after
2620 ;; reload.
2621 (define_insn "and_shl_scratch"
2622   [(set (match_operand:SI 0 "register_operand" "=r,&r")
2623         (lshiftrt:SI
2624          (ashift:SI
2625           (and:SI
2626            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
2627                         (match_operand:SI 2 "const_int_operand" "N,n"))
2628            (match_operand:SI 3 "" "0,r"))
2629           (match_operand:SI 4 "const_int_operand" "n,n"))
2630          (match_operand:SI 5 "const_int_operand" "n,n")))
2631    (clobber (reg:SI T_REG))]
2632   "TARGET_SH1"
2633   "#"
2634   [(set (attr "length")
2635         (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
2636                (const_string "4")
2637                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
2638                (const_string "6")
2639                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
2640                (const_string "8")
2641                (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
2642                (const_string "10")]
2643               (const_string "12")))
2644    (set_attr "type" "arith")])
2645
2646 (define_split
2647   [(set (match_operand:SI 0 "register_operand" "=r,&r")
2648         (lshiftrt:SI
2649          (ashift:SI
2650           (and:SI
2651            (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
2652                         (match_operand:SI 2 "const_int_operand" "N,n"))
2653            (match_operand:SI 3 "register_operand" "0,r"))
2654           (match_operand:SI 4 "const_int_operand" "n,n"))
2655          (match_operand:SI 5 "const_int_operand" "n,n")))
2656    (clobber (reg:SI T_REG))]
2657   "TARGET_SH1"
2658   [(use (reg:SI R0_REG))]
2659   "
2660 {
2661   rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
2662
2663   if (INTVAL (operands[2]))
2664     {
2665       gen_shifty_op (LSHIFTRT, operands);
2666     }
2667   emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
2668   operands[2] = operands[4];
2669   gen_shifty_op (ASHIFT, operands);
2670   if (INTVAL (operands[5]))
2671     {
2672       operands[2] = operands[5];
2673       gen_shifty_op (LSHIFTRT, operands);
2674     }
2675   DONE;
2676 }")
2677
2678 ;; signed left/right shift combination.
2679 (define_split
2680   [(set (match_operand:SI 0 "register_operand" "=r")
2681         (sign_extract:SI
2682          (ashift:SI (match_operand:SI 1 "register_operand" "r")
2683                     (match_operand:SI 2 "const_int_operand" "n"))
2684          (match_operand:SI 3 "const_int_operand" "n")
2685          (const_int 0)))
2686    (clobber (reg:SI T_REG))]
2687   "TARGET_SH1"
2688   [(use (reg:SI R0_REG))]
2689   "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
2690    DONE;")
2691
2692 (define_insn "shl_sext_ext"
2693   [(set (match_operand:SI 0 "register_operand" "=r")
2694         (sign_extract:SI
2695          (ashift:SI (match_operand:SI 1 "register_operand" "0")
2696                     (match_operand:SI 2 "const_int_operand" "n"))
2697          (match_operand:SI 3 "const_int_operand" "n")
2698          (const_int 0)))
2699    (clobber (reg:SI T_REG))]
2700   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
2701   "#"
2702   [(set (attr "length")
2703         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
2704                (const_string "2")
2705                (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
2706                (const_string "4")
2707                (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
2708                (const_string "6")
2709                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
2710                (const_string "8")
2711                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
2712                (const_string "10")
2713                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
2714                (const_string "12")
2715                (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
2716                (const_string "14")
2717                (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
2718                (const_string "16")]
2719               (const_string "18")))
2720     (set_attr "type" "arith")])
2721
2722 (define_insn "shl_sext_sub"
2723   [(set (match_operand:SI 0 "register_operand" "=z")
2724         (sign_extract:SI
2725          (ashift:SI (match_operand:SI 1 "register_operand" "0")
2726                     (match_operand:SI 2 "const_int_operand" "n"))
2727          (match_operand:SI 3 "const_int_operand" "n")
2728          (const_int 0)))
2729    (clobber (reg:SI T_REG))]
2730   "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
2731   "#"
2732   [(set (attr "length")
2733         (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
2734                (const_string "6")
2735                (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
2736                (const_string "8")
2737                (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
2738                (const_string "10")
2739                (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
2740                (const_string "12")]
2741               (const_string "14")))
2742     (set_attr "type" "arith")])
2743
2744 ;; These patterns are found in expansions of DImode shifts by 16, and
2745 ;; allow the xtrct instruction to be generated from C source.
2746
2747 (define_insn "xtrct_left"
2748   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2749         (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
2750                            (const_int 16))
2751                 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
2752                              (const_int 16))))]
2753   "TARGET_SH1"
2754   "xtrct        %1,%0"
2755   [(set_attr "type" "arith")])
2756
2757 (define_insn "xtrct_right"
2758   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2759         (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
2760                              (const_int 16))
2761                 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
2762                            (const_int 16))))]
2763   "TARGET_SH1"
2764   "xtrct        %2,%0"
2765   [(set_attr "type" "arith")])
2766 \f
2767 ;; -------------------------------------------------------------------------
2768 ;; Unary arithmetic
2769 ;; -------------------------------------------------------------------------
2770
2771 (define_insn "negc"
2772   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2773         (neg:SI (plus:SI (reg:SI T_REG)
2774                          (match_operand:SI 1 "arith_reg_operand" "r"))))
2775    (set (reg:SI T_REG)
2776         (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
2777                (const_int 0)))]
2778   "TARGET_SH1"
2779   "negc %1,%0"
2780   [(set_attr "type" "arith")])
2781
2782 (define_insn "*negdi_media"
2783   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2784         (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
2785   "TARGET_SHMEDIA"
2786   "sub  r63, %1, %0")
2787
2788 (define_expand "negdi2"
2789   [(set (match_operand:DI 0 "arith_reg_operand" "")
2790         (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
2791    (clobber (reg:SI T_REG))]
2792   ""
2793   "
2794 {
2795   if (TARGET_SH1)
2796     {
2797       int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
2798       int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
2799
2800       rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
2801       rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
2802
2803       rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
2804       rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
2805
2806       emit_insn (gen_clrt ());
2807       emit_insn (gen_negc (low_dst, low_src));
2808       emit_insn (gen_negc (high_dst, high_src));
2809       DONE;
2810     }
2811 }")
2812
2813 (define_insn "negsi2"
2814   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2815         (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
2816   "TARGET_SH1"
2817   "neg  %1,%0"
2818   [(set_attr "type" "arith")])
2819
2820 (define_insn "one_cmplsi2"
2821   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2822         (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
2823   "TARGET_SH1"
2824   "not  %1,%0"
2825   [(set_attr "type" "arith")])
2826
2827 (define_expand "one_cmpldi2"
2828   [(set (match_operand:DI 0 "arith_reg_operand" "")
2829         (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
2830                 (const_int -1)))]
2831   "TARGET_SHMEDIA" "")
2832 \f
2833 ;; -------------------------------------------------------------------------
2834 ;; Zero extension instructions
2835 ;; -------------------------------------------------------------------------
2836
2837 (define_insn "zero_extendsidi2"
2838   [(set (match_operand:DI 0 "register_operand" "=r")
2839         (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
2840   "TARGET_SHMEDIA"
2841   "addz.l       %1, r63, %0")
2842
2843 (define_insn "zero_extendhidi2"
2844   [(set (match_operand:DI 0 "register_operand" "=r,r")
2845         (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
2846   "TARGET_SHMEDIA"
2847   "@
2848         #
2849         ld%M1.uw        %m1, %0")
2850
2851 (define_split
2852   [(set (match_operand:DI 0 "register_operand" "=r")
2853         (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))]
2854   "TARGET_SHMEDIA && reload_completed"
2855   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
2856    (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))])
2857
2858 (define_insn "zero_extendqidi2"
2859   [(set (match_operand:DI 0 "register_operand" "=r,r")
2860         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2861   "TARGET_SHMEDIA"
2862   "@
2863         andi    %1, 255, %0
2864         ld%M1.ub        %m1, %0")
2865
2866 (define_insn "zero_extendhisi2"
2867   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2868         (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
2869   "TARGET_SH1"
2870   "extu.w       %1,%0"
2871   [(set_attr "type" "arith")])
2872
2873 (define_insn "zero_extendqisi2"
2874   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
2875         (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
2876   "TARGET_SH1"
2877   "extu.b       %1,%0"
2878   [(set_attr "type" "arith")])
2879
2880 (define_insn "zero_extendqihi2"
2881   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
2882         (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
2883   "TARGET_SH1"
2884   "extu.b       %1,%0"
2885   [(set_attr "type" "arith")])
2886 \f
2887 ;; -------------------------------------------------------------------------
2888 ;; Sign extension instructions
2889 ;; -------------------------------------------------------------------------
2890
2891 ;; ??? This should be a define expand.
2892 ;; ??? Or perhaps it should be dropped?
2893
2894 ;; convert_move generates good code for SH[1-4].
2895 (define_insn "extendsidi2"
2896   [(set (match_operand:DI 0 "register_operand" "=r,r")
2897         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
2898   "TARGET_SHMEDIA"
2899   "@
2900         add.l   %1, r63, %0
2901         ld%M1.l %m1, %0")
2902
2903 (define_insn "extendhidi2"
2904   [(set (match_operand:DI 0 "register_operand" "=r,r")
2905         (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
2906   "TARGET_SHMEDIA"
2907   "@
2908         #
2909         ld%M1.w %m1, %0")
2910
2911 (define_split
2912   [(set (match_operand:DI 0 "register_operand" "=r")
2913         (sign_extend:DI (match_operand:HI 1 "register_operand" "r")))]
2914   "TARGET_SHMEDIA && reload_completed"
2915   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
2916    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))])
2917
2918 (define_insn "extendqidi2"
2919   [(set (match_operand:DI 0 "register_operand" "=r,r")
2920         (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2921   "TARGET_SHMEDIA"
2922   "@
2923         #
2924         ld%M1.b %m1, %0")
2925
2926 (define_split
2927   [(set (match_operand:DI 0 "register_operand" "=r")
2928         (sign_extend:DI (match_operand:QI 1 "register_operand" "r")))]
2929   "TARGET_SHMEDIA && reload_completed"
2930   [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
2931    (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))])
2932
2933 (define_insn "extendhisi2"
2934   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2935         (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
2936   "TARGET_SH1"
2937   "@
2938         exts.w  %1,%0
2939         mov.w   %1,%0"
2940   [(set_attr "type" "arith,load")])
2941
2942 (define_insn "extendqisi2"
2943   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
2944         (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
2945   "TARGET_SH1"
2946   "@
2947         exts.b  %1,%0
2948         mov.b   %1,%0"
2949   [(set_attr "type" "arith,load")])
2950
2951 (define_insn "extendqihi2"
2952   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
2953         (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
2954   "TARGET_SH1"
2955   "@
2956         exts.b  %1,%0
2957         mov.b   %1,%0"
2958   [(set_attr "type" "arith,load")])
2959 \f
2960 ;; -------------------------------------------------------------------------
2961 ;; Move instructions
2962 ;; -------------------------------------------------------------------------
2963
2964 ;; define push and pop so it is easy for sh.c
2965 ;; We can't use push and pop on SHcompact because the stack must always
2966 ;; be 8-byte aligned.
2967
2968 (define_expand "push"
2969   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
2970         (match_operand:SI 0 "register_operand" "r,l,x"))]
2971   "TARGET_SH1 && ! TARGET_SH5"
2972   "")
2973
2974 (define_expand "pop"
2975   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
2976         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
2977   "TARGET_SH1 && ! TARGET_SH5"
2978   "")
2979
2980 (define_expand "push_e"
2981   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
2982                    (match_operand:SF 0 "" ""))
2983               (use (reg:PSI FPSCR_REG))
2984               (clobber (scratch:SI))])]
2985   "TARGET_SH1 && ! TARGET_SH5"
2986   "")
2987
2988 (define_insn "push_fpul"
2989   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
2990   "TARGET_SH3E && ! TARGET_SH5"
2991   "sts.l        fpul,@-r15"
2992   [(set_attr "type" "store")
2993    (set_attr "hit_stack" "yes")])
2994
2995 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
2996 ;; so use that.
2997 (define_expand "push_4"
2998   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
2999                    (match_operand:DF 0 "" ""))
3000               (use (reg:PSI FPSCR_REG))
3001               (clobber (scratch:SI))])]
3002   "TARGET_SH1 && ! TARGET_SH5"
3003   "")
3004
3005 (define_expand "pop_e"
3006   [(parallel [(set (match_operand:SF 0 "" "")
3007               (mem:SF (post_inc:SI (reg:SI SP_REG))))
3008               (use (reg:PSI FPSCR_REG))
3009               (clobber (scratch:SI))])]
3010   "TARGET_SH1 && ! TARGET_SH5"
3011   "")
3012
3013 (define_insn "pop_fpul"
3014   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
3015   "TARGET_SH3E && ! TARGET_SH5"
3016   "lds.l        @r15+,fpul"
3017   [(set_attr "type" "load")
3018    (set_attr "hit_stack" "yes")])
3019
3020 (define_expand "pop_4"
3021   [(parallel [(set (match_operand:DF 0 "" "")
3022                    (mem:DF (post_inc:SI (reg:SI SP_REG))))
3023               (use (reg:PSI FPSCR_REG))
3024               (clobber (scratch:SI))])]
3025   "TARGET_SH1 && ! TARGET_SH5"
3026   "")
3027
3028 ;; These two patterns can happen as the result of optimization, when
3029 ;; comparisons get simplified to a move of zero or 1 into the T reg.
3030 ;; They don't disappear completely, because the T reg is a fixed hard reg.
3031
3032 (define_insn "clrt"
3033   [(set (reg:SI T_REG) (const_int 0))]
3034   "TARGET_SH1"
3035   "clrt")
3036
3037 (define_insn "sett"
3038   [(set (reg:SI T_REG) (const_int 1))]
3039   "TARGET_SH1"
3040   "sett")
3041
3042 ;; t/r must come after r/r, lest reload will try to reload stuff like
3043 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
3044 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
3045 (define_insn "movsi_i"
3046   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
3047         (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
3048   "TARGET_SH1
3049    && ! TARGET_SH3E
3050    && (register_operand (operands[0], SImode)
3051        || register_operand (operands[1], SImode))"
3052   "@
3053         mov.l   %1,%0
3054         mov     %1,%0
3055         cmp/pl  %1
3056         mov.l   %1,%0
3057         sts     %1,%0
3058         sts     %1,%0
3059         movt    %0
3060         mov.l   %1,%0
3061         sts.l   %1,%0
3062         sts.l   %1,%0
3063         lds     %1,%0
3064         lds     %1,%0
3065         lds.l   %1,%0
3066         lds.l   %1,%0
3067         fake    %1,%0"
3068   [(set_attr "type" "pcload_si,move,*,load_si,move,prget,move,store,store,pstore,move,prset,load,pload,pcload_si")
3069    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
3070
3071 ;; t/r must come after r/r, lest reload will try to reload stuff like
3072 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
3073 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
3074 ;; will require a reload.
3075 (define_insn "movsi_ie"
3076   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,y")
3077         (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y"))]
3078   "TARGET_SH3E
3079    && (register_operand (operands[0], SImode)
3080        || register_operand (operands[1], SImode))"
3081   "@
3082         mov.l   %1,%0
3083         mov     %1,%0
3084         cmp/pl  %1
3085         mov.l   %1,%0
3086         sts     %1,%0
3087         sts     %1,%0
3088         movt    %0
3089         mov.l   %1,%0
3090         sts.l   %1,%0
3091         sts.l   %1,%0
3092         lds     %1,%0
3093         lds     %1,%0
3094         lds.l   %1,%0
3095         lds.l   %1,%0
3096         lds.l   %1,%0
3097         sts.l   %1,%0
3098         fake    %1,%0
3099         lds     %1,%0
3100         sts     %1,%0
3101         ! move optimized away"
3102   [(set_attr "type" "pcload_si,move,*,load_si,move,prget,move,store,store,pstore,move,prset,load,pload,load,store,pcload_si,gp_fpul,gp_fpul,nil")
3103    (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
3104
3105 (define_insn "movsi_i_lowpart"
3106   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
3107         (match_operand:SI 1 "general_movsrc_operand" "Q,rI,mr,x,l,t,r,i"))]
3108    "TARGET_SH1
3109     && (register_operand (operands[0], SImode)
3110         || register_operand (operands[1], SImode))"
3111   "@
3112         mov.l   %1,%0
3113         mov     %1,%0
3114         mov.l   %1,%0
3115         sts     %1,%0
3116         sts     %1,%0
3117         movt    %0
3118         mov.l   %1,%0
3119         fake    %1,%0"
3120   [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
3121
3122 (define_insn "*movsi_media"
3123   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,m,f,m,f,r,f,*b*k,r,b*k")
3124         (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,m,f,r,f,f,r,*b*k,T"))]
3125   "TARGET_SHMEDIA_FPU
3126    && (register_operand (operands[0], SImode)
3127        || register_operand (operands[1], SImode))"
3128   "@
3129         add.l   %1, r63, %0
3130         movi    %1, %0
3131         #
3132         ld%M1.l %m1, %0
3133         st%M0.l %m0, %1
3134         fld%M1.s        %m1, %0
3135         fst%M0.s        %m0, %1
3136         fmov.ls %1, %0
3137         fmov.sl %1, %0
3138         fmov.s  %1, %0
3139         ptabs   %1, %0
3140         gettr   %1, %0
3141         pt      %1, %0"
3142   [(set_attr "type"   "move,move,*,load,store,load,store,move,move,move,ptabs,move,pt")
3143    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")])
3144
3145 (define_insn "*movsi_media_nofpu"
3146   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,m,*b*k,r,b*k")
3147         (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,r,*b*k,T"))]
3148   "TARGET_SHMEDIA
3149    && (register_operand (operands[0], SImode)
3150        || register_operand (operands[1], SImode))"
3151   "@
3152         add.l   %1, r63, %0
3153         movi    %1, %0
3154         #
3155         ld%M1.l %m1, %0
3156         st%M0.l %m0, %1
3157         ptabs   %1, %0
3158         gettr   %1, %0
3159         pt      %1, %0"
3160   [(set_attr "type"   "move,move,*,load,store,ptabs,move,pt")
3161    (set_attr "length" "4,4,8,4,4,4,4,12")])
3162
3163 (define_split
3164   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
3165         (match_operand:SI 1 "immediate_operand" "s"))]
3166   "TARGET_SHMEDIA && reload_completed
3167    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3168   [(set (subreg:DI (match_dup 0) 0) (match_dup 2))]
3169   "
3170 {
3171   operands[2] = shallow_copy_rtx (operands[1]);
3172   PUT_MODE (operands[2], DImode);
3173 }")
3174
3175 (define_split
3176   [(set (match_operand:SI 0 "register_operand" "=r")
3177         (match_operand:SI 1 "immediate_operand" "n"))]
3178   "TARGET_SHMEDIA
3179    && ((GET_CODE (operands[1]) == CONST_INT
3180         && ! CONST_OK_FOR_J (INTVAL (operands[1])))
3181        || GET_CODE (operands[1]) == CONST_DOUBLE)"
3182   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3183
3184 (define_expand "movsi"
3185   [(set (match_operand:SI 0 "general_movdst_operand" "")
3186         (match_operand:SI 1 "general_movsrc_operand" ""))]
3187   ""
3188   "{ if (prepare_move_operands (operands, SImode)) DONE; }")
3189
3190 (define_expand "ic_invalidate_line"
3191   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
3192                                 (match_dup 1)] UNSPEC_ICACHE)
3193               (clobber (scratch:SI))])]
3194   "TARGET_HARD_SH4 || TARGET_SH5"
3195   "
3196 {
3197   if (TARGET_SHMEDIA)
3198     {
3199       emit_insn (gen_ic_invalidate_line_media (operands[0]));
3200       DONE;
3201     }
3202   else if (TARGET_SHCOMPACT)
3203     {
3204       operands[1] = gen_rtx_SYMBOL_REF (Pmode, \"__ic_invalidate\");
3205       operands[1] = force_reg (Pmode, operands[1]);
3206       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
3207       DONE;
3208     }
3209   operands[0] = force_reg (Pmode, operands[0]);
3210   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
3211                                                                Pmode)));
3212 }")
3213
3214 ;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
3215 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
3216 ;; the requirement *1*00 for associative address writes.  The alignment of
3217 ;; %0 implies that its least significant bit is cleared,
3218 ;; thus we clear the V bit of a matching entry if there is one.
3219 (define_insn "ic_invalidate_line_i"
3220   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
3221                      (match_operand:SI 1 "register_operand" "r")]
3222                      UNSPEC_ICACHE)
3223    (clobber (match_scratch:SI 2 "=&r"))]
3224   "TARGET_HARD_SH4"
3225   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
3226   [(set_attr "length" "8")])
3227
3228 (define_insn "ic_invalidate_line_media"
3229   [(unspec_volatile [(match_operand 0 "register_operand" "r")]
3230                     UNSPEC_ICACHE)]
3231   "TARGET_SHMEDIA"
3232   "icbi %0, 0\;synci"
3233   [(set_attr "length" "8")])
3234
3235 (define_insn "ic_invalidate_line_compact"
3236   [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
3237                      (match_operand:SI 1 "register_operand" "r")]
3238                     UNSPEC_ICACHE)
3239    (clobber (reg:SI PR_REG))]
3240   "TARGET_SHCOMPACT"
3241   "jsr @%1%#"
3242   [(set_attr "type" "sfunc")
3243    (set_attr "needs_delay_slot" "yes")])
3244
3245 (define_insn "movqi_i"
3246   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l")
3247         (match_operand:QI 1 "general_movsrc_operand"  "ri,m,r,t,l,r"))]
3248   "TARGET_SH1
3249    && (arith_reg_operand (operands[0], QImode)
3250        || arith_reg_operand (operands[1], QImode))"
3251   "@
3252         mov     %1,%0
3253         mov.b   %1,%0
3254         mov.b   %1,%0
3255         movt    %0
3256         sts     %1,%0
3257         lds     %1,%0"
3258  [(set_attr "type" "move,load,store,move,move,move")])
3259
3260 (define_insn "*movqi_media"
3261   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
3262         (match_operand:QI 1 "general_movsrc_operand" "r,JS,m,r"))]
3263   "TARGET_SHMEDIA
3264    && (arith_reg_operand (operands[0], QImode)
3265        || arith_reg_operand (operands[1], QImode))"
3266   "@
3267         add.l   %1, r63, %0
3268         movi    %1, %0
3269         ld%M1.b %m1, %0
3270         st%M0.b %m0, %1")
3271
3272 (define_expand "movqi"
3273   [(set (match_operand:QI 0 "general_operand" "")
3274         (match_operand:QI 1 "general_operand"  ""))]
3275   ""
3276   "{ if (prepare_move_operands (operands, QImode)) DONE; }")
3277
3278 (define_insn "movhi_i"
3279   [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r")
3280         (match_operand:HI 1 "general_movsrc_operand" "Q,rI,m,t,r,l,r,i"))]
3281   "TARGET_SH1
3282    && (arith_reg_operand (operands[0], HImode)
3283        || arith_reg_operand (operands[1], HImode))"
3284   "@
3285         mov.w   %1,%0
3286         mov     %1,%0
3287         mov.w   %1,%0
3288         movt    %0
3289         mov.w   %1,%0
3290         sts     %1,%0
3291         lds     %1,%0
3292         fake    %1,%0"
3293   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
3294
3295 (define_insn "*movhi_media"
3296   [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
3297         (match_operand:HI 1 "general_movsrc_operand" "r,JS,n,m,r"))]
3298   "TARGET_SHMEDIA
3299    && (arith_reg_operand (operands[0], HImode)
3300        || arith_reg_operand (operands[1], HImode))"
3301   "@
3302         add.l   %1, r63, %0
3303         movi    %1, %0
3304         #
3305         ld%M1.w %m1, %0
3306         st%M0.w %m0, %1")
3307
3308 (define_split
3309   [(set (match_operand:HI 0 "register_operand" "=r")
3310         (match_operand:HI 1 "immediate_operand" "n"))]
3311   "TARGET_SHMEDIA && ! CONST_OK_FOR_J (INTVAL (operands[1]))"
3312   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
3313
3314 (define_expand "movhi"
3315   [(set (match_operand:HI 0 "general_movdst_operand" "")
3316         (match_operand:HI 1 "general_movsrc_operand"  ""))]
3317   ""
3318   "{ if (prepare_move_operands (operands, HImode)) DONE; }")
3319
3320 ;; ??? This should be a define expand.
3321
3322 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
3323 ;; compiled with -m2 -ml -O3 -funroll-loops
3324 (define_insn ""
3325   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
3326         (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I,i,x,r"))]
3327   "TARGET_SH1
3328    && (arith_reg_operand (operands[0], DImode)
3329        || arith_reg_operand (operands[1], DImode))"
3330   "* return output_movedouble (insn, operands, DImode);"
3331   [(set_attr "length" "4")
3332    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
3333
3334 ;; If the output is a register and the input is memory or a register, we have
3335 ;; to be careful and see which word needs to be loaded first.  
3336
3337 (define_split
3338   [(set (match_operand:DI 0 "general_movdst_operand" "")
3339         (match_operand:DI 1 "general_movsrc_operand" ""))]
3340   "TARGET_SH1 && reload_completed"
3341   [(set (match_dup 2) (match_dup 3))
3342    (set (match_dup 4) (match_dup 5))]
3343   "
3344 {
3345   int regno;
3346
3347   if ((GET_CODE (operands[0]) == MEM
3348        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
3349       || (GET_CODE (operands[1]) == MEM
3350           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
3351     FAIL;
3352
3353   if (GET_CODE (operands[0]) == REG)
3354     regno = REGNO (operands[0]);
3355   else if (GET_CODE (operands[0]) == SUBREG)
3356     regno = subreg_regno (operands[0]);
3357   else if (GET_CODE (operands[0]) == MEM)
3358     regno = -1;
3359   else
3360     abort ();
3361
3362   if (regno == -1
3363       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
3364     {
3365       operands[2] = operand_subword (operands[0], 0, 0, DImode);
3366       operands[3] = operand_subword (operands[1], 0, 0, DImode);
3367       operands[4] = operand_subword (operands[0], 1, 0, DImode);
3368       operands[5] = operand_subword (operands[1], 1, 0, DImode);
3369     }
3370   else
3371     {
3372       operands[2] = operand_subword (operands[0], 1, 0, DImode);
3373       operands[3] = operand_subword (operands[1], 1, 0, DImode);
3374       operands[4] = operand_subword (operands[0], 0, 0, DImode);
3375       operands[5] = operand_subword (operands[1], 0, 0, DImode);
3376     }
3377
3378   if (operands[2] == 0 || operands[3] == 0
3379       || operands[4] == 0 || operands[5] == 0)
3380     FAIL;
3381 }")
3382
3383 (define_insn "*movdi_media"
3384   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,f,m,f,r,f,*b*k,r,b*k")
3385         (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,m,f,r,f,f,r,*b*k,T"))]
3386   "TARGET_SHMEDIA_FPU
3387    && (register_operand (operands[0], DImode)
3388        || register_operand (operands[1], DImode))"
3389   "@
3390         add     %1, r63, %0
3391         movi    %1, %0
3392         #
3393         ld%M1.q %m1, %0
3394         st%M0.q %m0, %1
3395         fld%M1.d        %m1, %0
3396         fst%M0.d        %m0, %1
3397         fmov.qd %1, %0
3398         fmov.dq %1, %0
3399         fmov.d  %1, %0
3400         ptabs   %1, %0
3401         gettr   %1, %0
3402         pt      %1, %0"
3403   [(set_attr "type"   "move,move,*,load,store,load,store,move,move,move,ptabs,move,pt")
3404    (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
3405
3406 (define_insn "*movdi_media_nofpu"
3407   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b*k,r,b*k")
3408         (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,r,*b*k,T"))]
3409   "TARGET_SHMEDIA
3410    && (register_operand (operands[0], DImode)
3411        || register_operand (operands[1], DImode))"
3412   "@
3413         add     %1, r63, %0
3414         movi    %1, %0
3415         #
3416         ld%M1.q %m1, %0
3417         st%M0.q %m0, %1
3418         ptabs   %1, %0
3419         gettr   %1, %0
3420         pt      %1, %0"
3421   [(set_attr "type"   "move,move,*,load,store,ptabs,move,pt")
3422    (set_attr "length" "4,4,16,4,4,4,4,*")])
3423
3424 (define_split
3425   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3426         (match_operand:DI 1 "immediate_operand" "s"))]
3427   "TARGET_SHMEDIA && reload_completed
3428    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3429   [(set (match_dup 0) (match_dup 1))]
3430   "
3431 {
3432   rtx insn;
3433
3434   if (TARGET_SHMEDIA64)
3435     insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
3436   else
3437     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
3438
3439   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
3440                                         REG_NOTES (insn));
3441
3442   DONE;
3443 }")
3444
3445 (define_expand "movdi_const"
3446   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3447         (const:DI (sign_extend:DI
3448                    (truncate:HI
3449                     (ashiftrt:DI
3450                      (match_operand:DI 1 "immediate_operand" "s")
3451                      (const_int 48))))))
3452    (set (match_dup 0)
3453         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3454                 (zero_extend:DI
3455                  (truncate:HI
3456                   (const:DI
3457                    (sign_extend:DI
3458                     (truncate:HI
3459                      (ashiftrt:SI
3460                       (match_dup 1)
3461                       (const_int 32)))))))))
3462    (set (match_dup 0)
3463         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3464                 (zero_extend:DI
3465                  (truncate:HI
3466                   (const:DI
3467                    (sign_extend:DI
3468                     (truncate:HI
3469                      (ashiftrt:SI
3470                       (match_dup 1)
3471                       (const_int 16)))))))))
3472    (set (match_dup 0)
3473         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3474                 (zero_extend:DI
3475                  (truncate:HI
3476                   (const:DI
3477                    (sign_extend:DI
3478                     (truncate:HI
3479                      (match_dup 1))))))))]
3480   "TARGET_SHMEDIA64 && reload_completed
3481    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3482   "
3483 {
3484   if (GET_CODE (operands[1]) == LABEL_REF
3485       && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
3486     LABEL_NUSES (XEXP (operands[1], 0)) += 4;
3487   else if (GOTOFF_P (operands[1])
3488            && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == LABEL_REF
3489            && (GET_CODE (XEXP (XVECEXP (XEXP (operands[1], 0), 0, 0), 0))
3490                == CODE_LABEL))
3491     LABEL_NUSES (XEXP (XVECEXP (XEXP (operands[1], 0), 0, 0), 0)) += 4;
3492 }")
3493
3494 (define_expand "movdi_const_32bit"
3495   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3496         (const:DI (sign_extend:DI
3497                    (truncate:HI
3498                     (ashiftrt:DI
3499                      (match_operand:DI 1 "immediate_operand" "s")
3500                      (const_int 16))))))
3501    (set (match_dup 0)
3502         (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3503                 (zero_extend:DI
3504                  (truncate:HI
3505                   (const:DI
3506                    (sign_extend:DI
3507                     (truncate:HI
3508                      (match_dup 1))))))))]
3509   "TARGET_SHMEDIA32 && reload_completed
3510    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
3511   "
3512 {
3513   if (GET_CODE (operands[1]) == LABEL_REF
3514       && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
3515     LABEL_NUSES (XEXP (operands[1], 0)) += 2;
3516   else if (GOTOFF_P (operands[1])
3517            && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == LABEL_REF
3518            && (GET_CODE (XEXP (XVECEXP (XEXP (operands[1], 0), 0, 0), 0))
3519                == CODE_LABEL))
3520     LABEL_NUSES (XEXP (XVECEXP (XEXP (operands[1], 0), 0, 0), 0)) += 2;
3521 }")
3522
3523 (define_expand "movdi_const_16bit"
3524   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3525         (const:DI (sign_extend:DI
3526                    (truncate:HI
3527                     (match_operand:DI 1 "immediate_operand" "s")))))]
3528   "TARGET_SHMEDIA && flag_pic && reload_completed
3529    && GET_CODE (operands[1]) == SYMBOL_REF"
3530   "")
3531
3532 (define_split
3533   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3534         (match_operand:DI 1 "immediate_operand" "i"))]
3535   "TARGET_SHMEDIA && reload_completed
3536    && GET_CODE (operands[1]) == CONST_INT
3537    && ! CONST_OK_FOR_J (INTVAL (operands[1]))"
3538   [(set (match_dup 0) (match_dup 2))
3539   (set (match_dup 0)
3540        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3541                (zero_extend:DI (truncate:HI (match_dup 1)))))]
3542   "
3543 {
3544   unsigned HOST_WIDE_INT low = INTVAL (operands[1]);
3545   unsigned HOST_WIDE_INT val = low;
3546   unsigned HOST_WIDE_INT sign;
3547
3548   /* Sign-extend the 16 least-significant bits.  */
3549   val &= 0xffff;
3550   val ^= 0x8000;
3551   val -= 0x8000;
3552   operands[1] = GEN_INT (val);
3553
3554   /* Arithmetic shift right the word by 16 bits.  */
3555   low >>= 16;
3556   sign = 1;
3557   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
3558   low ^= sign;
3559   low -= sign;
3560   operands[2] = GEN_INT (low);
3561 }")
3562
3563 (define_split
3564   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
3565         (match_operand:DI 1 "immediate_operand" "F"))]
3566   "TARGET_SHMEDIA && reload_completed
3567    && GET_CODE (operands[1]) == CONST_DOUBLE"
3568   [(set (match_dup 0) (match_dup 2))
3569   (set (match_dup 0)
3570        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
3571                (zero_extend:DI (truncate:HI (match_dup 1)))))]
3572   "
3573 {
3574   unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
3575   unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
3576   unsigned HOST_WIDE_INT val = low;
3577   unsigned HOST_WIDE_INT sign;
3578
3579   /* Sign-extend the 16 least-significant bits.  */
3580   val &= 0xffff;
3581   val ^= 0x8000;
3582   val -= 0x8000;
3583   operands[1] = GEN_INT (val);
3584
3585   /* Arithmetic shift right the double-word by 16 bits.  */
3586   low >>= 16;
3587   low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
3588   high >>= 16;
3589   sign = 1;
3590   sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
3591   high ^= sign;
3592   high -= sign;
3593
3594   /* This will only be true if high is a sign-extension of low, i.e.,
3595      it must be either 0 or (unsigned)-1, and be zero iff the
3596      most-significant bit of low is set.  */
3597   if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
3598     operands[2] = GEN_INT (low);
3599   else
3600     operands[2] = immed_double_const (low, high, DImode);
3601 }")
3602
3603 (define_insn "*shori_media"
3604   [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
3605         (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
3606                            (const_int 16))
3607                 (zero_extend:DI
3608                  (truncate:HI
3609                   (match_operand:DI 2 "immediate_operand" "JS,nF")))))]
3610   "TARGET_SHMEDIA"
3611   "@
3612         shori   %u2, %0
3613         #")
3614
3615 (define_expand "movdi"
3616   [(set (match_operand:DI 0 "general_movdst_operand" "")
3617         (match_operand:DI 1 "general_movsrc_operand" ""))]
3618   ""
3619   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
3620
3621 (define_insn "movdf_media"
3622   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
3623         (match_operand:DF 1 "general_movsrc_operand" "f,r,f,r,F,m,f,m,r"))]
3624   "TARGET_SHMEDIA_FPU
3625    && (register_operand (operands[0], DFmode)
3626        || register_operand (operands[1], DFmode))"
3627   "@
3628         fmov.d  %1, %0
3629         fmov.qd %1, %0
3630         fmov.dq %1, %0
3631         add     %1, r63, %0
3632         #
3633         fld%M1.d        %m1, %0
3634         fst%M0.d        %m0, %1
3635         ld%M1.q %m1, %0
3636         st%M0.q %m0, %1"
3637   [(set_attr "type" "move,move,move,move,*,load,store,load,store")])
3638
3639 (define_insn "movdf_media_nofpu"
3640   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
3641         (match_operand:DF 1 "general_movsrc_operand" "r,F,m,r"))]
3642   "TARGET_SHMEDIA
3643    && (register_operand (operands[0], DFmode)
3644        || register_operand (operands[1], DFmode))"
3645   "@
3646         add     %1, r63, %0
3647         #
3648         ld%M1.q %m1, %0
3649         st%M0.q %m0, %1"
3650   [(set_attr "type" "move,*,load,store")])
3651
3652 (define_split
3653   [(set (match_operand:DF 0 "arith_reg_operand" "")
3654         (match_operand:DF 1 "immediate_operand" ""))]
3655   "TARGET_SHMEDIA && reload_completed"
3656   [(set (match_dup 3) (match_dup 2))]
3657   "
3658 {
3659   int endian = WORDS_BIG_ENDIAN ? 1 : 0;
3660   long values[2];
3661   REAL_VALUE_TYPE value;
3662
3663   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
3664   REAL_VALUE_TO_TARGET_DOUBLE (value, values);
3665
3666   if (HOST_BITS_PER_WIDE_INT >= 64)
3667     operands[2] = immed_double_const ((unsigned long) values[endian]
3668                                       | ((HOST_WIDE_INT) values[1 - endian]
3669                                          << 32), 0, DImode);
3670   else if (HOST_BITS_PER_WIDE_INT == 32)
3671     operands[2] = immed_double_const (values[endian], values[1 - endian],
3672                                       DImode);
3673   else
3674     abort ();
3675
3676   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
3677 }")
3678
3679 ;; ??? This should be a define expand.
3680
3681 (define_insn "movdf_k"
3682   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
3683         (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
3684   "TARGET_SH1
3685    && (! TARGET_SH4 || reload_completed
3686        /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
3687        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
3688        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
3689    && (arith_reg_operand (operands[0], DFmode)
3690        || arith_reg_operand (operands[1], DFmode))"
3691   "* return output_movedouble (insn, operands, DFmode);"
3692   [(set_attr "length" "4")
3693    (set_attr "type" "move,pcload,load,store")])
3694
3695 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
3696 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
3697 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
3698 ;; the d/m/c/X alternative, which is split later into single-precision
3699 ;; instructions.  And when not optimizing, no splits are done before fixing
3700 ;; up pcloads, so we need usable length information for that.
3701 (define_insn "movdf_i4"
3702   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
3703         (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
3704    (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
3705    (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
3706   "TARGET_SH4
3707    && (arith_reg_operand (operands[0], DFmode)
3708        || arith_reg_operand (operands[1], DFmode))"
3709   "@
3710         fmov    %1,%0
3711         #
3712         #
3713         fmov.d  %1,%0
3714         fmov.d  %1,%0
3715         #
3716         #
3717         #
3718         #
3719         #"
3720   [(set_attr_alternative "length"
3721      [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
3722       (const_int 4)
3723       (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
3724       (if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 6))
3725       (if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 6))
3726       (const_int 4)
3727       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
3728       ;; We can't use 4-byte push/pop on SHcompact, so we have to
3729       ;; increment or decrement r15 explicitly.
3730       (if_then_else
3731        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
3732        (const_int 10) (const_int 8))
3733       (if_then_else
3734        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
3735        (const_int 10) (const_int 8))])
3736    (set_attr "type" "fmove,move,pcload,load,store,pcload,load,store,load,load")
3737    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
3738                                            (const_string "double")
3739                                            (const_string "none")))])
3740
3741 ;; Moving DFmode between fp/general registers through memory
3742 ;; (the top of the stack) is faster than moving through fpul even for
3743 ;; little endian.  Because the type of an instruction is important for its
3744 ;; scheduling,  it is beneficial to split these operations, rather than
3745 ;; emitting them in one single chunk, even if this will expose a stack
3746 ;; use that will prevent scheduling of other stack accesses beyond this
3747 ;; instruction.
3748 (define_split
3749   [(set (match_operand:DF 0 "register_operand" "")
3750         (match_operand:DF 1 "register_operand" ""))
3751    (use (match_operand:PSI 2 "fpscr_operand" "c"))
3752    (clobber (match_scratch:SI 3 "=X"))]
3753   "TARGET_SH4 && reload_completed
3754    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
3755   [(const_int 0)]
3756   "
3757 {
3758   rtx insn, tos;
3759
3760   if (TARGET_SH5 && true_regnum (operands[1]) < 16)
3761     {
3762       emit_move_insn (stack_pointer_rtx,
3763                       plus_constant (stack_pointer_rtx, -8));
3764       tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
3765     }
3766   else
3767     tos = gen_rtx (MEM, DFmode, gen_rtx (PRE_DEC, Pmode, stack_pointer_rtx));
3768   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
3769   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
3770     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
3771   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
3772     tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
3773   else
3774     tos = gen_rtx (MEM, DFmode, gen_rtx (POST_INC, Pmode, stack_pointer_rtx));
3775   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
3776   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
3777     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
3778   else
3779     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
3780   DONE;
3781 }")
3782
3783 ;; local-alloc sometimes allocates scratch registers even when not required,
3784 ;; so we must be prepared to handle these.
3785
3786 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
3787 (define_split
3788   [(set (match_operand:DF 0 "general_movdst_operand" "")
3789         (match_operand:DF 1 "general_movsrc_operand"  ""))
3790    (use (match_operand:PSI 2 "fpscr_operand" "c"))
3791    (clobber (match_scratch:SI 3 "X"))]
3792   "TARGET_SH4
3793    && reload_completed
3794    && true_regnum (operands[0]) < 16
3795    && true_regnum (operands[1]) < 16"
3796   [(set (match_dup 0) (match_dup 1))]
3797   "
3798 {
3799   /* If this was a reg <-> mem operation with base + index reg addressing,
3800      we have to handle this in a special way.  */
3801   rtx mem = operands[0];
3802   int store_p = 1;
3803   if (! memory_operand (mem, DFmode))
3804     {
3805       mem = operands[1];
3806       store_p = 0;
3807     }
3808   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
3809     mem = SUBREG_REG (mem);
3810   if (GET_CODE (mem) == MEM)
3811     {
3812       rtx addr = XEXP (mem, 0);
3813       if (GET_CODE (addr) == PLUS
3814           && GET_CODE (XEXP (addr, 0)) == REG
3815           && GET_CODE (XEXP (addr, 1)) == REG)
3816         {
3817           int offset;
3818           rtx reg0 = gen_rtx (REG, Pmode, 0);
3819           rtx regop = operands[store_p], word0 ,word1;
3820
3821           if (GET_CODE (regop) == SUBREG)
3822             alter_subreg (&regop);
3823           if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
3824             offset = 2;
3825           else
3826             offset = 4;
3827           mem = copy_rtx (mem);
3828           PUT_MODE (mem, SImode);
3829           word0 = gen_rtx (SUBREG, SImode, regop, 0);
3830           alter_subreg (&word0);
3831           word1 = gen_rtx (SUBREG, SImode, regop, 4);
3832           alter_subreg (&word1);
3833           if (store_p || ! refers_to_regno_p (REGNO (word0),
3834                                               REGNO (word0) + 1, addr, 0))
3835             {
3836               emit_insn (store_p
3837                          ? gen_movsi_ie (mem, word0)
3838                          : gen_movsi_ie (word0, mem));
3839               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
3840               mem = copy_rtx (mem);
3841               emit_insn (store_p
3842                          ? gen_movsi_ie (mem, word1)
3843                          : gen_movsi_ie (word1, mem));
3844               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
3845             }
3846           else
3847             {
3848               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
3849               emit_insn (gen_movsi_ie (word1, mem));
3850               emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
3851               mem = copy_rtx (mem);
3852               emit_insn (gen_movsi_ie (word0, mem));
3853             }
3854           DONE;
3855         }
3856     }
3857 }")
3858
3859 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
3860 (define_split
3861   [(set (match_operand:DF 0 "register_operand" "")
3862         (match_operand:DF 1 "memory_operand"  ""))
3863    (use (match_operand:PSI 2 "fpscr_operand" "c"))
3864    (clobber (reg:SI R0_REG))]
3865   "TARGET_SH4 && reload_completed"
3866   [(parallel [(set (match_dup 0) (match_dup 1))
3867               (use (match_dup 2))
3868               (clobber (scratch:SI))])]
3869   "")
3870
3871 (define_expand "reload_indf"
3872   [(parallel [(set (match_operand:DF 0 "register_operand" "=f")
3873                    (match_operand:DF 1 "immediate_operand" "FQ"))
3874               (use (reg:PSI FPSCR_REG))
3875               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
3876   "TARGET_SH1"
3877   "")
3878
3879 (define_expand "reload_outdf"
3880   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
3881                    (match_operand:DF 1 "register_operand" "af,r"))
3882               (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
3883   "TARGET_SH1"
3884   "")
3885
3886 ;; Simplify no-op moves.
3887 (define_split
3888   [(set (match_operand:SF 0 "register_operand" "")
3889         (match_operand:SF 1 "register_operand" ""))
3890    (use (match_operand:PSI 2 "fpscr_operand" ""))
3891    (clobber (match_scratch:SI 3 "X"))]
3892   "TARGET_SH3E && reload_completed
3893    && true_regnum (operands[0]) == true_regnum (operands[1])"
3894   [(set (match_dup 0) (match_dup 0))]
3895   "")
3896
3897 ;; fmovd substitute post-reload splits
3898 (define_split
3899   [(set (match_operand:DF 0 "register_operand" "")
3900         (match_operand:DF 1 "register_operand" ""))
3901    (use (match_operand:PSI 2 "fpscr_operand" "c"))
3902    (clobber (match_scratch:SI 3 "X"))]
3903   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
3904    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
3905    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
3906   [(const_int 0)]
3907   "
3908 {
3909   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
3910   emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, dst),
3911                            gen_rtx (REG, SFmode, src), operands[2]));
3912   emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode, dst + 1),
3913                            gen_rtx (REG, SFmode, src + 1), operands[2]));
3914   DONE;
3915 }")
3916
3917 (define_split
3918   [(set (match_operand:DF 0 "register_operand" "")
3919         (mem:DF (match_operand:SI 1 "register_operand" "")))
3920    (use (match_operand:PSI 2 "fpscr_operand" "c"))
3921    (clobber (match_scratch:SI 3 "X"))]
3922   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
3923    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
3924    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
3925   [(const_int 0)]
3926   "
3927 {
3928   int regno = true_regnum (operands[0]);
3929   rtx insn;
3930   rtx mem2 = gen_rtx (MEM, SFmode, gen_rtx (POST_INC, Pmode, operands[1]));
3931
3932   insn = emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode,
3933                                            regno + !! TARGET_LITTLE_ENDIAN),
3934                                   mem2, operands[2]));
3935   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[1], NULL_RTX);
3936   insn = emit_insn (gen_movsf_ie (gen_rtx (REG, SFmode,
3937                                            regno + ! TARGET_LITTLE_ENDIAN),
3938                                   gen_rtx (MEM, SFmode, operands[1]),
3939                                   operands[2]));
3940   DONE;
3941 }")
3942
3943 (define_split
3944   [(set (match_operand:DF 0 "register_operand" "")
3945         (match_operand:DF 1 "memory_operand" ""))
3946    (use (match_operand:PSI 2 "fpscr_operand" "c"))
3947    (clobber (match_scratch:SI 3 "X"))]
3948   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
3949    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
3950   [(const_int 0)]
3951   "
3952 {
3953   int regno = true_regnum (operands[0]);
3954   rtx addr, insn, adjust = NULL_RTX;
3955   rtx mem2 = copy_rtx (operands[1]);
3956   rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
3957   rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
3958
3959   PUT_MODE (mem2, SFmode);
3960   operands[1] = copy_rtx (mem2);
3961   addr = XEXP (mem2, 0);
3962   if (GET_CODE (addr) != POST_INC)
3963     {
3964       /* If we have to modify the stack pointer, the value that we have
3965          read with post-increment might be modified by an interrupt,
3966          so write it back.  */
3967       if (REGNO (addr) == STACK_POINTER_REGNUM)
3968         adjust = gen_push_e (reg0);
3969       else
3970         adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
3971       XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
3972     }
3973   addr = XEXP (addr, 0);
3974   insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
3975   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
3976   insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
3977   if (adjust)
3978     emit_insn (adjust);
3979   else
3980     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
3981   DONE;
3982 }")
3983
3984 (define_split
3985   [(set (match_operand:DF 0 "memory_operand" "")
3986         (match_operand:DF 1 "register_operand" ""))
3987    (use (match_operand:PSI 2 "fpscr_operand" "c"))
3988    (clobber (match_scratch:SI 3 "X"))]
3989   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
3990    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
3991   [(const_int 0)]
3992   "
3993 {
3994   int regno = true_regnum (operands[1]);
3995   rtx insn, addr, adjust = NULL_RTX;
3996
3997   operands[0] = copy_rtx (operands[0]);
3998   PUT_MODE (operands[0], SFmode);
3999   insn = emit_insn (gen_movsf_ie (operands[0],
4000                                   gen_rtx (REG, SFmode,
4001                                            regno + ! TARGET_LITTLE_ENDIAN),
4002                                   operands[2]));
4003   operands[0] = copy_rtx (operands[0]);
4004   addr = XEXP (operands[0], 0);
4005   if (GET_CODE (addr) != PRE_DEC)
4006     {
4007       adjust = gen_addsi3 (addr, addr, GEN_INT (4));
4008       emit_insn_before (adjust, insn);
4009       XEXP (operands[0], 0) = addr = gen_rtx (PRE_DEC, SImode, addr);
4010     }
4011   addr = XEXP (addr, 0);
4012   if (! adjust)
4013     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, addr, NULL_RTX);
4014   insn = emit_insn (gen_movsf_ie (operands[0],
4015                                   gen_rtx (REG, SFmode,
4016                                            regno + !! TARGET_LITTLE_ENDIAN),
4017                                   operands[2]));
4018   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, addr, NULL_RTX);
4019   DONE;
4020 }")
4021
4022 ;; If the output is a register and the input is memory or a register, we have
4023 ;; to be careful and see which word needs to be loaded first.  
4024
4025 (define_split
4026   [(set (match_operand:DF 0 "general_movdst_operand" "")
4027         (match_operand:DF 1 "general_movsrc_operand" ""))]
4028   "TARGET_SH1 && reload_completed"
4029   [(set (match_dup 2) (match_dup 3))
4030    (set (match_dup 4) (match_dup 5))]
4031   "
4032 {
4033   int regno;
4034
4035   if ((GET_CODE (operands[0]) == MEM
4036        && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
4037       || (GET_CODE (operands[1]) == MEM
4038           && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
4039     FAIL;
4040
4041   if (GET_CODE (operands[0]) == REG)
4042     regno = REGNO (operands[0]);
4043   else if (GET_CODE (operands[0]) == SUBREG)
4044     regno = subreg_regno (operands[0]);
4045   else if (GET_CODE (operands[0]) == MEM)
4046     regno = -1;
4047   else
4048     abort ();
4049
4050   if (regno == -1
4051       || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
4052     {
4053       operands[2] = operand_subword (operands[0], 0, 0, DFmode);
4054       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
4055       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
4056       operands[5] = operand_subword (operands[1], 1, 0, DFmode);
4057     }
4058   else
4059     {
4060       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
4061       operands[3] = operand_subword (operands[1], 1, 0, DFmode);
4062       operands[4] = operand_subword (operands[0], 0, 0, DFmode);
4063       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
4064     }
4065
4066   if (operands[2] == 0 || operands[3] == 0
4067       || operands[4] == 0 || operands[5] == 0)
4068     FAIL;
4069 }")
4070
4071 ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
4072 ;; used only once, let combine add in the index again.
4073
4074 (define_split
4075   [(set (match_operand:SI 0 "register_operand" "")
4076         (match_operand:SI 1 "" ""))
4077    (clobber (match_operand 2 "register_operand" ""))]
4078   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4079   [(use (reg:SI R0_REG))]
4080   "
4081 {
4082   rtx addr, reg, const_int;
4083
4084   if (GET_CODE (operands[1]) != MEM)
4085     FAIL;
4086   addr = XEXP (operands[1], 0);
4087   if (GET_CODE (addr) != PLUS)
4088     FAIL;
4089   reg = XEXP (addr, 0);
4090   const_int = XEXP (addr, 1);
4091   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4092          && GET_CODE (const_int) == CONST_INT))
4093     FAIL;
4094   emit_move_insn (operands[2], const_int);
4095   emit_move_insn (operands[0],
4096                   change_address (operands[1], VOIDmode,
4097                                   gen_rtx_PLUS (SImode, reg, operands[2])));
4098   DONE;
4099 }")
4100
4101 (define_split
4102   [(set (match_operand:SI 1 "" "")
4103         (match_operand:SI 0 "register_operand" ""))
4104    (clobber (match_operand 2 "register_operand" ""))]
4105   "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
4106   [(use (reg:SI R0_REG))]
4107   "
4108 {
4109   rtx addr, reg, const_int;
4110
4111   if (GET_CODE (operands[1]) != MEM)
4112     FAIL;
4113   addr = XEXP (operands[1], 0);
4114   if (GET_CODE (addr) != PLUS)
4115     FAIL;
4116   reg = XEXP (addr, 0);
4117   const_int = XEXP (addr, 1);
4118   if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
4119          && GET_CODE (const_int) == CONST_INT))
4120     FAIL;
4121   emit_move_insn (operands[2], const_int);
4122   emit_move_insn (change_address (operands[1], VOIDmode,
4123                                   gen_rtx_PLUS (SImode, reg, operands[2])),
4124                   operands[0]);
4125   DONE;
4126 }")
4127
4128 (define_expand "movdf"
4129   [(set (match_operand:DF 0 "general_movdst_operand" "")
4130         (match_operand:DF 1 "general_movsrc_operand" ""))]
4131   ""
4132   "
4133 {
4134   if (prepare_move_operands (operands, DFmode)) DONE;
4135   if (TARGET_SHMEDIA)
4136     {
4137       if (TARGET_SHMEDIA_FPU)
4138         emit_insn (gen_movdf_media (operands[0], operands[1]));
4139       else
4140         emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
4141       DONE;
4142     }
4143   if (TARGET_SH4)
4144     {
4145       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
4146       DONE;
4147     }
4148 }")
4149
4150 (define_insn "movv2sf_i"
4151   [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
4152         (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
4153   "TARGET_SHMEDIA_FPU
4154    && (fp_arith_reg_operand (operands[0], V2SFmode)
4155        || fp_arith_reg_operand (operands[1], V2SFmode))"
4156   "@
4157         #
4158         fld%M1.p        %m1, %0
4159         fst%M0.p        %m0, %1")
4160
4161 (define_split
4162   [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f")
4163         (match_operand:V2SF 1 "nonimmediate_operand" "f"))]
4164   "TARGET_SHMEDIA_FPU && reload_completed
4165    && fp_arith_reg_operand (operands[0], V2SFmode)
4166    && fp_arith_reg_operand (operands[1], V2SFmode)"
4167   [(set (subreg:DF (match_dup 0) 0) (subreg:DF (match_dup 1) 0))])
4168
4169 (define_expand "movv2sf"
4170   [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
4171         (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
4172   "TARGET_SHMEDIA_FPU"
4173   "
4174 {
4175   if (prepare_move_operands (operands, V2SFmode))
4176     DONE;
4177 }")
4178
4179 (define_insn_and_split "*movv4sf_i"
4180   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
4181         (match_operand:V4SF 1 "nonimmediate_operand" "f,m,f"))]
4182   "TARGET_SHMEDIA_FPU"
4183   "#"
4184   "&& reload_completed"
4185   [(const_int 0)]
4186   "
4187 {
4188   int i;
4189
4190   for (i = 0; i < 4/2; i++)
4191     {
4192       rtx x, y;
4193
4194       if (GET_CODE (operands[0]) == MEM)
4195         x = gen_rtx_MEM (V2SFmode,
4196                          plus_constant (XEXP (operands[0], 0),
4197                                         i * GET_MODE_SIZE (V2SFmode)));
4198       else
4199         {
4200           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 2);
4201           alter_subreg (&x);
4202         }
4203
4204       if (GET_CODE (operands[1]) == MEM)
4205         y = gen_rtx_MEM (V2SFmode,
4206                          plus_constant (XEXP (operands[1], 0),
4207                                         i * GET_MODE_SIZE (V2SFmode)));
4208       else
4209         {
4210           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 2);
4211           alter_subreg (&y);
4212         }
4213
4214       emit_insn (gen_movv2sf_i (x, y));
4215     }
4216
4217   DONE;
4218 }"
4219   [(set_attr "length" "8")])
4220   
4221 (define_expand "movv4sf"
4222   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
4223         (match_operand:V4SF 1 "nonimmediate_operand" "f,m,f"))]
4224   "TARGET_SHMEDIA_FPU"
4225   "
4226 {
4227   if (prepare_move_operands (operands, V4SFmode))
4228     DONE;
4229 }")
4230
4231 (define_insn_and_split "*movv16sf_i"
4232   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4233         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4234   "TARGET_SHMEDIA_FPU"
4235   "#"
4236   "&& reload_completed"
4237   [(const_int 0)]
4238   "
4239 {
4240   int i;
4241
4242   for (i = 0; i < 16/2; i++)
4243     {
4244       rtx x,y;
4245
4246       if (GET_CODE (operands[0]) == MEM)
4247         x = gen_rtx_MEM (V2SFmode,
4248                          plus_constant (XEXP (operands[0], 0),
4249                                         i * GET_MODE_SIZE (V2SFmode)));
4250       else
4251         {
4252           x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 2);
4253           alter_subreg (&x);
4254         }
4255
4256       if (GET_CODE (operands[1]) == MEM)
4257         y = gen_rtx_MEM (V2SFmode,
4258                          plus_constant (XEXP (operands[1], 0),
4259                                         i * GET_MODE_SIZE (V2SFmode)));
4260       else
4261         {
4262           y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 2);
4263           alter_subreg (&y);
4264         }
4265
4266       emit_insn (gen_movv2sf_i (x, y));
4267     }
4268
4269   DONE;
4270 }"
4271   [(set_attr "length" "32")])
4272   
4273 (define_expand "movv16sf"
4274   [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
4275         (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
4276   "TARGET_SHMEDIA_FPU"
4277   "
4278 {
4279   if (prepare_move_operands (operands, V16SFmode))
4280     DONE;
4281 }")
4282
4283 (define_insn "movsf_media"
4284   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
4285         (match_operand:SF 1 "general_movsrc_operand" "f,r,f,r,F,m,f,m,r"))]
4286   "TARGET_SHMEDIA_FPU
4287    && (register_operand (operands[0], SFmode)
4288        || register_operand (operands[1], SFmode))"
4289   "@
4290         fmov.s  %1, %0
4291         fmov.ls %1, %0
4292         fmov.sl %1, %0
4293         add     %1, r63, %0
4294         #
4295         fld%M1.s        %m1, %0
4296         fst%M0.s        %m0, %1
4297         ld%M1.l %m1, %0
4298         st%M0.l %m0, %1"
4299   [(set_attr "type" "move,move,move,move,*,load,store,load,store")])
4300
4301 (define_insn "movsf_media_nofpu"
4302   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
4303         (match_operand:SF 1 "general_movsrc_operand" "r,F,m,r"))]
4304   "TARGET_SHMEDIA
4305    && (register_operand (operands[0], SFmode)
4306        || register_operand (operands[1], SFmode))"
4307   "@
4308         add     %1, r63, %0
4309         #
4310         ld%M1.l %m1, %0
4311         st%M0.l %m0, %1"
4312   [(set_attr "type" "move,*,load,store")])
4313
4314 (define_split
4315   [(set (match_operand:SF 0 "arith_reg_operand" "")
4316         (match_operand:SF 1 "immediate_operand" ""))]
4317   "TARGET_SHMEDIA && reload_completed"
4318   [(set (match_dup 3) (match_dup 2))]
4319   "
4320 {
4321   long values;
4322   REAL_VALUE_TYPE value;
4323
4324   REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
4325   REAL_VALUE_TO_TARGET_SINGLE (value, values);
4326   operands[2] = GEN_INT (values);
4327   
4328   operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
4329 }")
4330
4331 (define_insn "movsf_i"
4332   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
4333         (match_operand:SF 1 "general_movsrc_operand"  "r,I,FQ,mr,r,r,l"))]
4334   "TARGET_SH1
4335    && (! TARGET_SH3E
4336        /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
4337        || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
4338        || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
4339    && (arith_reg_operand (operands[0], SFmode)
4340        || arith_reg_operand (operands[1], SFmode))"
4341   "@
4342         mov     %1,%0
4343         mov     %1,%0
4344         mov.l   %1,%0
4345         mov.l   %1,%0
4346         mov.l   %1,%0
4347         lds     %1,%0
4348         sts     %1,%0"
4349   [(set_attr "type" "move,move,pcload,load,store,move,move")])
4350
4351 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
4352 ;; update_flow_info would not know where to put REG_EQUAL notes
4353 ;; when the destination changes mode.
4354 (define_insn "movsf_ie"
4355   [(set (match_operand:SF 0 "general_movdst_operand"
4356          "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
4357         (match_operand:SF 1 "general_movsrc_operand"
4358           "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
4359    (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"))
4360    (clobber (match_scratch:SI 3 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
4361
4362   "TARGET_SH3E
4363    && (arith_reg_operand (operands[0], SFmode)
4364        || arith_reg_operand (operands[1], SFmode)
4365        || arith_reg_operand (operands[3], SImode)
4366        || (fpul_operand (operands[0], SFmode)
4367            && memory_operand (operands[1], SFmode)
4368            && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
4369        || (fpul_operand (operands[1], SFmode)
4370            && memory_operand (operands[0], SFmode)
4371            && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
4372   "@
4373         fmov    %1,%0
4374         mov     %1,%0
4375         fldi0   %0
4376         fldi1   %0
4377         #
4378         fmov.s  %1,%0
4379         fmov.s  %1,%0
4380         mov.l   %1,%0
4381         mov.l   %1,%0
4382         mov.l   %1,%0
4383         fsts    fpul,%0
4384         flds    %1,fpul
4385         lds.l   %1,%0
4386         #
4387         sts     %1,%0
4388         lds     %1,%0
4389         sts.l   %1,%0
4390         lds.l   %1,%0
4391         ! move optimized away"
4392   [(set_attr "type" "fmove,move,fmove,fmove,pcload,load,store,pcload,load,store,fmove,fmove,load,*,gp_fpul,gp_fpul,store,load,nil")
4393    (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,4,2,2,2,2,0")
4394    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
4395                                            (const_string "single")
4396                                            (const_string "none")))])
4397
4398 (define_split
4399   [(set (match_operand:SF 0 "register_operand" "")
4400         (match_operand:SF 1 "register_operand" ""))
4401    (use (match_operand:PSI 2 "fpscr_operand" "c"))
4402    (clobber (reg:SI FPUL_REG))]
4403   "TARGET_SH1"
4404   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
4405               (use (match_dup 2))
4406               (clobber (scratch:SI))])
4407    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
4408               (use (match_dup 2))
4409               (clobber (scratch:SI))])]
4410   "")
4411
4412 (define_expand "movsf"
4413   [(set (match_operand:SF 0 "general_movdst_operand" "")
4414         (match_operand:SF 1 "general_movsrc_operand" ""))]
4415   ""
4416   "
4417 {
4418   if (prepare_move_operands (operands, SFmode))
4419     DONE;
4420   if (TARGET_SHMEDIA)
4421     {
4422       if (TARGET_SHMEDIA_FPU)
4423         emit_insn (gen_movsf_media (operands[0], operands[1]));
4424       else
4425         emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
4426       DONE;
4427     }
4428   if (TARGET_SH3E)
4429     {
4430       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
4431       DONE;
4432     }
4433 }")
4434
4435 (define_insn "mov_nop"
4436   [(set (match_operand 0 "register_operand" "") (match_dup 0))]
4437   "TARGET_SH3E"
4438   ""
4439   [(set_attr "length" "0")
4440    (set_attr "type" "nil")])
4441
4442 (define_expand "reload_insf"
4443   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
4444                    (match_operand:SF 1 "immediate_operand" "FQ"))
4445               (use (reg:PSI FPSCR_REG))
4446               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4447   "TARGET_SH1"
4448   "")
4449
4450 (define_expand "reload_insi"
4451   [(parallel [(set (match_operand:SF 0 "register_operand" "=y")
4452                    (match_operand:SF 1 "immediate_operand" "FQ"))
4453               (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
4454   "TARGET_SH1"
4455   "")
4456
4457 (define_insn "*movsi_y"
4458   [(set (match_operand:SI 0 "register_operand" "=y,y")
4459         (match_operand:SI 1 "immediate_operand" "Qi,I"))
4460    (clobber (match_scratch:SI 2 "=&z,r"))]
4461   "TARGET_SH3E
4462    && (reload_in_progress || reload_completed)"
4463   "#"
4464   [(set_attr "length" "4")
4465    (set_attr "type" "pcload,move")])
4466
4467 (define_split
4468   [(set (match_operand:SI 0 "register_operand" "")
4469         (match_operand:SI 1 "immediate_operand" ""))
4470    (clobber (match_operand:SI 2 "register_operand" ""))]
4471   "TARGET_SH1"
4472   [(set (match_dup 2) (match_dup 1))
4473    (set (match_dup 0) (match_dup 2))]
4474   "")
4475
4476 (define_split
4477   [(set (match_operand:SI 0 "register_operand" "")
4478         (match_operand:SI 1 "memory_operand" ""))
4479    (clobber (reg:SI R0_REG))]
4480   "TARGET_SH1"
4481   [(set (match_dup 0) (match_dup 1))]
4482   "")
4483 \f
4484 ;; ------------------------------------------------------------------------
4485 ;; Define the real conditional branch instructions.
4486 ;; ------------------------------------------------------------------------
4487
4488 (define_insn "branch_true"
4489   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
4490                            (label_ref (match_operand 0 "" ""))
4491                            (pc)))]
4492   "TARGET_SH1"
4493   "* return output_branch (1, insn, operands);"
4494   [(set_attr "type" "cbranch")])
4495
4496 (define_insn "branch_false"
4497   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
4498                            (label_ref (match_operand 0 "" ""))
4499                            (pc)))]
4500   "TARGET_SH1"
4501   "* return output_branch (0, insn, operands);"
4502   [(set_attr "type" "cbranch")])
4503
4504 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
4505 ;; which destination is too far away.
4506 ;; The const_int_operand is distinct for each branch target; it avoids
4507 ;; unwanted matches with redundant_insn.
4508 (define_insn "block_branch_redirect"
4509   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
4510   "TARGET_SH1"
4511   ""
4512   [(set_attr "length" "0")])
4513
4514 ;; This one has the additional purpose to record a possible scratch register
4515 ;; for the following branch.
4516 (define_insn "indirect_jump_scratch"
4517   [(set (match_operand 0 "register_operand" "=r")
4518         (unspec [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))]
4519   "TARGET_SH1"
4520   ""
4521   [(set_attr "length" "0")])
4522 \f
4523 ;; Conditional branch insns
4524
4525 (define_expand "beq_media"
4526   [(set (pc)
4527         (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
4528                           (match_operand:DI 2 "arith_operand" "r,O"))
4529                       (label_ref:DI (match_operand 0 "" ""))
4530                       (pc)))]
4531   "TARGET_SHMEDIA"
4532   "")
4533
4534 (define_insn "beq_media_i"
4535   [(set (pc)
4536         (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
4537                           (match_operand:DI 2 "arith_operand" "r,O"))
4538                       (match_operand:DI 0 "target_operand" "b,b")
4539                       (pc)))]
4540   "TARGET_SHMEDIA"
4541   "@
4542         beq     %1, %2, %0
4543         beqi    %1, %2, %0")
4544
4545 (define_expand "bne_media"
4546   [(set (pc)
4547         (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
4548                           (match_operand:DI 2 "arith_operand" "r,O"))
4549                       (label_ref:DI (match_operand 0 "" ""))
4550                       (pc)))]
4551   "TARGET_SHMEDIA"
4552   "")
4553
4554 (define_insn "bne_media_i"
4555   [(set (pc)
4556         (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
4557                           (match_operand:DI 2 "arith_operand" "r,O"))
4558                       (match_operand:DI 0 "target_operand" "b,b")
4559                       (pc)))]
4560   "TARGET_SHMEDIA"
4561   "@
4562         bne     %1, %2, %0
4563         bnei    %1, %2, %0")
4564
4565 (define_expand "bgt_media"
4566   [(set (pc)
4567         (if_then_else (gt (match_operand:DI 1 "arith_reg_operand" "r")
4568                           (match_operand:DI 2 "arith_reg_operand" "r"))
4569                       (label_ref:DI (match_operand 0 "" ""))
4570                       (pc)))]
4571   "TARGET_SHMEDIA"
4572   "")
4573
4574 (define_insn "bgt_media_i"
4575   [(set (pc)
4576         (if_then_else (gt (match_operand:DI 1 "arith_reg_operand" "r")
4577                           (match_operand:DI 2 "arith_reg_operand" "r"))
4578                       (match_operand:DI 0 "target_operand" "b")
4579                       (pc)))]
4580   "TARGET_SHMEDIA"
4581   "bgt  %1, %2, %0")
4582
4583 (define_expand "bge_media"
4584   [(set (pc)
4585         (if_then_else (ge (match_operand:DI 1 "arith_reg_operand" "r")
4586                           (match_operand:DI 2 "arith_reg_operand" "r"))
4587                       (label_ref:DI (match_operand 0 "" ""))
4588                       (pc)))]
4589   "TARGET_SHMEDIA"
4590   "")
4591
4592 (define_insn "bge_media_i"
4593   [(set (pc)
4594         (if_then_else (ge (match_operand:DI 1 "arith_reg_operand" "r")
4595                           (match_operand:DI 2 "arith_reg_operand" "r"))
4596                       (match_operand:DI 0 "target_operand" "b")
4597                       (pc)))]
4598   "TARGET_SHMEDIA"
4599   "bge  %1, %2, %0")
4600
4601 (define_expand "bgtu_media"
4602   [(set (pc)
4603         (if_then_else (gtu (match_operand:DI 1 "arith_reg_operand" "r")
4604                            (match_operand:DI 2 "arith_reg_operand" "r"))
4605                       (label_ref:DI (match_operand 0 "" ""))
4606                       (pc)))]
4607   "TARGET_SHMEDIA"
4608   "")
4609
4610 (define_insn "bgtu_media_i"
4611   [(set (pc)
4612         (if_then_else (gtu (match_operand:DI 1 "arith_reg_operand" "r")
4613                            (match_operand:DI 2 "arith_reg_operand" "r"))
4614                       (match_operand:DI 0 "target_operand" "b")
4615                       (pc)))]
4616   "TARGET_SHMEDIA"
4617   "bgtu %1, %2, %0")
4618
4619 (define_expand "bgeu_media"
4620   [(set (pc)
4621         (if_then_else (geu (match_operand:DI 1 "arith_reg_operand" "r")
4622                            (match_operand:DI 2 "arith_reg_operand" "r"))
4623                       (label_ref:DI (match_operand 0 "" ""))
4624                       (pc)))]
4625   "TARGET_SHMEDIA"
4626   "")
4627
4628 (define_insn "bgeu_media_i"
4629   [(set (pc)
4630         (if_then_else (geu (match_operand:DI 1 "arith_reg_operand" "r")
4631                            (match_operand:DI 2 "arith_reg_operand" "r"))
4632                       (match_operand:DI 0 "target_operand" "b")
4633                       (pc)))]
4634   "TARGET_SHMEDIA"
4635   "bgeu %1, %2, %0")
4636
4637 ;; These are only needed to make invert_jump() happy.
4638 (define_insn "*ble_media_i"
4639   [(set (pc)
4640         (if_then_else (le (match_operand:DI 1 "arith_reg_operand" "r")
4641                           (match_operand:DI 2 "arith_reg_operand" "r"))
4642                       (match_operand:DI 0 "target_operand" "b")
4643                       (pc)))]
4644   "TARGET_SHMEDIA"
4645   "bge  %2, %1, %0")
4646
4647 (define_insn "*blt_media_i"
4648   [(set (pc)
4649         (if_then_else (lt (match_operand:DI 1 "arith_reg_operand" "r")
4650                           (match_operand:DI 2 "arith_reg_operand" "r"))
4651                       (match_operand:DI 0 "target_operand" "b")
4652                       (pc)))]
4653   "TARGET_SHMEDIA"
4654   "bgt  %2, %1, %0")
4655
4656 (define_insn "*bleu_media_i"
4657   [(set (pc)
4658         (if_then_else (leu (match_operand:DI 1 "arith_reg_operand" "r")
4659                            (match_operand:DI 2 "arith_reg_operand" "r"))
4660                       (match_operand:DI 0 "target_operand" "b")
4661                       (pc)))]
4662   "TARGET_SHMEDIA"
4663   "bgeu %2, %1, %0")
4664
4665 (define_insn "*bltu_media_i"
4666   [(set (pc)
4667         (if_then_else (ltu (match_operand:DI 1 "arith_reg_operand" "r")
4668                            (match_operand:DI 2 "arith_reg_operand" "r"))
4669                       (match_operand:DI 0 "target_operand" "b")
4670                       (pc)))]
4671   "TARGET_SHMEDIA"
4672   "bgtu %2, %1, %0")
4673
4674 (define_expand "beq"
4675   [(set (pc)
4676         (if_then_else (ne (reg:SI T_REG) (const_int 0))
4677                       (label_ref (match_operand 0 "" ""))
4678                       (pc)))]
4679   ""
4680   "
4681 {
4682   if (TARGET_SHMEDIA)
4683     {
4684       if (GET_MODE (sh_compare_op0) != DImode)
4685         {
4686           rtx tmp = gen_reg_rtx (DImode);
4687
4688           emit_insn (gen_seq (tmp));
4689           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
4690           DONE;
4691         }
4692
4693       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4694       emit_jump_insn (gen_beq_media (operands[0],
4695                                      sh_compare_op0, sh_compare_op1));
4696       DONE;
4697     }
4698
4699   from_compare (operands, EQ);
4700 }")
4701
4702 (define_expand "bne"
4703   [(set (pc)
4704         (if_then_else (eq (reg:SI T_REG) (const_int 0))
4705                       (label_ref (match_operand 0 "" ""))
4706                       (pc)))]
4707   ""
4708   "
4709 {
4710   if (TARGET_SHMEDIA)
4711     {
4712       if (GET_MODE (sh_compare_op0) != DImode)
4713         {
4714           rtx tmp = gen_reg_rtx (DImode);
4715
4716           emit_insn (gen_seq (tmp));
4717           emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
4718           DONE;
4719         }
4720
4721       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4722       emit_jump_insn (gen_bne_media (operands[0],
4723                                      sh_compare_op0, sh_compare_op1));
4724       DONE;
4725     }
4726
4727   from_compare (operands, EQ);
4728 }")
4729
4730 (define_expand "bgt"
4731   [(set (pc)
4732         (if_then_else (ne (reg:SI T_REG) (const_int 0))
4733                       (label_ref (match_operand 0 "" ""))
4734                       (pc)))]
4735   ""
4736   "
4737 {
4738   if (TARGET_SHMEDIA)
4739     {
4740       if (GET_MODE (sh_compare_op0) != DImode)
4741         {
4742           rtx tmp = gen_reg_rtx (DImode);
4743
4744           emit_insn (gen_sgt (tmp));
4745           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
4746           DONE;
4747         }
4748
4749       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4750       sh_compare_op1 = force_reg (DImode, sh_compare_op1);
4751       emit_jump_insn (gen_bgt_media (operands[0],
4752                                      sh_compare_op0, sh_compare_op1));
4753       DONE;
4754     }
4755
4756   from_compare (operands, GT);
4757 }")
4758
4759 (define_expand "blt"
4760   [(set (pc)
4761         (if_then_else (eq (reg:SI T_REG) (const_int 0))
4762                       (label_ref (match_operand 0 "" ""))
4763                       (pc)))]
4764   ""
4765   "
4766 {
4767   if (TARGET_SHMEDIA)
4768     {
4769       if (GET_MODE (sh_compare_op0) != DImode)
4770         {
4771           rtx tmp = gen_reg_rtx (DImode);
4772
4773           emit_insn (gen_slt (tmp));
4774           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
4775           DONE;
4776         }
4777
4778       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4779       sh_compare_op1 = force_reg (DImode, sh_compare_op1);
4780       emit_jump_insn (gen_bgt_media (operands[0],
4781                                      sh_compare_op1, sh_compare_op0));
4782       DONE;
4783     }
4784
4785   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
4786     {
4787       rtx tmp = sh_compare_op0;
4788       sh_compare_op0 = sh_compare_op1;
4789       sh_compare_op1 = tmp;
4790       emit_insn (gen_bgt (operands[0]));
4791       DONE;
4792     }
4793   from_compare (operands, GE);
4794 }")
4795
4796 (define_expand "ble"
4797   [(set (pc)
4798         (if_then_else (eq (reg:SI T_REG) (const_int 0))
4799                       (label_ref (match_operand 0 "" ""))
4800                       (pc)))]
4801   ""
4802   "
4803 {
4804   if (TARGET_SHMEDIA)
4805     {
4806       if (GET_MODE (sh_compare_op0) != DImode)
4807         {
4808           rtx tmp = gen_reg_rtx (DImode);
4809
4810           emit_insn (gen_sle (tmp));
4811           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
4812           DONE;
4813         }
4814
4815       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4816       sh_compare_op1 = force_reg (DImode, sh_compare_op1);
4817       emit_jump_insn (gen_bge_media (operands[0],
4818                                      sh_compare_op1, sh_compare_op0));
4819       DONE;
4820     }
4821
4822   if (TARGET_SH3E
4823       && TARGET_IEEE
4824       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
4825     {
4826       rtx tmp = sh_compare_op0;
4827       sh_compare_op0 = sh_compare_op1;
4828       sh_compare_op1 = tmp;
4829       emit_insn (gen_bge (operands[0]));
4830       DONE;
4831     }
4832   from_compare (operands, GT);
4833 }")
4834
4835 (define_expand "bge"
4836   [(set (pc)
4837         (if_then_else (ne (reg:SI T_REG) (const_int 0))
4838                       (label_ref (match_operand 0 "" ""))
4839                       (pc)))]
4840   ""
4841   "
4842 {
4843   if (TARGET_SHMEDIA)
4844     {
4845       if (GET_MODE (sh_compare_op0) != DImode)
4846         {
4847           rtx tmp = gen_reg_rtx (DImode);
4848
4849           emit_insn (gen_sge (tmp));
4850           emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
4851           DONE;
4852         }
4853
4854       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4855       sh_compare_op1 = force_reg (DImode, sh_compare_op1);
4856       emit_jump_insn (gen_bge_media (operands[0],
4857                                      sh_compare_op0, sh_compare_op1));
4858       DONE;
4859     }
4860
4861   if (TARGET_SH3E
4862       && ! TARGET_IEEE
4863       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
4864     {
4865       rtx tmp = sh_compare_op0;
4866       sh_compare_op0 = sh_compare_op1;
4867       sh_compare_op1 = tmp;
4868       emit_insn (gen_ble (operands[0]));
4869       DONE;
4870     }
4871   from_compare (operands, GE);
4872 }")
4873
4874 (define_expand "bgtu"
4875   [(set (pc)
4876         (if_then_else (ne (reg:SI T_REG) (const_int 0))
4877                       (label_ref (match_operand 0 "" ""))
4878                       (pc)))]
4879   ""
4880   "
4881 {
4882   if (TARGET_SHMEDIA)
4883     {
4884       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4885       sh_compare_op1 = force_reg (DImode, sh_compare_op1);
4886       emit_jump_insn (gen_bgtu_media (operands[0],
4887                                       sh_compare_op0, sh_compare_op1));
4888       DONE;
4889     }
4890
4891   from_compare (operands, GTU);
4892 }")
4893
4894 (define_expand "bltu"
4895   [(set (pc)
4896         (if_then_else (eq (reg:SI T_REG) (const_int 0))
4897                       (label_ref (match_operand 0 "" ""))
4898                       (pc)))]
4899   ""
4900   "
4901 {
4902   if (TARGET_SHMEDIA)
4903     {
4904       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4905       sh_compare_op1 = force_reg (DImode, sh_compare_op1);
4906       emit_jump_insn (gen_bgtu_media (operands[0],
4907                                       sh_compare_op1, sh_compare_op0));
4908       DONE;
4909     }
4910
4911   from_compare (operands, GEU);
4912 }")
4913
4914 (define_expand "bgeu"
4915   [(set (pc)
4916         (if_then_else (ne (reg:SI T_REG) (const_int 0))
4917                       (label_ref (match_operand 0 "" ""))
4918                       (pc)))]
4919   ""
4920   "
4921 {
4922   if (TARGET_SHMEDIA)
4923     {
4924       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4925       sh_compare_op1 = force_reg (DImode, sh_compare_op1);
4926       emit_jump_insn (gen_bgeu_media (operands[0],
4927                                       sh_compare_op0, sh_compare_op1));
4928       DONE;
4929     }
4930
4931   from_compare (operands, GEU);
4932 }")
4933
4934 (define_expand "bleu"
4935   [(set (pc)
4936         (if_then_else (eq (reg:SI T_REG) (const_int 0))
4937                       (label_ref (match_operand 0 "" ""))
4938                       (pc)))]
4939   ""
4940   "
4941 {
4942   if (TARGET_SHMEDIA)
4943     {
4944       sh_compare_op0 = force_reg (DImode, sh_compare_op0);
4945       sh_compare_op1 = force_reg (DImode, sh_compare_op1);
4946       emit_jump_insn (gen_bgeu_media (operands[0],
4947                                       sh_compare_op1, sh_compare_op0));
4948       DONE;
4949     }
4950
4951   from_compare (operands, GTU);
4952 }")
4953
4954 (define_expand "bunordered"
4955   [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3)))
4956    (set (pc)
4957         (if_then_else (ne (match_dup 1) (const_int 0))
4958                       (label_ref:DI (match_operand 0 "" ""))
4959                       (pc)))]
4960   "TARGET_SHMEDIA"
4961   "
4962 {
4963   operands[1] = gen_reg_rtx (DImode);
4964   operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
4965   operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
4966 }")
4967 \f
4968 ;; ------------------------------------------------------------------------
4969 ;; Jump and linkage insns
4970 ;; ------------------------------------------------------------------------
4971
4972 (define_insn "jump_compact"
4973   [(set (pc)
4974         (label_ref (match_operand 0 "" "")))]
4975   "TARGET_SH1"
4976   "*
4977 {
4978   /* The length is 16 if the delay slot is unfilled.  */
4979   if (get_attr_length(insn) > 4)
4980     return output_far_jump(insn, operands[0]);
4981   else
4982     return   \"bra      %l0%#\";
4983 }"
4984   [(set_attr "type" "jump")
4985    (set_attr "needs_delay_slot" "yes")])
4986
4987 (define_insn "jump_media"
4988   [(set (pc)
4989         (match_operand:DI 0 "target_operand" "b"))]
4990   "TARGET_SHMEDIA"
4991   "blink        %0, r63")
4992
4993 (define_expand "jump"
4994   [(set (pc)
4995         (label_ref (match_operand 0 "" "")))]
4996   ""
4997   "
4998 {
4999   if (TARGET_SH1)
5000     emit_insn (gen_jump_compact (operands[0]));
5001   else if (TARGET_SHMEDIA)
5002     {
5003       if (reload_in_progress || reload_completed)
5004         FAIL;
5005       emit_insn (gen_jump_media (gen_rtx_LABEL_REF (DImode, operands[0])));
5006     }
5007   DONE;
5008 }")
5009
5010 (define_insn "force_mode_for_call"
5011   [(use (reg:PSI FPSCR_REG))]
5012   "TARGET_SHCOMPACT"
5013   ""
5014   [(set_attr "length" "0")
5015    (set (attr "fp_mode")
5016         (if_then_else (eq_attr "fpu_single" "yes")
5017                       (const_string "single") (const_string "double")))])
5018
5019 (define_insn "calli"
5020   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5021          (match_operand 1 "" ""))
5022    (use (reg:PSI FPSCR_REG))
5023    (clobber (reg:SI PR_REG))]
5024   "TARGET_SH1"
5025   "jsr  @%0%#"
5026   [(set_attr "type" "call")
5027    (set (attr "fp_mode")
5028         (if_then_else (eq_attr "fpu_single" "yes")
5029                       (const_string "single") (const_string "double")))
5030    (set_attr "needs_delay_slot" "yes")])
5031
5032 ;; This is a pc-rel call, using bsrf, for use with PIC.
5033
5034 (define_insn "calli_pcrel"
5035   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5036          (match_operand 1 "" ""))
5037    (use (reg:PSI FPSCR_REG))
5038    (use (reg:SI PIC_REG))
5039    (use (match_operand 2 "" ""))
5040    (clobber (reg:SI PR_REG))]
5041   "TARGET_SH2"
5042   "bsrf %0\\n%O2:%#"
5043   [(set_attr "type" "call")
5044    (set (attr "fp_mode")
5045         (if_then_else (eq_attr "fpu_single" "yes")
5046                       (const_string "single") (const_string "double")))
5047    (set_attr "needs_delay_slot" "yes")])
5048
5049 (define_insn_and_split "call_pcrel"
5050   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
5051          (match_operand 1 "" ""))
5052    (use (reg:PSI FPSCR_REG))
5053    (use (reg:SI PIC_REG))
5054    (clobber (reg:SI PR_REG))
5055    (clobber (match_scratch:SI 2 "=r"))]
5056   "TARGET_SH2"
5057   "#"
5058   "reload_completed"
5059   [(const_int 0)]
5060   "
5061 {
5062   rtx lab = gen_call_site ();
5063
5064   if (SYMBOL_REF_FLAG (operands[0]))
5065     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
5066   else
5067     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
5068   emit_call_insn (gen_calli_pcrel (operands[2], operands[1], lab));
5069   DONE;
5070 }"
5071   [(set_attr "type" "call")
5072    (set (attr "fp_mode")
5073         (if_then_else (eq_attr "fpu_single" "yes")
5074                       (const_string "single") (const_string "double")))
5075    (set_attr "needs_delay_slot" "yes")])
5076
5077 (define_insn "call_compact"
5078   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5079          (match_operand 1 "" ""))
5080    (match_operand 2 "immediate_operand" "n")
5081    (use (reg:SI R0_REG))
5082    (use (reg:SI R1_REG))
5083    (use (reg:PSI FPSCR_REG))
5084    (clobber (reg:SI PR_REG))]
5085   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5086   "jsr  @%0%#"
5087   [(set_attr "type" "call")
5088    (set (attr "fp_mode")
5089         (if_then_else (eq_attr "fpu_single" "yes")
5090                       (const_string "single") (const_string "double")))
5091    (set_attr "needs_delay_slot" "yes")])
5092
5093 (define_insn "call_compact_rettramp"
5094   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5095          (match_operand 1 "" ""))
5096    (match_operand 2 "immediate_operand" "n")
5097    (use (reg:SI R0_REG))
5098    (use (reg:SI R1_REG))
5099    (use (reg:PSI FPSCR_REG))
5100    (clobber (reg:SI R10_REG))
5101    (clobber (reg:SI PR_REG))]
5102   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5103   "jsr  @%0%#"
5104   [(set_attr "type" "call")
5105    (set (attr "fp_mode")
5106         (if_then_else (eq_attr "fpu_single" "yes")
5107                       (const_string "single") (const_string "double")))
5108    (set_attr "needs_delay_slot" "yes")])
5109
5110 (define_insn "call_media"
5111   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "b"))
5112          (match_operand 1 "" ""))
5113    (clobber (reg:DI PR_MEDIA_REG))]
5114   "TARGET_SHMEDIA"
5115   "blink        %0, r18")
5116
5117 (define_insn "call_valuei"
5118   [(set (match_operand 0 "" "=rf")
5119         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5120               (match_operand 2 "" "")))
5121    (use (reg:PSI FPSCR_REG))
5122    (clobber (reg:SI PR_REG))]
5123   "TARGET_SH1"
5124   "jsr  @%1%#"
5125   [(set_attr "type" "call")
5126    (set (attr "fp_mode")
5127         (if_then_else (eq_attr "fpu_single" "yes")
5128                       (const_string "single") (const_string "double")))
5129    (set_attr "needs_delay_slot" "yes")])
5130
5131 (define_insn "call_valuei_pcrel"
5132   [(set (match_operand 0 "" "=rf")
5133         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5134               (match_operand 2 "" "")))
5135    (use (reg:PSI FPSCR_REG))
5136    (use (reg:SI PIC_REG))
5137    (use (match_operand 3 "" ""))
5138    (clobber (reg:SI PR_REG))]
5139   "TARGET_SH2"
5140   "bsrf %1\\n%O3:%#"
5141   [(set_attr "type" "call")
5142    (set (attr "fp_mode")
5143         (if_then_else (eq_attr "fpu_single" "yes")
5144                       (const_string "single") (const_string "double")))
5145    (set_attr "needs_delay_slot" "yes")])
5146
5147 (define_insn_and_split "call_value_pcrel"
5148   [(set (match_operand 0 "" "=rf")
5149         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
5150               (match_operand 2 "" "")))
5151    (use (reg:PSI FPSCR_REG))
5152    (use (reg:SI PIC_REG))
5153    (clobber (reg:SI PR_REG))
5154    (clobber (match_scratch:SI 3 "=r"))]
5155   "TARGET_SH2"
5156   "#"
5157   "reload_completed"
5158   [(const_int 0)]
5159   "
5160 {
5161   rtx lab = gen_call_site ();
5162
5163   if (SYMBOL_REF_FLAG (operands[1]))
5164     emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
5165   else
5166     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
5167   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
5168                                          operands[2], lab));
5169   DONE;
5170 }"
5171   [(set_attr "type" "call")
5172    (set (attr "fp_mode")
5173         (if_then_else (eq_attr "fpu_single" "yes")
5174                       (const_string "single") (const_string "double")))
5175    (set_attr "needs_delay_slot" "yes")])
5176
5177 (define_insn "call_value_compact"
5178   [(set (match_operand 0 "" "=rf")
5179         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5180               (match_operand 2 "" "")))
5181    (match_operand 3 "immediate_operand" "n")
5182    (use (reg:SI R0_REG))
5183    (use (reg:SI R1_REG))
5184    (use (reg:PSI FPSCR_REG))
5185    (clobber (reg:SI PR_REG))]
5186   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5187   "jsr  @%1%#"
5188   [(set_attr "type" "call")
5189    (set (attr "fp_mode")
5190         (if_then_else (eq_attr "fpu_single" "yes")
5191                       (const_string "single") (const_string "double")))
5192    (set_attr "needs_delay_slot" "yes")])
5193
5194 (define_insn "call_value_compact_rettramp"
5195   [(set (match_operand 0 "" "=rf")
5196         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5197               (match_operand 2 "" "")))
5198    (match_operand 3 "immediate_operand" "n")
5199    (use (reg:SI R0_REG))
5200    (use (reg:SI R1_REG))
5201    (use (reg:PSI FPSCR_REG))
5202    (clobber (reg:SI R10_REG))
5203    (clobber (reg:SI PR_REG))]
5204   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5205   "jsr  @%1%#"
5206   [(set_attr "type" "call")
5207    (set (attr "fp_mode")
5208         (if_then_else (eq_attr "fpu_single" "yes")
5209                       (const_string "single") (const_string "double")))
5210    (set_attr "needs_delay_slot" "yes")])
5211
5212 (define_insn "call_value_media"
5213   [(set (match_operand 0 "" "=rf")
5214         (call (mem:DI (match_operand:DI 1 "target_reg_operand" "b"))
5215               (match_operand 2 "" "")))
5216    (clobber (reg:DI PR_MEDIA_REG))]
5217   "TARGET_SHMEDIA"
5218   "blink        %1, r18")
5219
5220 (define_expand "call"
5221   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5222                             (match_operand 1 "" ""))
5223               (match_operand 2 "" "")
5224               (use (reg:PSI FPSCR_REG))
5225               (clobber (reg:SI PR_REG))])]
5226   ""
5227   "
5228 {
5229   if (TARGET_SHMEDIA)
5230     {
5231       operands[0] = XEXP (operands[0], 0);
5232       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
5233         {
5234           if (! SYMBOL_REF_FLAG (operands[0]))
5235             {
5236               rtx reg = gen_reg_rtx (Pmode);
5237               
5238               emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5239               operands[0] = reg;
5240             }
5241           else
5242             {
5243               operands[0] = gen_sym2PIC (operands[0]);
5244               PUT_MODE (operands[0], Pmode);
5245             }
5246         }
5247       if (GET_MODE (operands[0]) == SImode)
5248         {
5249           if (GET_CODE (operands[0]) == REG)
5250             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5251           else if (GET_CODE (operands[0]) == SUBREG)
5252             {
5253               operands[0] = SUBREG_REG (operands[0]);
5254               if (GET_MODE (operands[0]) != DImode)
5255                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5256             }
5257           else
5258             {
5259               operands[0] = shallow_copy_rtx (operands[0]);
5260               PUT_MODE (operands[0], DImode);
5261             }
5262         }
5263       if (! target_reg_operand (operands[0], DImode))
5264         operands[0] = copy_to_mode_reg (DImode, operands[0]);
5265       emit_call_insn (gen_call_media (operands[0], operands[1]));
5266       DONE;
5267     }
5268   else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
5269     {
5270       rtx cookie_rtx = operands[2];
5271       long cookie = INTVAL (cookie_rtx);
5272       rtx func = XEXP (operands[0], 0);
5273       rtx r0, r1;
5274
5275       if (flag_pic)
5276         {
5277           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5278             {
5279               rtx reg = gen_reg_rtx (Pmode);
5280
5281               emit_insn (gen_symGOTPLT2reg (reg, func));
5282               func = reg;
5283             }
5284           else
5285             func = legitimize_pic_address (func, Pmode, 0);
5286         }
5287
5288       r0 = gen_rtx_REG (SImode, R0_REG);
5289       r1 = gen_rtx_REG (SImode, R1_REG);
5290
5291       /* Since such a call function may use all call-clobbered
5292          registers, we force a mode switch earlier, so that we don't
5293          run out of registers when adjusting fpscr for the call.  */
5294       emit_insn (gen_force_mode_for_call ());
5295
5296       operands[0] = gen_rtx_SYMBOL_REF (SImode,
5297                                         \"__GCC_shcompact_call_trampoline\");
5298       if (flag_pic)
5299         {
5300           rtx reg = gen_reg_rtx (Pmode);
5301
5302           emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5303           operands[0] = reg;
5304         }
5305       operands[0] = force_reg (SImode, operands[0]);
5306
5307       emit_move_insn (r0, func);
5308       emit_move_insn (r1, cookie_rtx);
5309
5310       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5311         emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
5312                                                    operands[2]));
5313       else
5314         emit_call_insn (gen_call_compact (operands[0], operands[1],
5315                                           operands[2]));
5316
5317       DONE;
5318     }
5319   else if (TARGET_SHCOMPACT && flag_pic
5320            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
5321            && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
5322     {
5323       rtx reg = gen_reg_rtx (Pmode);
5324
5325       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
5326       XEXP (operands[0], 0) = reg;
5327     }
5328   if (flag_pic && TARGET_SH2
5329       && GET_CODE (operands[0]) == MEM
5330       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
5331     {
5332       emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
5333       DONE;
5334     }
5335   else
5336     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
5337
5338   emit_call_insn (gen_calli (operands[0], operands[1]));
5339   DONE;
5340 }")
5341
5342 (define_insn "call_pop_compact"
5343   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5344          (match_operand 1 "" ""))
5345    (match_operand 2 "immediate_operand" "n")
5346    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5347                                  (match_operand 3 "immediate_operand" "n")))
5348    (use (reg:SI R0_REG))
5349    (use (reg:SI R1_REG))
5350    (use (reg:PSI FPSCR_REG))
5351    (clobber (reg:SI PR_REG))]
5352   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5353   "jsr  @%0%#"
5354   [(set_attr "type" "call")
5355    (set (attr "fp_mode")
5356         (if_then_else (eq_attr "fpu_single" "yes")
5357                       (const_string "single") (const_string "double")))
5358    (set_attr "needs_delay_slot" "yes")])
5359
5360 (define_insn "call_pop_compact_rettramp"
5361   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
5362          (match_operand 1 "" ""))
5363    (match_operand 2 "immediate_operand" "n")
5364    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5365                                  (match_operand 3 "immediate_operand" "n")))
5366    (use (reg:SI R0_REG))
5367    (use (reg:SI R1_REG))
5368    (use (reg:PSI FPSCR_REG))
5369    (clobber (reg:SI R10_REG))
5370    (clobber (reg:SI PR_REG))]
5371   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
5372   "jsr  @%0%#"
5373   [(set_attr "type" "call")
5374    (set (attr "fp_mode")
5375         (if_then_else (eq_attr "fpu_single" "yes")
5376                       (const_string "single") (const_string "double")))
5377    (set_attr "needs_delay_slot" "yes")])
5378
5379 (define_expand "call_pop"
5380   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5381                     (match_operand 1 "" ""))
5382              (match_operand 2 "" "")
5383              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5384                                            (match_operand 3 "" "")))])]
5385   "TARGET_SHCOMPACT"
5386   "
5387 {
5388   if (operands[2] && INTVAL (operands[2]))
5389     {
5390       rtx cookie_rtx = operands[2];
5391       long cookie = INTVAL (cookie_rtx);
5392       rtx func = XEXP (operands[0], 0);
5393       rtx r0, r1;
5394
5395       if (flag_pic)
5396         {
5397           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5398             {
5399               rtx reg = gen_reg_rtx (Pmode);
5400
5401               emit_insn (gen_symGOTPLT2reg (reg, func));
5402               func = reg;
5403             }
5404           else
5405             func = legitimize_pic_address (func, Pmode, 0);
5406         }
5407
5408       r0 = gen_rtx_REG (SImode, R0_REG);
5409       r1 = gen_rtx_REG (SImode, R1_REG);
5410
5411       /* Since such a call function may use all call-clobbered
5412          registers, we force a mode switch earlier, so that we don't
5413          run out of registers when adjusting fpscr for the call.  */
5414       emit_insn (gen_force_mode_for_call ());
5415
5416       operands[0] = gen_rtx_SYMBOL_REF (SImode,
5417                                         \"__GCC_shcompact_call_trampoline\");
5418       if (flag_pic)
5419         {
5420           rtx reg = gen_reg_rtx (Pmode);
5421
5422           emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
5423           operands[0] = reg;
5424         }
5425       operands[0] = force_reg (SImode, operands[0]);
5426
5427       emit_move_insn (r0, func);
5428       emit_move_insn (r1, cookie_rtx);
5429
5430       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5431         emit_call_insn (gen_call_pop_compact_rettramp
5432                         (operands[0], operands[1], operands[2], operands[3]));
5433       else
5434         emit_call_insn (gen_call_pop_compact
5435                         (operands[0], operands[1], operands[2], operands[3]));
5436
5437       DONE;
5438     }
5439
5440   abort ();
5441 }")
5442
5443 (define_expand "call_value"
5444   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
5445                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
5446                                  (match_operand 2 "" "")))
5447               (match_operand 3 "" "")
5448               (use (reg:PSI FPSCR_REG))
5449               (clobber (reg:SI PR_REG))])]
5450   ""
5451   "
5452 {
5453   if (TARGET_SHMEDIA)
5454     {
5455       operands[1] = XEXP (operands[1], 0);
5456       if (flag_pic && GET_CODE (operands[1]) == SYMBOL_REF)
5457         {
5458           if (! SYMBOL_REF_FLAG (operands[1]))
5459             {
5460               rtx reg = gen_reg_rtx (Pmode);
5461               
5462               emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
5463               operands[1] = reg;
5464             }
5465           else
5466             {
5467               operands[1] = gen_sym2PIC (operands[1]);
5468               PUT_MODE (operands[1], Pmode);
5469             }
5470         }
5471       if (GET_MODE (operands[1]) == SImode)
5472         {
5473           if (GET_CODE (operands[1]) == REG)
5474             operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5475           else if (GET_CODE (operands[1]) == SUBREG)
5476             {
5477               operands[1] = SUBREG_REG (operands[1]);
5478               if (GET_MODE (operands[1]) != DImode)
5479                 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5480             }
5481           else
5482             {
5483               operands[1] = shallow_copy_rtx (operands[1]);
5484               PUT_MODE (operands[1], DImode);
5485             }
5486         }
5487       if (! target_reg_operand (operands[1], DImode))
5488         operands[1] = copy_to_mode_reg (DImode, operands[1]);
5489       emit_call_insn (gen_call_value_media (operands[0], operands[1],
5490                                             operands[2]));
5491       DONE;
5492     }
5493   else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
5494     {
5495       rtx cookie_rtx = operands[3];
5496       long cookie = INTVAL (cookie_rtx);
5497       rtx func = XEXP (operands[1], 0);
5498       rtx r0, r1;
5499
5500       if (flag_pic)
5501         {
5502           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5503             {
5504               rtx reg = gen_reg_rtx (Pmode);
5505
5506               emit_insn (gen_symGOTPLT2reg (reg, func));
5507               func = reg;
5508             }
5509           else
5510             func = legitimize_pic_address (func, Pmode, 0);
5511         }
5512
5513       r0 = gen_rtx_REG (SImode, R0_REG);
5514       r1 = gen_rtx_REG (SImode, R1_REG);
5515
5516       /* Since such a call function may use all call-clobbered
5517          registers, we force a mode switch earlier, so that we don't
5518          run out of registers when adjusting fpscr for the call.  */
5519       emit_insn (gen_force_mode_for_call ());
5520
5521       operands[1] = gen_rtx_SYMBOL_REF (SImode,
5522                                         \"__GCC_shcompact_call_trampoline\");
5523       if (flag_pic)
5524         {
5525           rtx reg = gen_reg_rtx (Pmode);
5526
5527           emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
5528           operands[1] = reg;
5529         }
5530       operands[1] = force_reg (SImode, operands[1]);
5531
5532       emit_move_insn (r0, func);
5533       emit_move_insn (r1, cookie_rtx);
5534
5535       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5536         emit_call_insn (gen_call_value_compact_rettramp (operands[0],
5537                                                          operands[1],
5538                                                          operands[2],
5539                                                          operands[3]));
5540       else
5541         emit_call_insn (gen_call_value_compact (operands[0], operands[1],
5542                                                 operands[2], operands[3]));
5543
5544       DONE;
5545     }
5546   else if (TARGET_SHCOMPACT && flag_pic
5547            && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
5548            && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
5549     {
5550       rtx reg = gen_reg_rtx (Pmode);
5551
5552       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
5553       XEXP (operands[1], 0) = reg;
5554     }
5555   if (flag_pic && TARGET_SH2
5556       && GET_CODE (operands[1]) == MEM
5557       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
5558     {
5559       emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
5560                                             operands[2]));
5561       DONE;
5562     }
5563   else
5564     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
5565
5566   emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
5567   DONE;
5568 }")
5569
5570 (define_insn "sibcalli"
5571   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
5572          (match_operand 1 "" ""))
5573    (use (reg:PSI FPSCR_REG))
5574    (return)]
5575   "TARGET_SH1"
5576   "jmp  @%0%#"
5577   [(set_attr "needs_delay_slot" "yes")
5578    (set (attr "fp_mode")
5579         (if_then_else (eq_attr "fpu_single" "yes")
5580                       (const_string "single") (const_string "double")))
5581    (set_attr "type" "jump_ind")])
5582
5583 (define_insn "sibcalli_pcrel"
5584   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
5585          (match_operand 1 "" ""))
5586    (use (match_operand 2 "" ""))
5587    (use (reg:PSI FPSCR_REG))
5588    (return)]
5589   "TARGET_SH2"
5590   "braf %0\\n%O2:%#"
5591   [(set_attr "needs_delay_slot" "yes")
5592    (set (attr "fp_mode")
5593         (if_then_else (eq_attr "fpu_single" "yes")
5594                       (const_string "single") (const_string "double")))
5595    (set_attr "type" "jump_ind")])
5596
5597 (define_insn_and_split "sibcall_pcrel"
5598   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
5599          (match_operand 1 "" ""))
5600    (use (reg:PSI FPSCR_REG))
5601    (clobber (match_scratch:SI 2 "=k"))
5602    (return)]
5603   "TARGET_SH2"
5604   "#"
5605   "reload_completed"
5606   [(const_int 0)]
5607   "
5608 {
5609   rtx lab = gen_call_site ();
5610   rtx call_insn;
5611
5612   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
5613   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
5614                                                   lab));
5615   SIBLING_CALL_P (call_insn) = 1;
5616   DONE;
5617 }"
5618   [(set_attr "needs_delay_slot" "yes")
5619    (set (attr "fp_mode")
5620         (if_then_else (eq_attr "fpu_single" "yes")
5621                       (const_string "single") (const_string "double")))
5622    (set_attr "type" "jump_ind")])
5623
5624 (define_insn "sibcall_compact"
5625   [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
5626          (match_operand 1 "" ""))
5627    (return)
5628    (use (match_operand 2 "register_operand" "z,x"))
5629    (use (reg:SI R1_REG))
5630    (use (reg:PSI FPSCR_REG))
5631    ;; We want to make sure the `x' above will only match MACH_REG
5632    ;; because sibcall_epilogue may clobber MACL_REG.
5633    (clobber (reg:SI MACL_REG))]
5634   "TARGET_SHCOMPACT"
5635   "@
5636         jmp     @%0%#
5637         jmp     @%0\\n  sts     %2, r0"
5638   [(set_attr "needs_delay_slot" "yes,no")
5639    (set_attr "length" "2,4")
5640    (set (attr "fp_mode") (const_string "single"))
5641    (set_attr "type" "jump_ind")])
5642
5643 (define_insn "sibcall_media"
5644   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k"))
5645          (match_operand 1 "" ""))
5646    (return)]
5647   "TARGET_SHMEDIA"
5648   "blink        %0, r63")
5649
5650 (define_expand "sibcall"
5651   [(parallel
5652     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
5653            (match_operand 1 "" ""))
5654      (match_operand 2 "" "")
5655      (use (reg:PSI FPSCR_REG))
5656      (return)])]
5657   ""
5658   "
5659 {
5660   if (TARGET_SHMEDIA)
5661     {
5662       operands[0] = XEXP (operands[0], 0);
5663       if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
5664         {
5665           if (! SYMBOL_REF_FLAG (operands[0]))
5666             {
5667               rtx reg = gen_reg_rtx (Pmode);
5668               
5669               /* We must not use GOTPLT for sibcalls, because PIC_REG
5670                  must be restored before the PLT code gets to run.  */
5671               emit_insn (gen_symGOT2reg (reg, operands[0]));
5672               operands[0] = reg;
5673             }
5674           else
5675             {
5676               operands[0] = gen_sym2PIC (operands[0]);
5677               PUT_MODE (operands[0], Pmode);
5678             }
5679         }
5680       if (GET_MODE (operands[0]) == SImode)
5681         {
5682           if (GET_CODE (operands[0]) == REG)
5683             operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5684           else if (GET_CODE (operands[0]) == SUBREG)
5685             {
5686               operands[0] = SUBREG_REG (operands[0]);
5687               if (GET_MODE (operands[0]) != DImode)
5688                 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5689             }
5690           else
5691             {
5692               operands[0] = shallow_copy_rtx (operands[0]);
5693               PUT_MODE (operands[0], DImode);
5694             }
5695         }
5696       if (! target_reg_operand (operands[0], DImode))
5697         operands[0] = copy_to_mode_reg (DImode, operands[0]);
5698       emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
5699       DONE;
5700     }
5701   else if (TARGET_SHCOMPACT && operands[2]
5702            && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
5703     {
5704       rtx cookie_rtx = operands[2];
5705       long cookie = INTVAL (cookie_rtx);
5706       rtx func = XEXP (operands[0], 0);
5707       rtx mach, r1;
5708
5709       if (flag_pic)
5710         {
5711           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5712             {
5713               rtx reg = gen_reg_rtx (Pmode);
5714
5715               emit_insn (gen_symGOT2reg (reg, func));
5716               func = reg;
5717             }
5718           else
5719             func = legitimize_pic_address (func, Pmode, 0);
5720         }
5721
5722       /* FIXME: if we could tell whether all argument registers are
5723          already taken, we could decide whether to force the use of
5724          MACH_REG or to stick to R0_REG.  Unfortunately, there's no
5725          simple way to tell.  We could use the CALL_COOKIE, but we
5726          can't currently tell a register used for regular argument
5727          passing from one that is unused.  If we leave it up to reload
5728          to decide which register to use, it seems to always choose
5729          R0_REG, which leaves no available registers in SIBCALL_REGS
5730          to hold the address of the trampoline.  */
5731       mach = gen_rtx_REG (SImode, MACH_REG);
5732       r1 = gen_rtx_REG (SImode, R1_REG);
5733
5734       /* Since such a call function may use all call-clobbered
5735          registers, we force a mode switch earlier, so that we don't
5736          run out of registers when adjusting fpscr for the call.  */
5737       emit_insn (gen_force_mode_for_call ());
5738
5739       operands[0] = gen_rtx_SYMBOL_REF (SImode,
5740                                         \"__GCC_shcompact_call_trampoline\");
5741       if (flag_pic)
5742         {
5743           rtx reg = gen_reg_rtx (Pmode);
5744
5745           emit_insn (gen_symGOT2reg (reg, operands[0]));
5746           operands[0] = reg;
5747         }
5748       operands[0] = force_reg (SImode, operands[0]);
5749
5750       /* We don't need a return trampoline, since the callee will
5751          return directly to the upper caller.  */
5752       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5753         {
5754           cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
5755           cookie_rtx = GEN_INT (cookie);
5756         }
5757
5758       emit_move_insn (mach, func);
5759       emit_move_insn (r1, cookie_rtx);
5760
5761       emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
5762       DONE;
5763     }
5764   else if (TARGET_SHCOMPACT && flag_pic
5765            && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
5766            && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
5767     {
5768       rtx reg = gen_reg_rtx (Pmode);
5769
5770       emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
5771       XEXP (operands[0], 0) = reg;
5772     }
5773   if (flag_pic && TARGET_SH2
5774       && GET_CODE (operands[0]) == MEM
5775       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
5776       /* The PLT needs the PIC register, but the epilogue would have
5777          to restore it, so we can only use PC-relative PIC calls for
5778          static functions.  */
5779       && SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
5780     {
5781       emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
5782       DONE;
5783     }
5784   else
5785     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
5786
5787   emit_call_insn (gen_sibcalli (operands[0], operands[1]));
5788   DONE;
5789 }")
5790
5791 (define_expand "sibcall_value"
5792   [(set (match_operand 0 "" "")
5793         (call (match_operand 1 "" "")
5794               (match_operand 2 "" "")))
5795    (match_operand 3 "" "")]
5796   ""
5797   "
5798 {
5799   emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
5800   DONE;
5801 }")
5802
5803 (define_insn "call_value_pop_compact"
5804   [(set (match_operand 0 "" "=rf")
5805         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5806               (match_operand 2 "" "")))
5807    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5808                                  (match_operand 4 "immediate_operand" "n")))
5809    (match_operand 3 "immediate_operand" "n")
5810    (use (reg:SI R0_REG))
5811    (use (reg:SI R1_REG))
5812    (use (reg:PSI FPSCR_REG))
5813    (clobber (reg:SI PR_REG))]
5814   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5815   "jsr  @%1%#"
5816   [(set_attr "type" "call")
5817    (set (attr "fp_mode")
5818         (if_then_else (eq_attr "fpu_single" "yes")
5819                       (const_string "single") (const_string "double")))
5820    (set_attr "needs_delay_slot" "yes")])
5821
5822 (define_insn "call_value_pop_compact_rettramp"
5823   [(set (match_operand 0 "" "=rf")
5824         (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5825               (match_operand 2 "" "")))
5826    (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5827                                  (match_operand 4 "immediate_operand" "n")))
5828    (match_operand 3 "immediate_operand" "n")
5829    (use (reg:SI R0_REG))
5830    (use (reg:SI R1_REG))
5831    (use (reg:PSI FPSCR_REG))
5832    (clobber (reg:SI R10_REG))
5833    (clobber (reg:SI PR_REG))]
5834   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
5835   "jsr  @%1%#"
5836   [(set_attr "type" "call")
5837    (set (attr "fp_mode")
5838         (if_then_else (eq_attr "fpu_single" "yes")
5839                       (const_string "single") (const_string "double")))
5840    (set_attr "needs_delay_slot" "yes")])
5841
5842 (define_expand "call_value_pop"
5843   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
5844                    (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
5845                                  (match_operand 2 "" "")))
5846               (match_operand 3 "" "")
5847               (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
5848                                             (match_operand 4 "" "")))])]
5849   "TARGET_SHCOMPACT"
5850   "
5851 {
5852   if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
5853     {
5854       rtx cookie_rtx = operands[3];
5855       long cookie = INTVAL (cookie_rtx);
5856       rtx func = XEXP (operands[1], 0);
5857       rtx r0, r1;
5858
5859       if (flag_pic)
5860         {
5861           if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
5862             {
5863               rtx reg = gen_reg_rtx (Pmode);
5864
5865               emit_insn (gen_symGOTPLT2reg (reg, func));
5866               func = reg;
5867             }
5868           else
5869             func = legitimize_pic_address (func, Pmode, 0);
5870         }
5871
5872       r0 = gen_rtx_REG (SImode, R0_REG);
5873       r1 = gen_rtx_REG (SImode, R1_REG);
5874
5875       /* Since such a call function may use all call-clobbered
5876          registers, we force a mode switch earlier, so that we don't
5877          run out of registers when adjusting fpscr for the call.  */
5878       emit_insn (gen_force_mode_for_call ());
5879
5880       operands[1] = gen_rtx_SYMBOL_REF (SImode,
5881                                         \"__GCC_shcompact_call_trampoline\");
5882       if (flag_pic)
5883         {
5884           rtx reg = gen_reg_rtx (Pmode);
5885
5886           emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
5887           operands[1] = reg;
5888         }
5889       operands[1] = force_reg (SImode, operands[1]);
5890
5891       emit_move_insn (r0, func);
5892       emit_move_insn (r1, cookie_rtx);
5893
5894       if (cookie & CALL_COOKIE_RET_TRAMP (1))
5895         emit_call_insn (gen_call_value_pop_compact_rettramp
5896                         (operands[0], operands[1], operands[2],
5897                          operands[3], operands[4]));
5898       else
5899         emit_call_insn (gen_call_value_pop_compact
5900                         (operands[0], operands[1], operands[2],
5901                          operands[3], operands[4]));
5902
5903       DONE;
5904     }
5905
5906   abort ();
5907 }")
5908
5909 (define_expand "sibcall_epilogue"
5910   [(return)]
5911   ""
5912   "
5913 {
5914   sh_expand_epilogue ();
5915   if (TARGET_SHCOMPACT)
5916     {
5917       rtx insn, set;
5918
5919       /* If epilogue clobbers r0, preserve it in macl.  */
5920       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5921         if ((set = single_set (insn))
5922             && GET_CODE (SET_DEST (set)) == REG
5923             && REGNO (SET_DEST (set)) == R0_REG)
5924           {
5925             rtx r0 = gen_rtx_REG (SImode, R0_REG);
5926             rtx tmp = gen_rtx_REG (SImode, MACL_REG);
5927             rtx i;
5928
5929             /* We can't tell at this point whether the sibcall is a
5930                sibcall_compact and, if it is, whether it uses r0 or
5931                mach as operand 2, so let the instructions that
5932                preserve r0 be optimized away if r0 turns out to be
5933                dead.  */
5934             i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
5935             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
5936                                                REG_NOTES (i));
5937             i = emit_move_insn (r0, tmp);
5938             REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
5939                                                REG_NOTES (i));
5940             break;
5941           }
5942     }
5943   DONE;
5944 }")
5945
5946 (define_insn "indirect_jump_compact"
5947   [(set (pc)
5948         (match_operand:SI 0 "arith_reg_operand" "r"))]
5949   "TARGET_SH1"
5950   "jmp  @%0%#"
5951   [(set_attr "needs_delay_slot" "yes")
5952    (set_attr "type" "jump_ind")])
5953
5954 (define_expand "indirect_jump"
5955   [(set (pc)
5956         (match_operand 0 "register_operand" ""))]
5957   ""
5958   "
5959 {
5960   if (TARGET_SHMEDIA && GET_MODE (operands[0]) == SImode)
5961     operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5962 }")
5963
5964 ;; The use of operand 1 / 2 helps us distinguish case table jumps
5965 ;; which can be present in structured code from indirect jumps which can not
5966 ;; be present in structured code.  This allows -fprofile-arcs to work.
5967
5968 ;; For SH1 processors.
5969 (define_insn "casesi_jump_1"
5970   [(set (pc)
5971         (match_operand:SI 0 "register_operand" "r"))
5972    (use (label_ref (match_operand 1 "" "")))]
5973   "TARGET_SH1"
5974   "jmp  @%0%#"
5975   [(set_attr "needs_delay_slot" "yes")
5976    (set_attr "type" "jump_ind")])
5977
5978 ;; For all later processors.
5979 (define_insn "casesi_jump_2"
5980   [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
5981                       (label_ref (match_operand 1 "" ""))))
5982    (use (label_ref (match_operand 2 "" "")))]
5983   "TARGET_SH2
5984    && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
5985   "braf %0%#"
5986   [(set_attr "needs_delay_slot" "yes")
5987    (set_attr "type" "jump_ind")])
5988
5989 (define_insn "casesi_jump_media"
5990   [(set (pc) (match_operand:DI 0 "target_reg_operand" "b"))
5991    (use (label_ref (match_operand 1 "" "")))]
5992   "TARGET_SHMEDIA"
5993   "blink        %0, r63")
5994   
5995 ;; Call subroutine returning any type.
5996 ;; ??? This probably doesn't work.
5997
5998 (define_expand "untyped_call"
5999   [(parallel [(call (match_operand 0 "" "")
6000                     (const_int 0))
6001               (match_operand 1 "" "")
6002               (match_operand 2 "" "")])]
6003   "TARGET_SH3E || TARGET_SHMEDIA"
6004   "
6005 {
6006   int i;
6007
6008   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
6009
6010   for (i = 0; i < XVECLEN (operands[2], 0); i++)
6011     {
6012       rtx set = XVECEXP (operands[2], 0, i);
6013       emit_move_insn (SET_DEST (set), SET_SRC (set));
6014     }
6015
6016   /* The optimizer does not know that the call sets the function value
6017      registers we stored in the result block.  We avoid problems by
6018      claiming that all hard registers are used and clobbered at this
6019      point.  */
6020   emit_insn (gen_blockage ());
6021
6022   DONE;
6023 }")
6024 \f
6025 ;; ------------------------------------------------------------------------
6026 ;; Misc insns
6027 ;; ------------------------------------------------------------------------
6028
6029 (define_insn "dect"
6030   [(set (reg:SI T_REG)
6031         (eq:SI (match_operand:SI 0 "arith_reg_operand" "+r") (const_int 1)))
6032    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
6033   "TARGET_SH2"
6034   "dt   %0"
6035   [(set_attr "type" "arith")])
6036
6037 (define_insn "nop"
6038   [(const_int 0)]
6039   ""
6040   "nop")
6041
6042 ;; Load address of a label. This is only generated by the casesi expand,
6043 ;; and by machine_dependent_reorg (fixing up fp moves).
6044 ;; This must use unspec, because this only works for labels that are
6045 ;; within range,
6046
6047 (define_insn "mova"
6048   [(set (reg:SI R0_REG)
6049         (unspec [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
6050   "TARGET_SH1"
6051   "mova %O0,r0"
6052   [(set_attr "in_delay_slot" "no")
6053    (set_attr "type" "arith")])
6054
6055 ;; machine_dependent_reorg() will make this a `mova'.
6056 (define_insn "mova_const"
6057   [(set (reg:SI R0_REG)
6058         (unspec [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
6059   "TARGET_SH1"
6060   "#"
6061   [(set_attr "in_delay_slot" "no")
6062    (set_attr "type" "arith")])
6063
6064 (define_expand "GOTaddr2picreg"
6065   [(set (reg:SI R0_REG)
6066         (unspec [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
6067                 UNSPEC_MOVA))
6068    (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
6069    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
6070   "" "
6071 {
6072   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
6073   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
6074
6075   if (TARGET_SH5)
6076     operands[1] = gen_datalabel_ref (operands[1]);
6077
6078   if (TARGET_SHMEDIA)
6079     {
6080       rtx tr = gen_rtx_REG (DImode, TR0_REG);
6081       rtx dipic = operands[0];
6082       rtx lab = gen_call_site ();
6083       rtx insn, equiv;
6084
6085       equiv = operands[1];
6086       operands[1] = gen_rtx_MINUS (DImode,
6087                                    operands[1],
6088                                    gen_rtx_CONST
6089                                    (DImode,
6090                                     gen_rtx_MINUS (DImode,
6091                                                    gen_rtx_CONST (DImode,
6092                                                                   lab),
6093                                                    pc_rtx)));
6094       operands[1] = gen_sym2PIC (operands[1]);
6095       PUT_MODE (operands[1], DImode);
6096
6097       if (GET_MODE (dipic) != DImode)
6098         dipic = gen_rtx_SUBREG (DImode, dipic, 0);
6099
6100       if (TARGET_SHMEDIA64)
6101         emit_insn (gen_movdi_const (dipic, operands[1]));
6102       else
6103         emit_insn (gen_movdi_const_32bit (dipic, operands[1]));
6104
6105       emit_insn (gen_ptrel (tr, dipic, lab));
6106
6107       if (GET_MODE (operands[0]) != GET_MODE (tr))
6108         tr = gen_rtx_SUBREG (GET_MODE (operands[0]), tr, 0);
6109
6110       insn = emit_move_insn (operands[0], tr);
6111       
6112       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
6113                                             REG_NOTES (insn));
6114
6115       DONE;
6116     }
6117 }
6118 ")
6119
6120 ;; When generating PIC, we must match label_refs especially, because
6121 ;; they do not satisfy LEGITIMATE_PIC_OPERAND_P(), and we don't want
6122 ;; them to do, because they can't be loaded directly into
6123 ;; non-branch-target registers.
6124 (define_insn "*pt"
6125   [(set (match_operand:DI 0 "target_reg_operand" "=b*k")
6126         (match_operand:DI 1 "" "T"))]
6127   "TARGET_SHMEDIA && flag_pic
6128    && EXTRA_CONSTRAINT_T (operands[1])"
6129   "pt   %1, %0"
6130   [(set_attr "type" "pt")
6131    (set_attr "length" "*")])
6132
6133 (define_insn "*ptb"
6134   [(set (match_operand:DI 0 "target_reg_operand" "=b*k")
6135         (const:DI (unspec:DI [(match_operand:DI 1 "" "T")]
6136                              UNSPEC_DATALABEL)))]
6137   "TARGET_SHMEDIA && flag_pic
6138    && EXTRA_CONSTRAINT_T (operands[1])"
6139   "ptb/u        datalabel %1, %0"
6140   [(set_attr "type" "pt")
6141    (set_attr "length" "*")])
6142
6143 (define_insn "ptrel"
6144   [(set (match_operand:DI 0 "target_reg_operand" "=bk")
6145         (plus (match_operand:DI 1 "register_operand" "r")
6146               (pc)))
6147    (match_operand:DI 2 "" "")]
6148   "TARGET_SHMEDIA"
6149   "%O2: ptrel/u %1, %0"
6150   [(set_attr "type" "ptabs")])
6151
6152 (define_expand "builtin_setjmp_receiver"
6153   [(match_operand 0 "" "")]
6154   "flag_pic"
6155   "
6156 {
6157   emit_insn (gen_GOTaddr2picreg ());
6158   DONE;
6159 }")
6160
6161 (define_expand "call_site"
6162   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
6163   "TARGET_SH1"
6164   "
6165 {
6166   static HOST_WIDE_INT i = 0;
6167   operands[0] = GEN_INT (i);
6168   i++;
6169 }")
6170
6171 (define_expand "sym_label2reg"
6172   [(set (match_operand:SI 0 "" "")
6173         (const:SI (minus:SI
6174                    (const:SI
6175                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
6176                    (const:SI
6177                     (plus:SI
6178                      (match_operand:SI 2 "" "")
6179                      (const_int 2))))))]
6180   "TARGET_SH1" "")
6181
6182 (define_expand "symGOT_load"
6183   [(set (match_dup 2) (match_operand 1 "" ""))
6184    (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
6185    (set (match_operand 0 "" "") (mem (match_dup 3)))]
6186   ""
6187   "
6188 {
6189   rtx insn;
6190
6191   operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6192   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
6193
6194   if (TARGET_SHMEDIA)
6195     {
6196       rtx reg = operands[2];
6197       
6198       if (GET_MODE (reg) != DImode)
6199         reg = gen_rtx_SUBREG (DImode, reg, 0);
6200       
6201       if (flag_pic > 1)
6202         emit_insn (gen_movdi_const_32bit (reg, operands[1]));
6203       else
6204         emit_insn (gen_movdi_const_16bit (reg, operands[1]));
6205     }
6206   else
6207     emit_move_insn (operands[2], operands[1]);
6208
6209   emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
6210                                              operands[2],
6211                                              gen_rtx_REG (Pmode, PIC_REG)));
6212
6213   insn = emit_move_insn (operands[0], gen_rtx_MEM (Pmode, operands[3]));
6214
6215   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, XVECEXP (XEXP (operands[1],
6216                                                                   0), 0, 0),
6217                                         REG_NOTES (insn));
6218   
6219   DONE;
6220 }")
6221
6222 (define_expand "sym2GOT"
6223   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
6224   ""
6225   "")
6226
6227 (define_expand "symGOT2reg"
6228   [(match_operand 0 "" "") (match_operand 1 "" "")]
6229   ""
6230   "
6231 {
6232   rtx gotsym, insn;
6233
6234   gotsym = gen_sym2GOT (operands[1]);
6235   PUT_MODE (gotsym, Pmode);
6236   insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
6237
6238   RTX_UNCHANGING_P (SET_SRC (PATTERN (insn))) = 1;
6239
6240   DONE;
6241 }")
6242
6243 (define_expand "sym2GOTPLT"
6244   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTPLT))]
6245   ""
6246   "")
6247
6248 (define_expand "symGOTPLT2reg"
6249   [(match_operand 0 "" "") (match_operand 1 "" "")]
6250   ""
6251   "
6252 {
6253   emit_insn (gen_symGOT_load (operands[0], gen_sym2GOTPLT (operands[1])));
6254   DONE;
6255 }")
6256
6257 (define_expand "sym2GOTOFF"
6258   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
6259   ""
6260   "")
6261
6262 (define_expand "symGOTOFF2reg"
6263   [(match_operand 0 "" "") (match_operand 1 "" "")]
6264   ""
6265   "
6266 {
6267   rtx gotoffsym, insn;
6268   rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
6269
6270   gotoffsym = gen_sym2GOTOFF (operands[1]);
6271   PUT_MODE (gotoffsym, Pmode);
6272   emit_move_insn (t, gotoffsym);
6273   insn = emit_move_insn (operands[0],
6274                          gen_rtx_PLUS (Pmode, t,
6275                                        gen_rtx_REG (Pmode, PIC_REG)));
6276
6277   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
6278                                         REG_NOTES (insn));
6279
6280   DONE;
6281 }")
6282
6283 (define_expand "symPLT_label2reg"
6284   [(set (match_operand:SI 0 "" "")
6285         (const:SI (minus:SI
6286                    (const:SI
6287                     (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
6288                    (const:SI
6289                     (minus:SI
6290                      (const:SI (plus:SI
6291                                 (match_operand:SI 2 "" "")
6292                                 (const_int 2)))
6293                      (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
6294    ;; Even though the PIC register is not really used by the call
6295    ;; sequence in which this is expanded, the PLT code assumes the PIC
6296    ;; register is set, so we must not skip its initialization.  Since
6297    ;; we only use this expand as part of calling sequences, and never
6298    ;; to take the address of a function, this is the best point to
6299    ;; insert the (use).  Using the PLT to take the address of a
6300    ;; function would be wrong, not only because the PLT entry could
6301    ;; then be called from a function that doesn't initialize the PIC
6302    ;; register to the proper GOT, but also because pointers to the
6303    ;; same function might not compare equal, should they be set by
6304    ;; different shared libraries.
6305    (use (reg:SI PIC_REG))]
6306   "TARGET_SH1"
6307   "")
6308
6309 (define_expand "sym2PIC"
6310   [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
6311   ""
6312   "")
6313
6314 ;; case instruction for switch statements.
6315
6316 ;; Operand 0 is index
6317 ;; operand 1 is the minimum bound
6318 ;; operand 2 is the maximum bound - minimum bound + 1
6319 ;; operand 3 is CODE_LABEL for the table;
6320 ;; operand 4 is the CODE_LABEL to go to if index out of range.
6321
6322 (define_expand "casesi"
6323   [(match_operand:SI 0 "arith_reg_operand" "")
6324    (match_operand:SI 1 "arith_reg_operand" "")
6325    (match_operand:SI 2 "arith_reg_operand" "")
6326    (match_operand 3 "" "") (match_operand 4 "" "")]
6327   ""
6328   "
6329 {
6330   rtx reg = gen_reg_rtx (SImode);
6331   rtx reg2 = gen_reg_rtx (SImode);
6332   if (TARGET_SHMEDIA)
6333     {
6334       rtx reg = gen_reg_rtx (DImode);
6335       rtx reg2 = gen_reg_rtx (DImode);
6336       rtx reg3 = gen_reg_rtx (DImode);
6337       rtx reg4 = gen_reg_rtx (DImode);
6338       rtx reg5 = gen_reg_rtx (DImode);
6339
6340       operands[0] = convert_modes (DImode, SImode, operands[0], 0);
6341       operands[1] = convert_modes (DImode, SImode, operands[1], 0);
6342       operands[2] = convert_modes (DImode, SImode, operands[2], 1);
6343
6344       emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
6345       emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
6346       emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
6347       emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
6348       emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
6349                                                (DImode, operands[3])));
6350       emit_insn (gen_casesi_load_media (reg4, reg3, reg2, operands[3]));
6351       emit_move_insn (reg5, gen_rtx_PLUS (DImode, reg3, reg4));
6352       emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
6353       emit_barrier ();
6354       DONE;
6355     }
6356   operands[1] = copy_to_mode_reg (SImode, operands[1]);
6357   operands[2] = copy_to_mode_reg (SImode, operands[2]);
6358   /* If optimizing, casesi_worker depends on the mode of the instruction
6359      before label it 'uses' - operands[3].  */
6360   emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
6361                            reg));
6362   emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
6363   if (TARGET_SH2)
6364     emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
6365   else
6366     emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
6367   /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
6368      operands[3], but to lab.  We will fix this up in
6369      machine_dependent_reorg.  */
6370   emit_barrier ();
6371   DONE;
6372 }")
6373
6374 (define_expand "casesi_0"
6375   [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
6376    (set (match_dup 4) (minus:SI (match_dup 4)
6377                                 (match_operand:SI 1 "arith_operand" "")))
6378    (set (reg:SI T_REG)
6379         (gtu:SI (match_dup 4)
6380                 (match_operand:SI 2 "arith_reg_operand" "")))
6381    (set (pc)
6382         (if_then_else (ne (reg:SI T_REG)
6383                           (const_int 0))
6384                       (label_ref (match_operand 3 "" ""))
6385                       (pc)))]
6386   "TARGET_SH1"
6387   "")
6388
6389 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
6390 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
6391 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
6392
6393 (define_insn "casesi_worker_0"
6394   [(set (match_operand:SI 0 "register_operand" "=r,r")
6395         (unspec:SI [(match_operand 1 "register_operand" "0,r")
6396                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6397    (clobber (match_scratch:SI 3 "=X,1"))
6398    (clobber (match_scratch:SI 4 "=&z,z"))]
6399   "TARGET_SH1"
6400   "#")
6401
6402 (define_split
6403   [(set (match_operand:SI 0 "register_operand" "")
6404         (unspec [(match_operand 1 "register_operand" "")
6405                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6406    (clobber (match_scratch:SI 3 ""))
6407    (clobber (match_scratch:SI 4 ""))]
6408   "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
6409   [(set (reg:SI R0_REG) (unspec [(label_ref (match_dup 2))] UNSPEC_MOVA))
6410    (parallel [(set (match_dup 0)
6411               (unspec [(reg:SI R0_REG) (match_dup 1)
6412                        (label_ref (match_dup 2))] UNSPEC_CASESI))
6413               (clobber (match_dup 3))])
6414    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
6415   "LABEL_NUSES (operands[2])++;")
6416
6417 (define_split
6418   [(set (match_operand:SI 0 "register_operand" "")
6419         (unspec:SI [(match_operand 1 "register_operand" "")
6420                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6421    (clobber (match_scratch:SI 3 ""))
6422    (clobber (match_scratch:SI 4 ""))]
6423   "TARGET_SH2 && reload_completed"
6424   [(set (reg:SI R0_REG) (unspec [(label_ref (match_dup 2))] UNSPEC_MOVA))
6425    (parallel [(set (match_dup 0)
6426               (unspec:SI [(reg:SI R0_REG) (match_dup 1)
6427                        (label_ref (match_dup 2))] UNSPEC_CASESI))
6428               (clobber (match_dup 3))])]
6429   "LABEL_NUSES (operands[2])++;")
6430
6431 (define_insn "*casesi_worker"
6432   [(set (match_operand:SI 0 "register_operand" "=r,r")
6433         (unspec [(reg:SI R0_REG) (match_operand 1 "register_operand" "0,r")
6434                  (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
6435    (clobber (match_scratch:SI 3 "=X,1"))]
6436   "TARGET_SH1"
6437   "*
6438 {
6439   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
6440
6441   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
6442     abort ();
6443
6444   switch (GET_MODE (diff_vec))
6445     {
6446     case SImode:
6447       return \"shll2    %1\;mov.l       @(r0,%1),%0\";
6448     case HImode:
6449       return \"add      %1,%1\;mov.w    @(r0,%1),%0\";
6450     case QImode:
6451       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
6452         return \"mov.b  @(r0,%1),%0\;extu.b     %0,%0\";
6453       return \"mov.b    @(r0,%1),%0\";
6454     default:
6455       abort ();
6456     }
6457 }"
6458   [(set_attr "length" "4")])
6459
6460 (define_insn "casesi_shift_media"
6461   [(set (match_operand 0 "arith_reg_operand" "=r")
6462         (ashift (match_operand 1 "arith_reg_operand" "r")
6463                 (unspec [(label_ref:DI (match_operand 2 "" ""))] 2)))]
6464   "TARGET_SHMEDIA"
6465   "*
6466 {
6467   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
6468
6469   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
6470     abort ();
6471
6472   switch (GET_MODE (diff_vec))
6473     {
6474     case SImode:
6475       return \"shlli    %1, 2, %0\";
6476     case HImode:
6477       return \"shlli    %1, 1, %0\";
6478     case QImode:
6479       if (rtx_equal_p (operands[0], operands[1]))
6480         return \"\";
6481       return \"add      %1, r63, %0\";
6482     default:
6483       abort ();
6484     }
6485 }")
6486
6487 (define_insn "casesi_load_media"
6488   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
6489         (mem:DI (unspec [(match_operand 1 "arith_reg_operand" "r")
6490                          (match_operand 2 "arith_reg_operand" "r")
6491                          (label_ref:DI (match_operand 3 "" ""))] 2)))]
6492   "TARGET_SHMEDIA"
6493   "*
6494 {
6495   rtx diff_vec = PATTERN (next_real_insn (operands[3]));
6496
6497   if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
6498     abort ();
6499
6500   switch (GET_MODE (diff_vec))
6501     {
6502     case SImode:
6503       return \"ldx.l    %1, %2, %0\";
6504     case HImode:
6505 #if 0
6506       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
6507         return \"ldx.uw %1, %2, %0\";
6508 #endif
6509       return \"ldx.w    %1, %2, %0\";
6510     case QImode:
6511       if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
6512         return \"ldx.ub %1, %2, %0\";
6513       return \"ldx.b    %1, %2, %0\";
6514     default:
6515       abort ();
6516     }
6517 }")
6518
6519 (define_expand "return"
6520   [(return)]
6521   "reload_completed && ! sh_need_epilogue ()"
6522   "
6523 {
6524   if (TARGET_SHMEDIA)
6525     {
6526       emit_jump_insn (gen_return_media ());
6527       DONE;
6528     }
6529
6530   if (TARGET_SHCOMPACT
6531       && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
6532     {
6533       emit_jump_insn (gen_shcompact_return_tramp ());
6534       DONE;
6535     }
6536 }")
6537
6538 (define_insn "*return_i"
6539   [(return)]
6540   "TARGET_SH1 && ! (TARGET_SHCOMPACT
6541                     && (current_function_args_info.call_cookie
6542                         & CALL_COOKIE_RET_TRAMP (1)))
6543    && reload_completed"
6544   "%@   %#"
6545   [(set_attr "type" "return")
6546    (set_attr "needs_delay_slot" "yes")])
6547
6548 (define_expand "shcompact_return_tramp"
6549   [(return)]
6550   "TARGET_SHCOMPACT
6551    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
6552   "
6553 {
6554   rtx reg = gen_rtx_REG (Pmode, R0_REG);
6555   rtx sym = gen_rtx_SYMBOL_REF (Pmode,
6556                                 \"__GCC_shcompact_return_trampoline\");
6557
6558   if (flag_pic)
6559     emit_insn (gen_symGOTPLT2reg (reg, sym));
6560   else
6561     emit_move_insn (reg, sym);
6562
6563   emit_jump_insn (gen_shcompact_return_tramp_i ());
6564   DONE;
6565 }")
6566
6567 (define_insn "shcompact_return_tramp_i"
6568   [(parallel [(return) (use (reg:SI R0_REG))])]
6569   "TARGET_SHCOMPACT
6570    && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
6571   "jmp  @r0%#"
6572   [(set_attr "type" "jump_ind")
6573    (set_attr "needs_delay_slot" "yes")])
6574
6575 (define_insn "return_media_i"
6576   [(parallel [(return) (use (match_operand:DI 0 "target_reg_operand" "k"))])]
6577   "TARGET_SHMEDIA && reload_completed"
6578   "blink        %0, r63")
6579
6580 (define_expand "return_media"
6581   [(return)]
6582   "TARGET_SHMEDIA && reload_completed"
6583   "
6584 {
6585   int tr_regno = sh_media_register_for_return ();
6586   rtx tr;
6587
6588   if (tr_regno < 0)
6589     {
6590       rtx r18 = gen_rtx_REG (DImode, PR_MEDIA_REG);
6591
6592       tr_regno = TR0_REG;
6593       tr = gen_rtx_REG (DImode, tr_regno);
6594       emit_move_insn (tr, r18);
6595     }
6596   else
6597     tr = gen_rtx_REG (DImode, tr_regno);
6598
6599   emit_jump_insn (gen_return_media_i (tr));
6600   DONE;
6601 }")
6602
6603 (define_insn "shcompact_preserve_incoming_args"
6604   [(set (match_operand 0 "register_operand" "+r")
6605         (unspec [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
6606   "TARGET_SHCOMPACT"
6607   ""
6608   [(set_attr "length" "0")])
6609
6610 (define_insn "shcompact_incoming_args"
6611   [(set (reg:SI R2_REG) (unspec [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
6612    (set (reg:SI R3_REG) (unspec [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
6613    (set (reg:SI R4_REG) (unspec [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
6614    (set (reg:SI R5_REG) (unspec [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
6615    (set (reg:SI R6_REG) (unspec [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
6616    (set (reg:SI R7_REG) (unspec [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
6617    (set (reg:SI R8_REG) (unspec [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
6618    (set (reg:SI R9_REG) (unspec [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
6619    (set (mem:BLK (reg:SI MACL_REG))
6620         (unspec [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
6621    (use (reg:SI R0_REG))
6622    (clobber (reg:SI R0_REG))
6623    (clobber (reg:SI MACL_REG))
6624    (clobber (reg:SI MACH_REG))
6625    (clobber (reg:SI PR_REG))]
6626   "TARGET_SHCOMPACT"
6627   "jsr  @r0%#"
6628   [(set_attr "needs_delay_slot" "yes")])
6629
6630 (define_insn "shmedia_save_restore_regs_compact"
6631   [(set (reg:SI SP_REG)
6632         (plus:SI (reg:SI SP_REG)
6633                  (match_operand:SI 0 "immediate_operand" "i")))
6634    (use (reg:SI R0_REG))
6635    (clobber (reg:SI PR_REG))]
6636   "TARGET_SHCOMPACT
6637    && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
6638        || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
6639   "jsr @r0%#"
6640   [(set_attr "needs_delay_slot" "yes")])
6641
6642 (define_expand "prologue"
6643   [(const_int 0)]
6644   ""
6645   "sh_expand_prologue (); DONE;")
6646
6647 (define_expand "epilogue"
6648   [(return)]
6649   ""
6650   "
6651 {
6652   sh_expand_epilogue ();
6653   emit_jump_insn (gen_return ());
6654   DONE;
6655 }")
6656
6657 (define_insn "blockage"
6658   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
6659   ""
6660   ""
6661   [(set_attr "length" "0")])
6662 \f
6663 ;; ------------------------------------------------------------------------
6664 ;; Scc instructions
6665 ;; ------------------------------------------------------------------------
6666
6667 (define_insn "movt"
6668   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6669         (eq:SI (reg:SI T_REG) (const_int 1)))]
6670   "TARGET_SH1"
6671   "movt %0"
6672   [(set_attr "type" "arith")])
6673
6674 (define_expand "seq"
6675   [(set (match_operand:SI 0 "arith_reg_operand" "")
6676         (match_dup 1))]
6677   ""
6678   "
6679 {
6680   if (TARGET_SHMEDIA)
6681     {
6682       if (GET_MODE (operands[0]) != DImode)
6683         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6684       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
6685       if (sh_compare_op1 != const0_rtx)
6686         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
6687                                     ? GET_MODE (sh_compare_op0)
6688                                     : GET_MODE (sh_compare_op1),
6689                                     sh_compare_op1);
6690
6691       switch (GET_MODE (sh_compare_op0))
6692         {
6693         case DImode:
6694           emit_insn (gen_cmpeqdi_media (operands[0],
6695                                         sh_compare_op0, sh_compare_op1));
6696           break;
6697
6698         case SFmode:
6699           if (! TARGET_SHMEDIA_FPU)
6700             FAIL;
6701           emit_insn (gen_cmpeqsf_media (operands[0],
6702                                         sh_compare_op0, sh_compare_op1));
6703           break;
6704
6705         case DFmode:
6706           if (! TARGET_SHMEDIA_FPU)
6707             FAIL;
6708           emit_insn (gen_cmpeqdf_media (operands[0],
6709                                         sh_compare_op0, sh_compare_op1));
6710           break;
6711
6712         default:
6713           FAIL;
6714         }
6715       DONE;
6716     }
6717   operands[1] = prepare_scc_operands (EQ);
6718 }")
6719
6720 (define_expand "slt"
6721   [(set (match_operand:SI 0 "arith_reg_operand" "")
6722         (match_dup 1))]
6723   ""
6724   "
6725 {
6726   if (TARGET_SHMEDIA)
6727     {
6728       if (GET_MODE (operands[0]) != DImode)
6729         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6730       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
6731       if (sh_compare_op1 != const0_rtx)
6732         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
6733                                     ? GET_MODE (sh_compare_op0)
6734                                     : GET_MODE (sh_compare_op1),
6735                                     sh_compare_op1);
6736
6737       switch (GET_MODE (sh_compare_op0))
6738         {
6739         case DImode:
6740           emit_insn (gen_cmpgtdi_media (operands[0],
6741                                         sh_compare_op1, sh_compare_op0));
6742           break;
6743
6744         case SFmode:
6745           if (! TARGET_SHMEDIA_FPU)
6746             FAIL;
6747           emit_insn (gen_cmpgtsf_media (operands[0],
6748                                         sh_compare_op1, sh_compare_op0));
6749           break;
6750
6751         case DFmode:
6752           if (! TARGET_SHMEDIA_FPU)
6753             FAIL;
6754           emit_insn (gen_cmpgtdf_media (operands[0],
6755                                         sh_compare_op1, sh_compare_op0));
6756           break;
6757
6758         default:
6759           FAIL;
6760         }
6761       DONE;
6762     }
6763   operands[1] = prepare_scc_operands (LT);
6764 }")
6765
6766 (define_expand "sle"
6767   [(match_operand:SI 0 "arith_reg_operand" "")]
6768   ""
6769   "
6770 {
6771   rtx tmp = sh_compare_op0;
6772
6773   if (TARGET_SHMEDIA)
6774     {
6775       if (GET_MODE (operands[0]) != DImode)
6776         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6777       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
6778       if (sh_compare_op1 != const0_rtx)
6779         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
6780                                     ? GET_MODE (sh_compare_op0)
6781                                     : GET_MODE (sh_compare_op1),
6782                                     sh_compare_op1);
6783
6784       switch (GET_MODE (sh_compare_op0))
6785         {
6786         case DImode:
6787           {
6788             tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
6789
6790             emit_insn (gen_cmpgtdi_media (tmp,
6791                                           sh_compare_op0, sh_compare_op1));
6792             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
6793             break;
6794           }
6795
6796         case SFmode:
6797           if (! TARGET_SHMEDIA_FPU)
6798             FAIL;
6799           emit_insn (gen_cmpgesf_media (operands[0],
6800                                         sh_compare_op1, sh_compare_op0));
6801           break;
6802
6803         case DFmode:
6804           if (! TARGET_SHMEDIA_FPU)
6805             FAIL;
6806           emit_insn (gen_cmpgedf_media (operands[0],
6807                                         sh_compare_op1, sh_compare_op0));
6808           break;
6809
6810         default:
6811           FAIL;
6812         }
6813       DONE;
6814     }
6815
6816   sh_compare_op0 = sh_compare_op1;
6817   sh_compare_op1 = tmp;
6818   emit_insn (gen_sge (operands[0]));
6819   DONE;
6820 }")
6821
6822 (define_expand "sgt"
6823   [(set (match_operand:SI 0 "arith_reg_operand" "")
6824         (match_dup 1))]
6825   ""
6826   "
6827 {
6828   if (TARGET_SHMEDIA)
6829     {
6830       if (GET_MODE (operands[0]) != DImode)
6831         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6832       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
6833       if (sh_compare_op1 != const0_rtx)
6834         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
6835                                     ? GET_MODE (sh_compare_op0)
6836                                     : GET_MODE (sh_compare_op1),
6837                                     sh_compare_op1);
6838
6839       switch (GET_MODE (sh_compare_op0))
6840         {
6841         case DImode:
6842           emit_insn (gen_cmpgtdi_media (operands[0],
6843                                         sh_compare_op0, sh_compare_op1));
6844           break;
6845
6846         case SFmode:
6847           if (! TARGET_SHMEDIA_FPU)
6848             FAIL;
6849           emit_insn (gen_cmpgtsf_media (operands[0],
6850                                         sh_compare_op0, sh_compare_op1));
6851           break;
6852
6853         case DFmode:
6854           if (! TARGET_SHMEDIA_FPU)
6855             FAIL;
6856           emit_insn (gen_cmpgtdf_media (operands[0],
6857                                         sh_compare_op0, sh_compare_op1));
6858           break;
6859
6860         default:
6861           FAIL;
6862         }
6863       DONE;
6864     }
6865   operands[1] = prepare_scc_operands (GT);
6866 }")
6867
6868 (define_expand "sge"
6869   [(set (match_operand:SI 0 "arith_reg_operand" "")
6870         (match_dup 1))]
6871   ""
6872   "
6873 {
6874   if (TARGET_SHMEDIA)
6875     {
6876       if (GET_MODE (operands[0]) != DImode)
6877         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6878       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
6879       if (sh_compare_op1 != const0_rtx)
6880         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
6881                                     ? GET_MODE (sh_compare_op0)
6882                                     : GET_MODE (sh_compare_op1),
6883                                     sh_compare_op1);
6884
6885       switch (GET_MODE (sh_compare_op0))
6886         {
6887         case DImode:
6888           {
6889             rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
6890
6891             emit_insn (gen_cmpgtdi_media (tmp,
6892                                           sh_compare_op1, sh_compare_op0));
6893             emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
6894             break;
6895           }
6896
6897         case SFmode:
6898           if (! TARGET_SHMEDIA_FPU)
6899             FAIL;
6900           emit_insn (gen_cmpgesf_media (operands[0],
6901                                         sh_compare_op0, sh_compare_op1));
6902           break;
6903
6904         case DFmode:
6905           if (! TARGET_SHMEDIA_FPU)
6906             FAIL;
6907           emit_insn (gen_cmpgedf_media (operands[0],
6908                                         sh_compare_op0, sh_compare_op1));
6909           break;
6910
6911         default:
6912           FAIL;
6913         }
6914       DONE;
6915     }
6916
6917   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
6918     {
6919       if (TARGET_IEEE)
6920         {
6921           rtx lab = gen_label_rtx ();
6922           prepare_scc_operands (EQ);
6923           emit_jump_insn (gen_branch_true (lab));
6924           prepare_scc_operands (GT);
6925           emit_label (lab);
6926           emit_insn (gen_movt (operands[0]));
6927         }
6928       else
6929         emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
6930       DONE;
6931     }
6932   operands[1] = prepare_scc_operands (GE);
6933 }")
6934
6935 (define_expand "sgtu"
6936   [(set (match_operand:SI 0 "arith_reg_operand" "")
6937         (match_dup 1))]
6938   ""
6939   "
6940 {
6941   if (TARGET_SHMEDIA)
6942     {
6943       if (GET_MODE (operands[0]) != DImode)
6944         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6945       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
6946       if (sh_compare_op1 != const0_rtx)
6947         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
6948                                     ? GET_MODE (sh_compare_op0)
6949                                     : GET_MODE (sh_compare_op1),
6950                                     sh_compare_op1);
6951
6952       emit_insn (gen_cmpgtudi_media (operands[0],
6953                                      sh_compare_op0, sh_compare_op1));
6954       DONE;
6955     }
6956   operands[1] = prepare_scc_operands (GTU);
6957 }")
6958
6959 (define_expand "sltu"
6960   [(set (match_operand:SI 0 "arith_reg_operand" "")
6961         (match_dup 1))]
6962   ""
6963   "
6964 {
6965   if (TARGET_SHMEDIA)
6966     {
6967       if (GET_MODE (operands[0]) != DImode)
6968         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6969       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
6970       if (sh_compare_op1 != const0_rtx)
6971         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
6972                                     ? GET_MODE (sh_compare_op0)
6973                                     : GET_MODE (sh_compare_op1),
6974                                     sh_compare_op1);
6975
6976       emit_insn (gen_cmpgtudi_media (operands[0],
6977                                      sh_compare_op1, sh_compare_op0));
6978       DONE;
6979     }
6980   operands[1] = prepare_scc_operands (LTU);
6981 }")
6982
6983 (define_expand "sleu"
6984   [(set (match_operand:SI 0 "arith_reg_operand" "")
6985         (match_dup 1))]
6986   ""
6987   "
6988 {
6989   if (TARGET_SHMEDIA)
6990     {
6991       rtx tmp;
6992
6993       if (GET_MODE (operands[0]) != DImode)
6994         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6995       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
6996       if (sh_compare_op1 != const0_rtx)
6997         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
6998                                     ? GET_MODE (sh_compare_op0)
6999                                     : GET_MODE (sh_compare_op1),
7000                                     sh_compare_op1);
7001
7002       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7003
7004       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
7005       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7006
7007       DONE;
7008     }
7009   operands[1] = prepare_scc_operands (LEU);
7010 }")
7011
7012 (define_expand "sgeu"
7013   [(set (match_operand:SI 0 "arith_reg_operand" "")
7014         (match_dup 1))]
7015   ""
7016   "
7017 {
7018   if (TARGET_SHMEDIA)
7019     {
7020       rtx tmp;
7021
7022       if (GET_MODE (operands[0]) != DImode)
7023         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7024       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7025       if (sh_compare_op1 != const0_rtx)
7026         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7027                                     ? GET_MODE (sh_compare_op0)
7028                                     : GET_MODE (sh_compare_op1),
7029                                     sh_compare_op1);
7030
7031       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7032
7033       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
7034       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7035
7036       DONE;
7037     }
7038
7039   operands[1] = prepare_scc_operands (GEU);
7040 }")
7041
7042 ;; sne moves the complement of the T reg to DEST like this:
7043 ;;      cmp/eq ...
7044 ;;      mov    #-1,temp
7045 ;;      negc   temp,dest
7046 ;;   This is better than xoring compare result with 1 because it does
7047 ;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
7048 ;;   loop.
7049
7050 (define_expand "sne"
7051   [(set (match_dup 2) (const_int -1))
7052    (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
7053                    (neg:SI (plus:SI (match_dup 1)
7054                                     (match_dup 2))))
7055               (set (reg:SI T_REG)
7056                    (ne:SI (ior:SI (match_dup 1) (match_dup 2))
7057                           (const_int 0)))])]  
7058   ""
7059   "
7060 {
7061   if (TARGET_SHMEDIA)
7062     {
7063       rtx tmp;
7064
7065       if (GET_MODE (operands[0]) != DImode)
7066         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7067
7068       if (! TARGET_SHMEDIA_FPU && GET_MODE (sh_compare_op0) != DImode)
7069         FAIL;
7070
7071       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7072       if (sh_compare_op1 != const0_rtx)
7073         sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
7074                                     ? GET_MODE (sh_compare_op0)
7075                                     : GET_MODE (sh_compare_op1),
7076                                     sh_compare_op1);
7077
7078       tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
7079
7080       emit_insn (gen_seq (tmp));
7081       emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
7082
7083       DONE;
7084     }
7085
7086    operands[1] = prepare_scc_operands (EQ);
7087    operands[2] = gen_reg_rtx (SImode);
7088 }")
7089
7090 (define_expand "sunordered"
7091   [(set (match_operand:DI 0 "arith_reg_operand" "")
7092         (unordered:DI (match_dup 1) (match_dup 2)))]
7093   "TARGET_SHMEDIA_FPU"
7094   "
7095 {
7096   operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
7097   operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
7098 }")
7099
7100 ;; Use the same trick for FP sle / sge
7101 (define_expand "movnegt"
7102   [(set (match_dup 2) (const_int -1))
7103    (parallel [(set (match_operand 0 "" "")
7104                    (neg:SI (plus:SI (match_dup 1)
7105                                     (match_dup 2))))
7106               (set (reg:SI T_REG)
7107                    (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
7108                           (const_int 0)))])]  
7109   "TARGET_SH1"
7110   "operands[2] = gen_reg_rtx (SImode);")
7111
7112 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
7113 ;; This prevents a regression that occurred when we switched from xor to
7114 ;; mov/neg for sne.
7115
7116 (define_split
7117   [(set (match_operand:SI 0 "arith_reg_operand" "")
7118         (plus:SI (reg:SI T_REG)
7119                  (const_int -1)))]
7120   "TARGET_SH1"
7121   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
7122    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
7123   "")
7124
7125 ;; -------------------------------------------------------------------------
7126 ;; Instructions to cope with inline literal tables
7127 ;; -------------------------------------------------------------------------
7128
7129 ; 2 byte integer in line
7130
7131 (define_insn "consttable_2"
7132  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7133                     (match_operand 1 "" "")]
7134                    UNSPECV_CONST2)]
7135  ""
7136  "*
7137 {
7138   if (operands[1] != const0_rtx)
7139     assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
7140   return \"\";
7141 }"
7142  [(set_attr "length" "2")
7143  (set_attr "in_delay_slot" "no")])
7144
7145 ; 4 byte integer in line
7146
7147 (define_insn "consttable_4"
7148  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7149                     (match_operand 1 "" "")]
7150                    UNSPECV_CONST4)]
7151  ""
7152  "*
7153 {
7154   if (operands[1] != const0_rtx)
7155     assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
7156   return \"\";
7157 }"
7158  [(set_attr "length" "4")
7159   (set_attr "in_delay_slot" "no")])
7160
7161 ; 8 byte integer in line
7162
7163 (define_insn "consttable_8"
7164  [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
7165                     (match_operand 1 "" "")]
7166                    UNSPECV_CONST8)]
7167  ""
7168  "*
7169 {
7170   if (operands[1] != const0_rtx)
7171     assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
7172   return \"\";
7173 }"
7174  [(set_attr "length" "8")
7175   (set_attr "in_delay_slot" "no")])
7176
7177 ; 4 byte floating point
7178
7179 (define_insn "consttable_sf"
7180  [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
7181                     (match_operand 1 "" "")]
7182                    UNSPECV_CONST4)]
7183  ""
7184  "*
7185 {
7186   if (operands[1] != const0_rtx)
7187     {
7188       union real_extract u;
7189       memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
7190       assemble_real (u.d, SFmode, GET_MODE_ALIGNMENT (SFmode));
7191     }
7192   return \"\";
7193 }"
7194  [(set_attr "length" "4")
7195   (set_attr "in_delay_slot" "no")])
7196
7197 ; 8 byte floating point
7198
7199 (define_insn "consttable_df"
7200  [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
7201                     (match_operand 1 "" "")]
7202                    UNSPECV_CONST8)]
7203  ""
7204  "*
7205 {
7206   if (operands[1] != const0_rtx)
7207     {
7208       union real_extract u;
7209       memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
7210       assemble_real (u.d, DFmode, GET_MODE_ALIGNMENT (DFmode));
7211     }
7212   return \"\";
7213 }"
7214  [(set_attr "length" "8")
7215   (set_attr "in_delay_slot" "no")])
7216
7217 ;; Alignment is needed for some constant tables; it may also be added for
7218 ;; Instructions at the start of loops, or after unconditional branches.
7219 ;; ??? We would get more accurate lengths if we did instruction
7220 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
7221 ;; here is too conservative.
7222
7223 ; align to a two byte boundary
7224
7225 (define_expand "align_2"
7226  [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
7227  ""
7228  "")
7229
7230 ; align to a four byte boundary
7231 ;; align_4 and align_log are instructions for the starts of loops, or
7232 ;; after unconditional branches, which may take up extra room.
7233
7234 (define_expand "align_4"
7235  [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
7236  ""
7237  "")
7238
7239 ; align to a cache line boundary
7240
7241 (define_insn "align_log"
7242  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
7243  ""
7244  ""
7245  [(set_attr "length" "0")
7246   (set_attr "in_delay_slot" "no")])
7247
7248 ; emitted at the end of the literal table, used to emit the
7249 ; 32bit branch labels if needed.
7250
7251 (define_insn "consttable_end"
7252   [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
7253   ""
7254   "* return output_jump_label_table ();"
7255   [(set_attr "in_delay_slot" "no")])
7256
7257 ; emitted at the end of the window in the literal table.
7258
7259 (define_insn "consttable_window_end"
7260   [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
7261   ""
7262   ""
7263   [(set_attr "length" "0")
7264    (set_attr "in_delay_slot" "no")])
7265
7266 ;; -------------------------------------------------------------------------
7267 ;; Misc
7268 ;; -------------------------------------------------------------------------
7269
7270 ;; String/block move insn.
7271
7272 (define_expand "movstrsi"
7273   [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
7274                    (mem:BLK (match_operand:BLK 1 "" "")))
7275               (use (match_operand:SI 2 "nonmemory_operand" ""))
7276               (use (match_operand:SI 3 "immediate_operand" ""))
7277               (clobber (reg:SI PR_REG))
7278               (clobber (reg:SI R4_REG))
7279               (clobber (reg:SI R5_REG))
7280               (clobber (reg:SI R0_REG))])]
7281   "TARGET_SH1 && ! TARGET_SH5"
7282   "
7283 {
7284   if(expand_block_move (operands))
7285      DONE;
7286   else FAIL;
7287 }")
7288
7289 (define_insn "block_move_real"
7290   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7291                    (mem:BLK (reg:SI R5_REG)))
7292               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7293               (clobber (reg:SI PR_REG))
7294               (clobber (reg:SI R0_REG))])]
7295   "TARGET_SH1 && ! TARGET_HARD_SH4"
7296   "jsr  @%0%#"
7297   [(set_attr "type" "sfunc")
7298    (set_attr "needs_delay_slot" "yes")])
7299
7300 (define_insn "block_lump_real"
7301   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7302                    (mem:BLK (reg:SI R5_REG)))
7303               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7304               (use (reg:SI R6_REG))
7305               (clobber (reg:SI PR_REG))
7306               (clobber (reg:SI T_REG))
7307               (clobber (reg:SI R4_REG))
7308               (clobber (reg:SI R5_REG))
7309               (clobber (reg:SI R6_REG))
7310               (clobber (reg:SI R0_REG))])]
7311   "TARGET_SH1 && ! TARGET_HARD_SH4"
7312   "jsr  @%0%#"
7313   [(set_attr "type" "sfunc")
7314    (set_attr "needs_delay_slot" "yes")])
7315
7316 (define_insn "block_move_real_i4"
7317   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7318                    (mem:BLK (reg:SI R5_REG)))
7319               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7320               (clobber (reg:SI PR_REG))
7321               (clobber (reg:SI R0_REG))
7322               (clobber (reg:SI R1_REG))
7323               (clobber (reg:SI R2_REG))])]
7324   "TARGET_HARD_SH4"
7325   "jsr  @%0%#"
7326   [(set_attr "type" "sfunc")
7327    (set_attr "needs_delay_slot" "yes")])
7328
7329 (define_insn "block_lump_real_i4"
7330   [(parallel [(set (mem:BLK (reg:SI R4_REG))
7331                    (mem:BLK (reg:SI R5_REG)))
7332               (use (match_operand:SI 0 "arith_reg_operand" "r"))
7333               (use (reg:SI R6_REG))
7334               (clobber (reg:SI PR_REG))
7335               (clobber (reg:SI T_REG))
7336               (clobber (reg:SI R4_REG))
7337               (clobber (reg:SI R5_REG))
7338               (clobber (reg:SI R6_REG))
7339               (clobber (reg:SI R0_REG))
7340               (clobber (reg:SI R1_REG))
7341               (clobber (reg:SI R2_REG))
7342               (clobber (reg:SI R3_REG))])]
7343   "TARGET_HARD_SH4"
7344   "jsr  @%0%#"
7345   [(set_attr "type" "sfunc")
7346    (set_attr "needs_delay_slot" "yes")])
7347 \f
7348 ;; -------------------------------------------------------------------------
7349 ;; Floating point instructions.
7350 ;; -------------------------------------------------------------------------
7351
7352 ;; ??? All patterns should have a type attribute.
7353
7354 (define_expand "fpu_switch0"
7355   [(set (match_operand:SI 0 "" "") (match_dup 2))
7356    (set (match_dup 1) (mem:PSI (match_dup 0)))]
7357   "TARGET_SH4"
7358   "
7359 {
7360   operands[1] = get_fpscr_rtx ();
7361   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
7362   if (flag_pic)
7363     operands[2] = legitimize_pic_address (operands[2], SImode,
7364                                           no_new_pseudos ? operands[0] : 0);
7365 }")
7366
7367 (define_expand "fpu_switch1"
7368   [(set (match_operand:SI 0 "" "") (match_dup 2))
7369    (set (match_dup 3) (plus:SI (match_dup 0) (const_int 4)))
7370    (set (match_dup 1) (mem:PSI (match_dup 3)))]
7371   "TARGET_SH4"
7372   "
7373 {
7374   operands[1] = get_fpscr_rtx ();
7375   operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
7376   if (flag_pic)
7377     operands[2] = legitimize_pic_address (operands[2], SImode,
7378                                           no_new_pseudos ? operands[0] : 0);
7379   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
7380 }")
7381
7382 (define_expand "movpsi"
7383   [(set (match_operand:PSI 0 "register_operand" "")
7384         (match_operand:PSI 1 "general_movsrc_operand" ""))]
7385   "TARGET_SH4"
7386   "")
7387
7388 ;; The c / m alternative is a fake to guide reload to load directly into
7389 ;; fpscr, since reload doesn't know how to use post-increment.
7390 ;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
7391 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
7392 ;; predicate after reload.
7393 ;; The gp_fpul type for r/!c might look a bit odd, but it actually schedules
7394 ;; like a gpr <-> fpul move.
7395 (define_insn "fpu_switch"
7396   [(set (match_operand:PSI 0 "register_operand" "=c,c,r,c,c,r,m,r")
7397         (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c"))]
7398   "TARGET_SH4
7399    && (! reload_completed
7400        || true_regnum (operands[0]) != FPSCR_REG
7401        || GET_CODE (operands[1]) != MEM
7402        || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
7403   "@
7404         ! precision stays the same
7405         lds.l   %1,fpscr
7406         mov.l   %1,%0
7407         #
7408         lds     %1,fpscr
7409         mov     %1,%0
7410         mov.l   %1,%0
7411         sts     fpscr,%0"
7412   [(set_attr "length" "0,2,2,4,2,2,2,2")
7413    (set_attr "type" "dfp_conv,dfp_conv,load,dfp_conv,dfp_conv,move,store,gp_fpul")])
7414
7415 (define_split
7416   [(set (reg:PSI FPSCR_REG)
7417         (mem:PSI (match_operand:SI 0 "register_operand" "r")))]
7418   "TARGET_SH4 && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
7419   [(set (match_dup 0) (match_dup 0))]
7420   "
7421 {
7422   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
7423                                         gen_rtx (MEM, PSImode,
7424                                                  gen_rtx (POST_INC, Pmode,
7425                                                           operands[0]))));
7426   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[0], NULL_RTX);
7427 }")
7428
7429 (define_split
7430   [(set (reg:PSI FPSCR_REG)
7431         (mem:PSI (match_operand:SI 0 "register_operand" "r")))]
7432   "TARGET_SH4"
7433   [(set (match_dup 0) (plus:SI (match_dup 0) (const_int -4)))]
7434   "
7435 {
7436   rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
7437                                         gen_rtx (MEM, PSImode,
7438                                                  gen_rtx (POST_INC, Pmode,
7439                                                           operands[0]))));
7440   REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, operands[0], NULL_RTX);
7441 }")
7442
7443 ;; ??? This uses the fp unit, but has no type indicating that.
7444 ;; If we did that, this would either give a bogus latency or introduce
7445 ;; a bogus FIFO constraint.
7446 ;; Since this insn is currently only used for prologues/epilogues,
7447 ;; it is probably best to claim no function unit, which matches the
7448 ;; current setting.
7449 (define_insn "toggle_sz"
7450   [(set (reg:PSI FPSCR_REG)
7451         (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
7452   "TARGET_SH4"
7453   "fschg")
7454
7455 (define_expand "addsf3"
7456   [(set (match_operand:SF 0 "arith_reg_operand" "")
7457         (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
7458                  (match_operand:SF 2 "arith_reg_operand" "")))]
7459   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7460   "
7461 {
7462   if (TARGET_SH3E)
7463     {
7464       expand_sf_binop (&gen_addsf3_i, operands);
7465       DONE;
7466     }
7467 }")
7468
7469 (define_insn "*addsf3_media"
7470   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7471         (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
7472                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7473   "TARGET_SHMEDIA_FPU"
7474   "fadd.s       %1, %2, %0")
7475
7476 (define_insn "addsf3_i"
7477   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
7478         (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0")
7479                  (match_operand:SF 2 "arith_reg_operand" "f")))
7480    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
7481   "TARGET_SH3E"
7482   "fadd %2,%0"
7483   [(set_attr "type" "fp")
7484    (set_attr "fp_mode" "single")])
7485
7486 (define_expand "subsf3"
7487   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
7488         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
7489                   (match_operand:SF 2 "fp_arith_reg_operand" "")))]
7490   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7491   "
7492 {
7493   if (TARGET_SH3E)
7494     {
7495       expand_sf_binop (&gen_subsf3_i, operands);
7496       DONE;
7497     }
7498 }")
7499
7500 (define_insn "*subsf3_media"
7501   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7502         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
7503                   (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7504   "TARGET_SHMEDIA_FPU"
7505   "fsub.s       %1, %2, %0")
7506
7507 (define_insn "subsf3_i"
7508   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7509         (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
7510                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
7511    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
7512   "TARGET_SH3E"
7513   "fsub %2,%0"
7514   [(set_attr "type" "fp")
7515    (set_attr "fp_mode" "single")])
7516
7517 ;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
7518 ;; register in feeding fp instructions.  Thus, we cannot generate fmac for
7519 ;; mixed-precision SH4 targets.  To allow it to be still generated for the
7520 ;; SH3E, we use a separate insn for SH3E mulsf3.
7521
7522 (define_expand "mulsf3"
7523   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
7524         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
7525                  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
7526   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7527   "
7528 {
7529   if (TARGET_SH4)
7530     expand_sf_binop (&gen_mulsf3_i4, operands);
7531   else if (TARGET_SH3E)
7532     emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2]));
7533   if (! TARGET_SHMEDIA)
7534     DONE;
7535 }")
7536
7537 (define_insn "*mulsf3_media"
7538   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7539         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
7540                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7541   "TARGET_SHMEDIA_FPU"
7542   "fmul.s       %1, %2, %0")
7543
7544 (define_insn "mulsf3_i4"
7545   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7546         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
7547                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))
7548    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
7549   "TARGET_SH3E"
7550   "fmul %2,%0"
7551   [(set_attr "type" "fp")
7552    (set_attr "fp_mode" "single")])
7553
7554 (define_insn "mulsf3_ie"
7555   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7556         (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
7557                  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7558   "TARGET_SH3E && ! TARGET_SH4"
7559   "fmul %2,%0"
7560   [(set_attr "type" "fp")])
7561
7562 (define_insn "*mac_media"
7563   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7564         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
7565                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
7566                  (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
7567   "TARGET_SHMEDIA_FPU"
7568   "fmac.s %1, %2, %0")
7569
7570 (define_insn "*macsf3"
7571   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7572         (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
7573                           (match_operand:SF 2 "fp_arith_reg_operand" "f"))
7574                  (match_operand:SF 3 "arith_reg_operand" "0")))
7575    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
7576   "TARGET_SH3E && ! TARGET_SH4"
7577   "fmac fr0,%2,%0"
7578   [(set_attr "type" "fp")
7579    (set_attr "fp_mode" "single")])
7580
7581 (define_expand "divsf3"
7582   [(set (match_operand:SF 0 "arith_reg_operand" "")
7583         (div:SF (match_operand:SF 1 "arith_reg_operand" "")
7584                 (match_operand:SF 2 "arith_reg_operand" "")))]
7585   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7586   "
7587 {
7588   if (TARGET_SH3E)
7589     {
7590       expand_sf_binop (&gen_divsf3_i, operands);
7591       DONE;
7592     }
7593 }")
7594
7595 (define_insn "*divsf3_media"
7596   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7597         (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
7598                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7599   "TARGET_SHMEDIA_FPU"
7600   "fdiv.s       %1, %2, %0")
7601
7602 (define_insn "divsf3_i"
7603   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
7604         (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
7605                  (match_operand:SF 2 "arith_reg_operand" "f")))
7606    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
7607   "TARGET_SH3E"
7608   "fdiv %2,%0"
7609   [(set_attr "type" "fdiv")
7610    (set_attr "fp_mode" "single")])
7611
7612 (define_insn "floatdisf2"
7613   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7614         (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
7615   "TARGET_SHMEDIA_FPU"
7616   "float.qs %1, %0")
7617
7618 (define_expand "floatsisf2"
7619   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
7620         (float:SF (match_operand:SI 1 "fpul_operand" "")))]
7621   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7622   "
7623 {
7624   if (TARGET_SH4)
7625     {
7626       emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
7627       DONE;
7628     }
7629 }")
7630
7631 (define_insn "*floatsisf2_media"
7632   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7633         (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
7634   "TARGET_SHMEDIA_FPU"
7635   "float.ls     %1, %0")
7636
7637 (define_insn "floatsisf2_i4"
7638   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7639         (float:SF (match_operand:SI 1 "fpul_operand" "y")))
7640    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
7641   "TARGET_SH4"
7642   "float        %1,%0"
7643   [(set_attr "type" "fp")
7644    (set_attr "fp_mode" "single")])
7645
7646 (define_insn "*floatsisf2_ie"
7647   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7648         (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
7649   "TARGET_SH3E && ! TARGET_SH4"
7650   "float        %1,%0"
7651   [(set_attr "type" "fp")])
7652
7653 (define_insn "fix_truncsfdi2"
7654   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
7655         (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
7656   "TARGET_SHMEDIA_FPU"
7657   "ftrc.sq %1, %0")
7658
7659 (define_expand "fix_truncsfsi2"
7660   [(set (match_operand:SI 0 "fpul_operand" "=y")
7661         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
7662   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7663   "
7664 {
7665   if (TARGET_SH4)
7666     {
7667       emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
7668       DONE;
7669     }
7670 }")
7671
7672 (define_insn "*fix_truncsfsi2_media"
7673   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
7674         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
7675   "TARGET_SHMEDIA_FPU"
7676   "ftrc.sl      %1, %0")
7677
7678 (define_insn "fix_truncsfsi2_i4"
7679   [(set (match_operand:SI 0 "fpul_operand" "=y")
7680         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
7681    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
7682   "TARGET_SH4"
7683   "ftrc %1,%0"
7684   [(set_attr "type" "fp")
7685    (set_attr "fp_mode" "single")])
7686
7687 ;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
7688 ;; fix_truncsfsi2_i4.
7689 ;; (define_insn "fix_truncsfsi2_i4_2"
7690 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7691 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
7692 ;;   (use (reg:PSI FPSCR_REG))
7693 ;;   (clobber (reg:SI FPUL_REG))]
7694 ;;  "TARGET_SH4"
7695 ;;  "#"
7696 ;;  [(set_attr "length" "4")
7697 ;;   (set_attr "fp_mode" "single")])
7698
7699 ;;(define_split
7700 ;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7701 ;;      (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
7702 ;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
7703 ;;   (clobber (reg:SI FPUL_REG))]
7704 ;;  "TARGET_SH4"
7705 ;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
7706 ;;            (use (match_dup 2))])
7707 ;;   (set (match_dup 0) (reg:SI FPUL_REG))])
7708
7709 (define_insn "*fixsfsi"
7710   [(set (match_operand:SI 0 "fpul_operand" "=y")
7711         (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
7712   "TARGET_SH3E && ! TARGET_SH4"
7713   "ftrc %1,%0"
7714   [(set_attr "type" "fp")])
7715
7716 (define_insn "cmpgtsf_t"
7717   [(set (reg:SI T_REG)
7718         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
7719                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
7720   "TARGET_SH3E && ! TARGET_SH4"
7721   "fcmp/gt      %1,%0"
7722   [(set_attr "type" "fp")
7723    (set_attr "fp_mode" "single")])
7724
7725 (define_insn "cmpeqsf_t"
7726   [(set (reg:SI T_REG)
7727         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
7728                (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
7729   "TARGET_SH3E && ! TARGET_SH4"
7730   "fcmp/eq      %1,%0"
7731   [(set_attr "type" "fp")
7732    (set_attr "fp_mode" "single")])
7733
7734 (define_insn "ieee_ccmpeqsf_t"
7735   [(set (reg:SI T_REG)
7736         (ior:SI (reg:SI T_REG)
7737                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
7738                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
7739   "TARGET_SH3E && TARGET_IEEE && ! TARGET_SH4"
7740   "* return output_ieee_ccmpeq (insn, operands);"
7741   [(set_attr "length" "4")])
7742
7743
7744 (define_insn "cmpgtsf_t_i4"
7745   [(set (reg:SI T_REG)
7746         (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
7747                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
7748    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
7749   "TARGET_SH4"
7750   "fcmp/gt      %1,%0"
7751   [(set_attr "type" "fp")
7752    (set_attr "fp_mode" "single")])
7753
7754 (define_insn "cmpeqsf_t_i4"
7755   [(set (reg:SI T_REG)
7756         (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
7757                (match_operand:SF 1 "fp_arith_reg_operand" "f")))
7758    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
7759   "TARGET_SH4"
7760   "fcmp/eq      %1,%0"
7761   [(set_attr "type" "fp")
7762    (set_attr "fp_mode" "single")])
7763
7764 (define_insn "*ieee_ccmpeqsf_t_4"
7765   [(set (reg:SI T_REG)
7766         (ior:SI (reg:SI T_REG)
7767                 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
7768                        (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
7769    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
7770   "TARGET_IEEE && TARGET_SH4"
7771   "* return output_ieee_ccmpeq (insn, operands);"
7772   [(set_attr "length" "4")
7773    (set_attr "fp_mode" "single")])
7774
7775 (define_insn "cmpeqsf_media"
7776   [(set (match_operand:DI 0 "register_operand" "=r")
7777         (eq:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
7778                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7779   "TARGET_SHMEDIA_FPU"
7780   "fcmpeq.s     %1, %2, %0")
7781
7782 (define_insn "cmpgtsf_media"
7783   [(set (match_operand:DI 0 "register_operand" "=r")
7784         (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
7785                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7786   "TARGET_SHMEDIA_FPU"
7787   "fcmpgt.s     %1, %2, %0")
7788
7789 (define_insn "cmpgesf_media"
7790   [(set (match_operand:DI 0 "register_operand" "=r")
7791         (ge:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
7792                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7793   "TARGET_SHMEDIA_FPU"
7794   "fcmpge.s     %1, %2, %0")
7795
7796 (define_insn "cmpunsf_media"
7797   [(set (match_operand:DI 0 "register_operand" "=r")
7798         (unordered:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
7799                       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
7800   "TARGET_SHMEDIA_FPU"
7801   "fcmpun.s     %1, %2, %0")
7802
7803 (define_expand "cmpsf"
7804   [(set (reg:SI T_REG)
7805         (compare (match_operand:SF 0 "arith_operand" "")
7806                  (match_operand:SF 1 "arith_operand" "")))]
7807   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7808   "
7809 {
7810   sh_compare_op0 = operands[0];
7811   sh_compare_op1 = operands[1];
7812   DONE;
7813 }")
7814
7815 (define_expand "negsf2"
7816   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
7817         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
7818   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7819   "
7820 {
7821   if (TARGET_SH3E)
7822     {
7823       expand_sf_unop (&gen_negsf2_i, operands);
7824       DONE;
7825     }
7826 }")
7827
7828 (define_insn "*negsf2_media"
7829   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7830         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
7831   "TARGET_SHMEDIA_FPU"
7832   "fneg.s       %1, %0")
7833
7834 (define_insn "negsf2_i"
7835   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7836         (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
7837    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
7838   "TARGET_SH3E"
7839   "fneg %0"
7840   [(set_attr "type" "fmove")
7841    (set_attr "fp_mode" "single")])
7842
7843 (define_expand "sqrtsf2"
7844   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
7845         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
7846   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7847   "
7848 {
7849   if (TARGET_SH3E)
7850     {
7851       expand_sf_unop (&gen_sqrtsf2_i, operands);
7852       DONE;
7853     }
7854 }")
7855
7856 (define_insn "*sqrtsf2_media"
7857   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7858         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
7859   "TARGET_SHMEDIA_FPU"
7860   "fsqrt.s      %1, %0")
7861
7862 (define_insn "sqrtsf2_i"
7863   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7864         (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
7865    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
7866   "TARGET_SH3E"
7867   "fsqrt        %0"
7868   [(set_attr "type" "fdiv")
7869    (set_attr "fp_mode" "single")])
7870
7871 (define_expand "abssf2"
7872   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
7873         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
7874   "TARGET_SH3E || TARGET_SHMEDIA_FPU"
7875   "
7876 {
7877   if (TARGET_SH3E)
7878     {
7879       expand_sf_unop (&gen_abssf2_i, operands);
7880       DONE;
7881     }
7882 }")
7883
7884 (define_insn "*abssf2_media"
7885   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7886         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
7887   "TARGET_SHMEDIA_FPU"
7888   "fabs.s       %1, %0")
7889
7890 (define_insn "abssf2_i"
7891   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
7892         (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
7893    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
7894   "TARGET_SH3E"
7895   "fabs %0"
7896   [(set_attr "type" "fmove")
7897    (set_attr "fp_mode" "single")])
7898
7899 (define_expand "adddf3"
7900   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
7901         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
7902                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
7903   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
7904   "
7905 {
7906   if (TARGET_SH4)
7907     {
7908       expand_df_binop (&gen_adddf3_i, operands);
7909       DONE;
7910     }
7911 }")
7912
7913 (define_insn "*adddf3_media"
7914   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
7915         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
7916                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
7917   "TARGET_SHMEDIA_FPU"
7918   "fadd.d       %1, %2, %0")
7919
7920 (define_insn "adddf3_i"
7921   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
7922         (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
7923                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
7924    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
7925   "TARGET_SH4"
7926   "fadd %2,%0"
7927   [(set_attr "type" "dfp_arith")
7928    (set_attr "fp_mode" "double")])
7929
7930 (define_expand "subdf3"
7931   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
7932         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
7933                   (match_operand:DF 2 "fp_arith_reg_operand" "")))]
7934   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
7935   "
7936 {
7937   if (TARGET_SH4)
7938     {
7939       expand_df_binop (&gen_subdf3_i, operands);
7940       DONE;
7941     }
7942 }")
7943
7944 (define_insn "*subdf3_media"
7945   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
7946         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
7947                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
7948   "TARGET_SHMEDIA_FPU"
7949   "fsub.d       %1, %2, %0")
7950
7951 (define_insn "subdf3_i"
7952   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
7953         (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
7954                   (match_operand:DF 2 "fp_arith_reg_operand" "f")))
7955    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
7956   "TARGET_SH4"
7957   "fsub %2,%0"
7958   [(set_attr "type" "dfp_arith")
7959    (set_attr "fp_mode" "double")])
7960
7961 (define_expand "muldf3"
7962   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
7963         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
7964                  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
7965   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
7966   "
7967 {
7968   if (TARGET_SH4)
7969     {
7970       expand_df_binop (&gen_muldf3_i, operands);
7971       DONE;
7972     }
7973 }")
7974
7975 (define_insn "*muldf3_media"
7976   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
7977         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
7978                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
7979   "TARGET_SHMEDIA_FPU"
7980   "fmul.d       %1, %2, %0")
7981
7982 (define_insn "muldf3_i"
7983   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
7984         (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
7985                  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
7986    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
7987   "TARGET_SH4"
7988   "fmul %2,%0"
7989   [(set_attr "type" "dfp_arith")
7990    (set_attr "fp_mode" "double")])
7991
7992 (define_expand "divdf3"
7993   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
7994         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
7995                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
7996   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
7997   "
7998 {
7999   if (TARGET_SH4)
8000     {
8001       expand_df_binop (&gen_divdf3_i, operands);
8002       DONE;
8003     }
8004 }")
8005
8006 (define_insn "*divdf3_media"
8007   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8008         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
8009                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8010   "TARGET_SHMEDIA_FPU"
8011   "fdiv.d       %1, %2, %0")
8012
8013 (define_insn "divdf3_i"
8014   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8015         (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
8016                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
8017    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
8018   "TARGET_SH4"
8019   "fdiv %2,%0"
8020   [(set_attr "type" "dfdiv")
8021    (set_attr "fp_mode" "double")])
8022
8023 (define_insn "floatdidf2"
8024   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8025         (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
8026   "TARGET_SHMEDIA_FPU"
8027   "float.qd     %1, %0")
8028
8029 (define_expand "floatsidf2"
8030   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8031         (float:DF (match_operand:SI 1 "fpul_operand" "")))]
8032   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8033   "
8034 {
8035   if (TARGET_SH4)
8036     {
8037       emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
8038                                       get_fpscr_rtx ()));
8039       DONE;
8040     }
8041 }")
8042
8043 (define_insn "*floatsidf2_media"
8044   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8045         (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
8046   "TARGET_SHMEDIA_FPU"
8047   "float.ld     %1, %0")
8048
8049 (define_insn "floatsidf2_i"
8050   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8051         (float:DF (match_operand:SI 1 "fpul_operand" "y")))
8052    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8053   "TARGET_SH4"
8054   "float        %1,%0"
8055   [(set_attr "type" "dfp_conv")
8056    (set_attr "fp_mode" "double")])
8057
8058 (define_insn "fix_truncdfdi2"
8059   [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
8060         (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8061   "TARGET_SHMEDIA_FPU"
8062   "ftrc.dq      %1, %0")
8063
8064 (define_expand "fix_truncdfsi2"
8065   [(set (match_operand:SI 0 "fpul_operand" "")
8066         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
8067   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8068   "
8069 {
8070   if (TARGET_SH4)
8071     {
8072       emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
8073                                           get_fpscr_rtx ()));
8074       DONE;
8075     }
8076 }")
8077
8078 (define_insn "*fix_truncdfsi2_media"
8079   [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
8080         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8081   "TARGET_SHMEDIA_FPU"
8082   "ftrc.dl      %1, %0")
8083
8084 (define_insn "fix_truncdfsi2_i"
8085   [(set (match_operand:SI 0 "fpul_operand" "=y")
8086         (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
8087    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8088   "TARGET_SH4"
8089   "ftrc %1,%0"
8090   [(set_attr "type" "dfp_conv")
8091    (set_attr "fp_mode" "double")])
8092
8093 ;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
8094 ;; fix_truncdfsi2_i.
8095 ;; (define_insn "fix_truncdfsi2_i4"
8096 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8097 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
8098 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
8099 ;;    (clobber (reg:SI FPUL_REG))]
8100 ;;   "TARGET_SH4"
8101 ;;   "#"
8102 ;;   [(set_attr "length" "4")
8103 ;;    (set_attr "fp_mode" "double")])
8104 ;; 
8105 ;; (define_split
8106 ;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8107 ;;      (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
8108 ;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
8109 ;;    (clobber (reg:SI FPUL_REG))]
8110 ;;   "TARGET_SH4"
8111 ;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
8112 ;;            (use (match_dup 2))])
8113 ;;    (set (match_dup 0) (reg:SI FPUL_REG))])
8114
8115 (define_insn "cmpgtdf_t"
8116   [(set (reg:SI T_REG)
8117         (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
8118                (match_operand:DF 1 "arith_reg_operand" "f")))
8119    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8120   "TARGET_SH4"
8121   "fcmp/gt      %1,%0"
8122   [(set_attr "type" "dfp_cmp")
8123    (set_attr "fp_mode" "double")])
8124
8125 (define_insn "cmpeqdf_t"
8126   [(set (reg:SI T_REG)
8127         (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
8128                (match_operand:DF 1 "arith_reg_operand" "f")))
8129    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8130   "TARGET_SH4"
8131   "fcmp/eq      %1,%0"
8132   [(set_attr "type" "dfp_cmp")
8133    (set_attr "fp_mode" "double")])
8134
8135 (define_insn "*ieee_ccmpeqdf_t"
8136   [(set (reg:SI T_REG)
8137         (ior:SI (reg:SI T_REG)
8138                 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
8139                        (match_operand:DF 1 "arith_reg_operand" "f"))))
8140    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8141   "TARGET_IEEE && TARGET_SH4"
8142   "* return output_ieee_ccmpeq (insn, operands);"
8143   [(set_attr "length" "4")
8144    (set_attr "fp_mode" "double")])
8145    
8146 (define_insn "cmpeqdf_media"
8147   [(set (match_operand:DI 0 "register_operand" "=r")
8148         (eq:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8149                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8150   "TARGET_SHMEDIA_FPU"
8151   "fcmpeq.d     %1,%2,%0")
8152
8153 (define_insn "cmpgtdf_media"
8154   [(set (match_operand:DI 0 "register_operand" "=r")
8155         (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8156                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8157   "TARGET_SHMEDIA_FPU"
8158   "fcmpgt.d     %1,%2,%0")
8159
8160 (define_insn "cmpgedf_media"
8161   [(set (match_operand:DI 0 "register_operand" "=r")
8162         (ge:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8163                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8164   "TARGET_SHMEDIA_FPU"
8165   "fcmpge.d     %1,%2,%0")
8166
8167 (define_insn "cmpundf_media"
8168   [(set (match_operand:DI 0 "register_operand" "=r")
8169         (unordered:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
8170                       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
8171   "TARGET_SHMEDIA_FPU"
8172   "fcmpun.d     %1,%2,%0")
8173
8174 (define_expand "cmpdf"
8175   [(set (reg:SI T_REG)
8176         (compare (match_operand:DF 0 "arith_operand" "")
8177                  (match_operand:DF 1 "arith_operand" "")))]
8178   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8179   "
8180 {
8181   sh_compare_op0 = operands[0];
8182   sh_compare_op1 = operands[1];
8183   DONE;
8184 }")
8185
8186 (define_expand "negdf2"
8187   [(set (match_operand:DF 0 "arith_reg_operand" "")
8188         (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
8189   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8190   "
8191 {
8192   if (TARGET_SH4)
8193     {
8194       expand_df_unop (&gen_negdf2_i, operands);
8195       DONE;
8196     }
8197 }")
8198
8199 (define_insn "*negdf2_media"
8200   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8201         (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8202   "TARGET_SHMEDIA_FPU"
8203   "fneg.d       %1, %0")
8204
8205 (define_insn "negdf2_i"
8206   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
8207         (neg:DF (match_operand:DF 1 "arith_reg_operand" "0")))
8208    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8209   "TARGET_SH4"
8210   "fneg %0"
8211   [(set_attr "type" "fmove")
8212    (set_attr "fp_mode" "double")])
8213
8214 (define_expand "sqrtdf2"
8215   [(set (match_operand:DF 0 "arith_reg_operand" "")
8216         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
8217   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8218   "
8219 {
8220   if (TARGET_SH4)
8221     {
8222       expand_df_unop (&gen_sqrtdf2_i, operands);
8223       DONE;
8224     }
8225 }")
8226
8227 (define_insn "*sqrtdf2_media"
8228   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8229         (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8230   "TARGET_SHMEDIA_FPU"
8231   "fsqrt.d      %1, %0")
8232
8233 (define_insn "sqrtdf2_i"
8234   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
8235         (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "0")))
8236    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8237   "TARGET_SH4"
8238   "fsqrt        %0"
8239   [(set_attr "type" "dfdiv")
8240    (set_attr "fp_mode" "double")])
8241
8242 (define_expand "absdf2"
8243   [(set (match_operand:DF 0 "arith_reg_operand" "")
8244         (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
8245   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8246   "
8247 {
8248   if (TARGET_SH4)
8249     {
8250       expand_df_unop (&gen_absdf2_i, operands);
8251       DONE;
8252     }
8253 }")
8254
8255 (define_insn "*absdf2_media"
8256   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8257         (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8258   "TARGET_SHMEDIA_FPU"
8259   "fabs.d       %1, %0")
8260
8261 (define_insn "absdf2_i"
8262   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
8263         (abs:DF (match_operand:DF 1 "arith_reg_operand" "0")))
8264    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8265   "TARGET_SH4"
8266   "fabs %0"
8267   [(set_attr "type" "fmove")
8268    (set_attr "fp_mode" "double")])
8269
8270 (define_expand "extendsfdf2"
8271   [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
8272         (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
8273   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8274   "
8275 {
8276   if (TARGET_SH4)
8277     {
8278       emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
8279                                         get_fpscr_rtx ()));
8280       DONE;
8281     }
8282 }")
8283
8284 (define_insn "*extendsfdf2_media"
8285   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8286         (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
8287   "TARGET_SHMEDIA_FPU"
8288   "fcnv.sd      %1, %0")
8289
8290 (define_insn "extendsfdf2_i4"
8291   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
8292         (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
8293    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8294   "TARGET_SH4"
8295   "fcnvsd  %1,%0"
8296   [(set_attr "type" "fp")
8297    (set_attr "fp_mode" "double")])
8298
8299 (define_expand "truncdfsf2"
8300   [(set (match_operand:SF 0 "fpul_operand" "")
8301         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
8302   "TARGET_SH4 || TARGET_SHMEDIA_FPU"
8303   "
8304 {
8305   if (TARGET_SH4)
8306     {
8307       emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
8308                                        get_fpscr_rtx ()));
8309       DONE;
8310     }
8311 }")
8312
8313 (define_insn "*truncdfsf2_media"
8314   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
8315         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
8316   "TARGET_SHMEDIA_FPU"
8317   "fcnv.ds      %1, %0")
8318
8319 (define_insn "truncdfsf2_i4"
8320   [(set (match_operand:SF 0 "fpul_operand" "=y")
8321         (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
8322    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
8323   "TARGET_SH4"
8324   "fcnvds  %1,%0"
8325   [(set_attr "type" "fp")
8326    (set_attr "fp_mode" "double")])
8327 \f
8328 ;; Bit field extract patterns.  These give better code for packed bitfields,
8329 ;; because they allow auto-increment addresses to be generated.
8330
8331 (define_expand "insv"
8332   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
8333                          (match_operand:SI 1 "immediate_operand" "")
8334                          (match_operand:SI 2 "immediate_operand" ""))
8335         (match_operand:SI 3 "general_operand" ""))]
8336   "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
8337   "
8338 {
8339   rtx addr_target, orig_address, shift_reg, qi_val;
8340   HOST_WIDE_INT bitsize, size, v;
8341   rtx x = operands[3];
8342
8343   /* ??? expmed doesn't care for non-register predicates.  */
8344   if (! memory_operand (operands[0], VOIDmode)
8345       || ! immediate_operand (operands[1], VOIDmode)
8346       || ! immediate_operand (operands[2], VOIDmode)
8347       || ! general_operand (x, VOIDmode))
8348     FAIL;
8349   /* If this isn't a 16 / 24 / 32 bit field, or if
8350      it doesn't start on a byte boundary, then fail.  */
8351   bitsize = INTVAL (operands[1]);
8352   if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
8353       || (INTVAL (operands[2]) % 8) != 0)
8354     FAIL;
8355
8356   size = bitsize / 8;
8357   orig_address = XEXP (operands[0], 0);
8358   shift_reg = gen_reg_rtx (SImode);
8359   if (GET_CODE (x) == CONST_INT)
8360     {
8361       v = INTVAL (x);
8362       qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
8363     }
8364   else
8365     {
8366       emit_insn (gen_movsi (shift_reg, operands[3]));
8367       qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
8368     }
8369   addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
8370
8371   operands[0] = replace_equiv_address (operands[0], addr_target);
8372   emit_insn (gen_movqi (operands[0], qi_val));
8373
8374   while (size -= 1)
8375     {
8376       if (GET_CODE (x) == CONST_INT)
8377         qi_val
8378           = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
8379       else
8380         {
8381           emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
8382           qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
8383         }
8384       emit_insn (gen_addsi3 (addr_target, addr_target, GEN_INT (-1)));
8385       emit_insn (gen_movqi (operands[0], qi_val));
8386     }
8387
8388   DONE;
8389 }")
8390 \f
8391 ;; -------------------------------------------------------------------------
8392 ;; Peepholes
8393 ;; -------------------------------------------------------------------------
8394
8395 ;; This matches cases where a stack pointer increment at the start of the
8396 ;; epilogue combines with a stack slot read loading the return value.
8397
8398 (define_peephole
8399   [(set (match_operand:SI 0 "arith_reg_operand" "")
8400         (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
8401    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
8402   "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
8403   "mov.l        @%1+,%0")
8404
8405 ;; See the comment on the dt combiner pattern above.
8406
8407 (define_peephole
8408   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
8409         (plus:SI (match_dup 0)
8410                  (const_int -1)))
8411    (set (reg:SI T_REG)
8412         (eq:SI (match_dup 0)
8413                (const_int 0)))]
8414   "TARGET_SH2"
8415   "dt   %0")
8416
8417 ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
8418 ;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
8419 ;; reload when the constant is too large for a reg+offset address.
8420
8421 ;; ??? We would get much better code if this was done in reload.  This would
8422 ;; require modifying find_reloads_address to recognize that if the constant
8423 ;; is out-of-range for an immediate add, then we get better code by reloading
8424 ;; the constant into a register than by reloading the sum into a register,
8425 ;; since the former is one instruction shorter if the address does not need
8426 ;; to be offsettable.  Unfortunately this does not work, because there is
8427 ;; only one register, r0, that can be used as an index register.  This register
8428 ;; is also the function return value register.  So, if we try to force reload
8429 ;; to use double-reg addresses, then we end up with some instructions that
8430 ;; need to use r0 twice.  The only way to fix this is to change the calling
8431 ;; convention so that r0 is not used to return values.
8432
8433 (define_peephole
8434   [(set (match_operand:SI 0 "register_operand" "=r")
8435         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8436    (set (mem:SI (match_dup 0))
8437         (match_operand:SI 2 "general_movsrc_operand" ""))]
8438   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
8439   "mov.l        %2,@(%0,%1)")
8440
8441 (define_peephole
8442   [(set (match_operand:SI 0 "register_operand" "=r")
8443         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8444    (set (match_operand:SI 2 "general_movdst_operand" "")
8445         (mem:SI (match_dup 0)))]
8446   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
8447   "mov.l        @(%0,%1),%2")
8448
8449 (define_peephole
8450   [(set (match_operand:SI 0 "register_operand" "=r")
8451         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8452    (set (mem:HI (match_dup 0))
8453         (match_operand:HI 2 "general_movsrc_operand" ""))]
8454   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
8455   "mov.w        %2,@(%0,%1)")
8456
8457 (define_peephole
8458   [(set (match_operand:SI 0 "register_operand" "=r")
8459         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8460    (set (match_operand:HI 2 "general_movdst_operand" "")
8461         (mem:HI (match_dup 0)))]
8462   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
8463   "mov.w        @(%0,%1),%2")
8464
8465 (define_peephole
8466   [(set (match_operand:SI 0 "register_operand" "=r")
8467         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8468    (set (mem:QI (match_dup 0))
8469         (match_operand:QI 2 "general_movsrc_operand" ""))]
8470   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
8471   "mov.b        %2,@(%0,%1)")
8472
8473 (define_peephole
8474   [(set (match_operand:SI 0 "register_operand" "=r")
8475         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8476    (set (match_operand:QI 2 "general_movdst_operand" "")
8477         (mem:QI (match_dup 0)))]
8478   "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
8479   "mov.b        @(%0,%1),%2")
8480
8481 (define_peephole
8482   [(set (match_operand:SI 0 "register_operand" "=r")
8483         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8484    (set (mem:SF (match_dup 0))
8485         (match_operand:SF 2 "general_movsrc_operand" ""))]
8486   "TARGET_SH1 && REGNO (operands[0]) == 0
8487    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
8488        || (GET_CODE (operands[2]) == SUBREG
8489            && REGNO (SUBREG_REG (operands[2])) < 16))
8490    && reg_unused_after (operands[0], insn)"
8491   "mov.l        %2,@(%0,%1)")
8492
8493 (define_peephole
8494   [(set (match_operand:SI 0 "register_operand" "=r")
8495         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8496    (set (match_operand:SF 2 "general_movdst_operand" "")
8497
8498         (mem:SF (match_dup 0)))]
8499   "TARGET_SH1 && REGNO (operands[0]) == 0
8500    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
8501        || (GET_CODE (operands[2]) == SUBREG
8502            && REGNO (SUBREG_REG (operands[2])) < 16))
8503    && reg_unused_after (operands[0], insn)"
8504   "mov.l        @(%0,%1),%2")
8505
8506 (define_peephole
8507   [(set (match_operand:SI 0 "register_operand" "=r")
8508         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8509    (set (mem:SF (match_dup 0))
8510         (match_operand:SF 2 "general_movsrc_operand" ""))]
8511   "TARGET_SH3E && REGNO (operands[0]) == 0
8512    && ((GET_CODE (operands[2]) == REG
8513         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
8514        || (GET_CODE (operands[2]) == SUBREG
8515            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
8516    && reg_unused_after (operands[0], insn)"
8517   "fmov{.s|}    %2,@(%0,%1)")
8518
8519 (define_peephole
8520   [(set (match_operand:SI 0 "register_operand" "=r")
8521         (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
8522    (set (match_operand:SF 2 "general_movdst_operand" "")
8523
8524         (mem:SF (match_dup 0)))]
8525   "TARGET_SH3E && REGNO (operands[0]) == 0
8526    && ((GET_CODE (operands[2]) == REG
8527         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
8528        || (GET_CODE (operands[2]) == SUBREG
8529            && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
8530    && reg_unused_after (operands[0], insn)"
8531   "fmov{.s|}    @(%0,%1),%2")
8532
8533 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
8534 (define_insn "sp_switch_1"
8535   [(const_int 1)]
8536   "TARGET_SH1"
8537   "*
8538 {
8539   rtx xoperands[1];
8540
8541   xoperands[0] = sp_switch;
8542   output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", xoperands);
8543   output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", xoperands);
8544   return \"mov r0,r15\";
8545 }"
8546   [(set_attr "length" "10")])
8547
8548 ;; Switch back to the original stack for interrupt functions with the
8549 ;; sp_switch attribute.  */
8550 (define_insn "sp_switch_2"
8551   [(const_int 2)]
8552   "TARGET_SH1"
8553   "mov.l @r15+,r15\;mov.l @r15+,r0"
8554   [(set_attr "length" "4")])