OSDN Git Service

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