sh.md revision 1.1.1.1.4.2
1;;- Machine description for Renesas / SuperH SH.
2;;  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3;;  2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4;;  Contributed by Steve Chamberlain (sac@cygnus.com).
5;;  Improved by Jim Wilson (wilson@cygnus.com).
6
7;; This file is part of GCC.
8
9;; GCC is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation; either version 3, or (at your option)
12;; any later version.
13
14;; GCC is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GCC; see the file COPYING3.  If not see
21;; <http://www.gnu.org/licenses/>.
22
23
24;; ??? Should prepend a * to all pattern names which are not used.
25;; This will make the compiler smaller, and rebuilds after changes faster.
26
27;; ??? Should be enhanced to include support for many more GNU superoptimizer
28;; sequences.  Especially the sequences for arithmetic right shifts.
29
30;; ??? Should check all DImode patterns for consistency and usefulness.
31
32;; ??? The MAC.W and MAC.L instructions are not supported.  There is no
33;; way to generate them.
34
35;; ??? The cmp/str instruction is not supported.  Perhaps it can be used
36;; for a str* inline function.
37
38;; BSR is not generated by the compiler proper, but when relaxing, it
39;; generates .uses pseudo-ops that allow linker relaxation to create
40;; BSR.  This is actually implemented in bfd/{coff,elf32}-sh.c
41
42;; Special constraints for SH machine description:
43;;
44;;    t -- T
45;;    x -- mac
46;;    l -- pr
47;;    z -- r0
48;;
49;; Special formats used for outputting SH instructions:
50;;
51;;   %.  --  print a .s if insn needs delay slot
52;;   %@  --  print rte/rts if is/isn't an interrupt function
53;;   %#  --  output a nop if there is nothing to put in the delay slot
54;;   %O  --  print a constant without the #
55;;   %R  --  print the lsw reg of a double
56;;   %S  --  print the msw reg of a double
57;;   %T  --  print next word of a double REG or MEM
58;;
59;; Special predicates:
60;;
61;;  arith_operand          -- operand is valid source for arithmetic op
62;;  arith_reg_operand      -- operand is valid register for arithmetic op
63;;  general_movdst_operand -- operand is valid move destination
64;;  general_movsrc_operand -- operand is valid move source
65;;  logical_operand        -- operand is valid source for logical op
66
67;; -------------------------------------------------------------------------
68;; Constants
69;; -------------------------------------------------------------------------
70
71(define_constants [
72  (AP_REG	145)
73  (PR_REG	146)
74  (T_REG	147)
75  (GBR_REG	144)
76  (MACH_REG	148)
77  (MACL_REG	149)
78  (FPUL_REG	150)
79  (RAP_REG	152)
80
81  (FPSCR_REG	151)
82
83  (PIC_REG	12)
84  (FP_REG	14)
85  (SP_REG	15)
86
87  (PR_MEDIA_REG	18)
88  (T_MEDIA_REG	19)
89
90  (R0_REG	0)
91  (R1_REG	1)
92  (R2_REG	2)
93  (R3_REG	3)
94  (R4_REG	4)
95  (R5_REG	5)
96  (R6_REG	6)
97  (R7_REG	7)
98  (R8_REG	8)
99  (R9_REG	9)
100  (R10_REG	10)
101  (R20_REG	20)
102  (R21_REG	21)
103  (R22_REG	22)
104  (R23_REG	23)
105
106  (DR0_REG	64)
107  (DR2_REG	66)
108  (DR4_REG	68)
109  (FR23_REG	87)
110
111  (TR0_REG	128)
112  (TR1_REG	129)
113  (TR2_REG	130)
114
115  (XD0_REG	136)
116
117  ;; These are used with unspec.
118  (UNSPEC_COMPACT_ARGS	0)
119  (UNSPEC_MOVA		1)
120  (UNSPEC_CASESI	2)
121  (UNSPEC_DATALABEL	3)
122  (UNSPEC_BBR		4)
123  (UNSPEC_SFUNC		5)
124  (UNSPEC_PIC		6)
125  (UNSPEC_GOT		7)
126  (UNSPEC_GOTOFF	8)
127  (UNSPEC_PLT		9)
128  (UNSPEC_CALLER	10)
129  (UNSPEC_GOTPLT	11)
130  (UNSPEC_ICACHE	12)
131  (UNSPEC_INIT_TRAMP	13)
132  (UNSPEC_FCOSA		14)
133  (UNSPEC_FSRRA		15)
134  (UNSPEC_FSINA		16)
135  (UNSPEC_NSB		17)
136  (UNSPEC_ALLOCO	18)
137  (UNSPEC_TLSGD		20)
138  (UNSPEC_TLSLDM	21)
139  (UNSPEC_TLSIE		22)
140  (UNSPEC_DTPOFF	23)
141  (UNSPEC_GOTTPOFF	24)
142  (UNSPEC_TPOFF		25)
143  (UNSPEC_RA		26)
144  (UNSPEC_DIV_INV_M0	30)
145  (UNSPEC_DIV_INV_M1	31)
146  (UNSPEC_DIV_INV_M2	32)
147  (UNSPEC_DIV_INV_M3	33)
148  (UNSPEC_DIV_INV20	34)
149  (UNSPEC_DIV_INV_TABLE	37)
150  (UNSPEC_ASHIFTRT	35)
151  (UNSPEC_THUNK		36)
152  (UNSPEC_CHKADD	38)
153  (UNSPEC_SP_SET	40)
154  (UNSPEC_SP_TEST	41)
155  (UNSPEC_MOVUA		42)
156
157  ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
158  ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
159  (UNSPEC_EXTRACT_S16	43)
160  (UNSPEC_EXTRACT_U16	44)
161
162  ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
163  (UNSPEC_SYMOFF	45)
164
165  ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
166  (UNSPEC_PCREL_SYMOFF	46)
167
168  ;; These are used with unspec_volatile.
169  (UNSPECV_BLOCKAGE	0)
170  (UNSPECV_ALIGN	1)
171  (UNSPECV_CONST2	2)
172  (UNSPECV_CONST4	4)
173  (UNSPECV_CONST8	6)
174  (UNSPECV_WINDOW_END	10)
175  (UNSPECV_CONST_END	11)
176  (UNSPECV_EH_RETURN	12)
177])
178
179;; -------------------------------------------------------------------------
180;; Attributes
181;; -------------------------------------------------------------------------
182
183;; Target CPU.
184
185(define_attr "cpu"
186 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
187  (const (symbol_ref "sh_cpu_attr")))
188
189(define_attr "endian" "big,little"
190 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
191		      (const_string "little") (const_string "big"))))
192
193;; Indicate if the default fpu mode is single precision.
194(define_attr "fpu_single" "yes,no"
195  (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
196                         (const_string "yes") (const_string "no"))))
197
198(define_attr "fmovd" "yes,no"
199  (const (if_then_else (symbol_ref "TARGET_FMOVD")
200		       (const_string "yes") (const_string "no"))))
201;; pipeline model
202(define_attr "pipe_model" "sh1,sh4,sh5media"
203  (const
204   (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
205          (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
206         (const_string "sh1"))))
207
208;; cbranch	conditional branch instructions
209;; jump		unconditional jumps
210;; arith	ordinary arithmetic
211;; arith3	a compound insn that behaves similarly to a sequence of
212;;		three insns of type arith
213;; arith3b	like above, but might end with a redirected branch
214;; load		from memory
215;; load_si	Likewise, SImode variant for general register.
216;; fload	Likewise, but load to fp register.
217;; store	to memory
218;; fstore	floating point register to memory
219;; move		general purpose register to register
220;; movi8	8-bit immediate to general purpose register
221;; mt_group	other sh4 mt instructions
222;; fmove	register to register, floating point
223;; smpy		word precision integer multiply
224;; dmpy		longword or doublelongword precision integer multiply
225;; return	rts
226;; pload	load of pr reg, which can't be put into delay slot of rts
227;; prset	copy register to pr reg, ditto
228;; pstore	store of pr reg, which can't be put into delay slot of jsr
229;; prget	copy pr to register, ditto
230;; pcload	pc relative load of constant value
231;; pcfload	Likewise, but load to fp register.
232;; pcload_si	Likewise, SImode variant for general register.
233;; rte		return from exception
234;; sfunc	special function call with known used registers
235;; call		function call
236;; fp		floating point
237;; fpscr_toggle	toggle a bit in the fpscr
238;; fdiv		floating point divide (or square root)
239;; gp_fpul	move from general purpose register to fpul
240;; fpul_gp	move from fpul to general purpose register
241;; mac_gp	move from mac[lh] to general purpose register
242;; gp_mac	move from general purpose register to mac[lh]
243;; mac_mem	move from mac[lh] to memory
244;; mem_mac	move from memory to mac[lh]
245;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
246;; ftrc_s	fix_truncsfsi2_i4
247;; dfdiv	double precision floating point divide (or square root)
248;; cwb		ic_invalidate_line_i
249;; movua	SH4a unaligned load
250;; fsrra	square root reciprocal approximate
251;; fsca		sine and cosine approximate
252;; tls_load     load TLS related address
253;; arith_media	SHmedia arithmetic, logical, and shift instructions
254;; cbranch_media SHmedia conditional branch instructions
255;; cmp_media	SHmedia compare instructions
256;; dfdiv_media	SHmedia double precision divide and square root
257;; dfmul_media	SHmedia double precision multiply instruction
258;; dfparith_media SHmedia double precision floating point arithmetic
259;; dfpconv_media SHmedia double precision floating point conversions
260;; dmpy_media	SHmedia longword multiply
261;; fcmp_media	SHmedia floating point compare instructions
262;; fdiv_media	SHmedia single precision divide and square root
263;; fload_media	SHmedia floating point register load instructions
264;; fmove_media	SHmedia floating point register moves (inc. fabs and fneg)
265;; fparith_media SHmedia single precision floating point arithmetic
266;; fpconv_media	SHmedia single precision floating point conversions
267;; fstore_media	SHmedia floating point register store instructions
268;; gettr_media	SHmedia gettr instruction
269;; invalidate_line_media SHmedia invalidate_line sequence
270;; jump_media	SHmedia unconditional branch instructions
271;; load_media	SHmedia general register load instructions
272;; pt_media	SHmedia pt instruction (expanded by assembler)
273;; ptabs_media	SHmedia ptabs instruction
274;; store_media	SHmedia general register store instructions
275;; mcmp_media	SHmedia multimedia compare, absolute, saturating ops
276;; mac_media	SHmedia mac-style fixed point operations
277;; d2mpy_media	SHmedia: two 32-bit integer multiplies
278;; atrans_media	SHmedia approximate transcendental functions
279;; ustore_media	SHmedia unaligned stores
280;; nil		no-op move, will be deleted.
281
282(define_attr "type"
283 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other"
284  (const_string "other"))
285
286;; We define a new attribute namely "insn_class".We use
287;; this for the DFA based pipeline description.
288;;
289;; mt_group      SH4 "mt" group instructions.
290;;
291;; ex_group      SH4 "ex" group instructions.
292;;
293;; ls_group      SH4 "ls" group instructions.
294;;
295
296(define_attr "insn_class"
297  "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
298  (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
299         (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
300	 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
301	 (eq_attr "type" "cbranch,jump") (const_string "br_group")
302	 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
303	   (const_string "fe_group")
304	 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,gp_mac,mac_mem,mem_mac") (const_string "co_group")]
305	(const_string "none")))
306;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
307;; so these do not belong in an insn group, although they are modeled
308;; with their own define_insn_reservations.
309
310;; Indicate what precision must be selected in fpscr for this insn, if any.
311
312(define_attr "fp_mode" "single,double,none" (const_string "none"))
313
314;; Indicate if the fpu mode is set by this instruction
315;; "unknown" must have the value as "none" in fp_mode, and means
316;; that the instruction/abi has left the processor in an unknown
317;; state.
318;; "none" means that nothing has changed and no mode is set.
319;; This attribute is only used for the Renesas ABI.
320(define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
321
322; If a conditional branch destination is within -252..258 bytes away
323; from the instruction it can be 2 bytes long.  Something in the
324; range -4090..4100 bytes can be 6 bytes long.  All other conditional
325; branches are initially assumed to be 16 bytes long.
326; In machine_dependent_reorg, we split all branches that are longer than
327; 2 bytes.
328
329;; The maximum range used for SImode constant pool entries is 1018.  A final
330;; instruction can add 8 bytes while only being 4 bytes in size, thus we
331;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
332;; instruction around the pool table, 2 bytes of alignment before the table,
333;; and 30 bytes of alignment after the table.  That gives a maximum total
334;; pool size of 1058 bytes.
335;; Worst case code/pool content size ratio is 1:2 (using asms).
336;; Thus, in the worst case, there is one instruction in front of a maximum
337;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
338;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
339;; If we have a forward branch, the initial table will be put after the
340;; unconditional branch.
341;;
342;; ??? We could do much better by keeping track of the actual pcloads within
343;; the branch range and in the pcload range in front of the branch range.
344
345;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
346;; inside an le.
347(define_attr "short_cbranch_p" "no,yes"
348  (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
349	 (const_string "no")
350	 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
351	 (const_string "yes")
352	 (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
353	 (const_string "no")
354	 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
355	 (const_string "yes")
356         ] (const_string "no")))
357
358(define_attr "med_branch_p" "no,yes"
359  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
360	      (const_int 1988))
361	 (const_string "yes")
362	 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
363	 (const_string "no")
364	 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
365	      (const_int 8186))
366	 (const_string "yes")
367	 ] (const_string "no")))
368
369(define_attr "med_cbranch_p" "no,yes"
370  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
371	      (const_int 1986))
372	 (const_string "yes")
373	 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
374	 (const_string "no")
375	 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
376	       (const_int 8184))
377	 (const_string "yes")
378	 ] (const_string "no")))
379
380(define_attr "braf_branch_p" "no,yes"
381  (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
382	 (const_string "no")
383	 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
384	      (const_int 20660))
385	 (const_string "yes")
386	 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
387	 (const_string "no")
388	 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
389	      (const_int 65530))
390	 (const_string "yes")
391	 ] (const_string "no")))
392
393(define_attr "braf_cbranch_p" "no,yes"
394  (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
395	 (const_string "no")
396	 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
397	      (const_int 20658))
398	 (const_string "yes")
399	 (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
400	 (const_string "no")
401	 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
402	      (const_int 65528))
403	 (const_string "yes")
404	 ] (const_string "no")))
405
406; An unconditional jump in the range -4092..4098 can be 2 bytes long.
407; For wider ranges, we need a combination of a code and a data part.
408; If we can get a scratch register for a long range jump, the code
409; part can be 4 bytes long; otherwise, it must be 8 bytes long.
410; If the jump is in the range -32764..32770, the data part can be 2 bytes
411; long; otherwise, it must be 6 bytes long.
412
413; All other instructions are two bytes long by default.
414
415;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
416;; but getattrtab doesn't understand this.
417(define_attr "length" ""
418  (cond [(eq_attr "type" "cbranch")
419	 (cond [(eq_attr "short_cbranch_p" "yes")
420		(const_int 2)
421		(eq_attr "med_cbranch_p" "yes")
422		(const_int 6)
423		(eq_attr "braf_cbranch_p" "yes")
424		(const_int 12)
425;; ??? using pc is not computed transitively.
426		(ne (match_dup 0) (match_dup 0))
427		(const_int 14)
428		(ne (symbol_ref ("flag_pic")) (const_int 0))
429		(const_int 24)
430		] (const_int 16))
431	 (eq_attr "type" "jump")
432	 (cond [(eq_attr "med_branch_p" "yes")
433		(const_int 2)
434		(and (ne (symbol_ref "prev_nonnote_insn (insn)")
435			 (const_int 0))
436		     (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
437			      (symbol_ref "INSN"))
438			  (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
439			      (symbol_ref "code_for_indirect_jump_scratch"))))
440                (cond [(eq_attr "braf_branch_p" "yes")
441                       (const_int 6)
442                       (eq (symbol_ref "flag_pic") (const_int 0))
443                       (const_int 10)
444                       (ne (symbol_ref "TARGET_SH2") (const_int 0))
445                       (const_int 10)] (const_int 18))
446		(eq_attr "braf_branch_p" "yes")
447		(const_int 10)
448;; ??? using pc is not computed transitively.
449		(ne (match_dup 0) (match_dup 0))
450		(const_int 12)
451		(ne (symbol_ref ("flag_pic")) (const_int 0))
452		(const_int 22)
453		] (const_int 14))
454	 (eq_attr "type" "pt_media")
455	 (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
456		       (const_int 20) (const_int 12))
457	 (and (eq_attr "type" "jump_media")
458	      (ne (symbol_ref "TARGET_SH5_CUT2_WORKAROUND") (const_int 0)))
459	 (const_int 8)
460	 ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
461			 (const_int 4)
462			 (const_int 2))))
463
464;; DFA descriptions for the pipelines
465
466(include "sh1.md")
467(include "shmedia.md")
468(include "sh4.md")
469
470(include "predicates.md")
471(include "constraints.md")
472
473;; Definitions for filling delay slots
474
475(define_attr "needs_delay_slot" "yes,no" (const_string "no"))
476
477(define_attr "banked" "yes,no" 
478	(cond [(eq (symbol_ref "sh_loads_bankedreg_p (insn)")
479		   (const_int 1))
480	       (const_string "yes")]
481	      (const_string "no")))
482
483;; ??? This should be (nil) instead of (const_int 0)
484(define_attr "hit_stack" "yes,no"
485	(cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
486		   (const_int 0))
487	       (const_string "no")]
488	      (const_string "yes")))
489
490(define_attr "interrupt_function" "no,yes"
491  (const (symbol_ref "current_function_interrupt")))
492
493(define_attr "in_delay_slot" "yes,no"
494  (cond [(eq_attr "type" "cbranch") (const_string "no")
495	 (eq_attr "type" "pcload,pcload_si") (const_string "no")
496	 (eq_attr "needs_delay_slot" "yes") (const_string "no")
497	 (eq_attr "length" "2") (const_string "yes")
498	 ] (const_string "no")))
499
500(define_attr "cond_delay_slot" "yes,no"
501  (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
502	 ] (const_string "no")))
503
504(define_attr "is_sfunc" ""
505  (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
506
507(define_attr "is_mac_media" ""
508  (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
509
510(define_attr "branch_zero" "yes,no"
511  (cond [(eq_attr "type" "!cbranch") (const_string "no")
512	 (ne (symbol_ref "(next_active_insn (insn)\
513			   == (prev_active_insn\
514			       (XEXP (SET_SRC (PATTERN (insn)), 1))))\
515			  && get_attr_length (next_active_insn (insn)) == 2")
516	     (const_int 0))
517	 (const_string "yes")]
518	(const_string "no")))
519
520;; SH4 Double-precision computation with double-precision result -
521;; the two halves are ready at different times.
522(define_attr "dfp_comp" "yes,no"
523  (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
524	(const_string "no")))
525
526;; Insns for which the latency of a preceding fp insn is decreased by one.
527(define_attr "late_fp_use" "yes,no" (const_string "no"))
528;; And feeding insns for which this relevant.
529(define_attr "any_fp_comp" "yes,no"
530  (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
531	 (const_string "yes")]
532	(const_string "no")))
533
534(define_attr "any_int_load" "yes,no"
535  (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
536	 (const_string "yes")]
537	(const_string "no")))
538
539(define_attr "highpart" "user, ignore, extend, depend, must_split"
540  (const_string "user"))
541
542(define_delay
543  (eq_attr "needs_delay_slot" "yes")
544  [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
545
546;; On the SH and SH2, the rte instruction reads the return pc from the stack,
547;; and thus we can't put a pop instruction in its delay slot.
548;; ??? On the SH3, the rte instruction does not use the stack, so a pop
549;; instruction can go in the delay slot.
550
551;; Since a normal return (rts) implicitly uses the PR register,
552;; we can't allow PR register loads in an rts delay slot.
553
554(define_delay
555  (eq_attr "type" "return")
556  [(and (eq_attr "in_delay_slot" "yes")
557	(ior (and (eq_attr "interrupt_function" "no")
558		  (eq_attr "type" "!pload,prset"))
559	     (and (eq_attr "interrupt_function" "yes")
560		  (ior
561		   (eq (symbol_ref "TARGET_SH3") (const_int 0))
562		   (eq_attr "hit_stack" "no")
563		   (eq_attr "banked" "no"))))) (nil) (nil)])
564
565;; Since a call implicitly uses the PR register, we can't allow
566;; a PR register store in a jsr delay slot.
567
568(define_delay
569  (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
570  [(and (eq_attr "in_delay_slot" "yes")
571	(eq_attr "type" "!pstore,prget")) (nil) (nil)])
572
573;; Say that we have annulled true branches, since this gives smaller and
574;; faster code when branches are predicted as not taken.
575
576;; ??? The non-annulled condition should really be "in_delay_slot",
577;; but insns that can be filled in non-annulled get priority over insns
578;; that can only be filled in anulled.
579
580(define_delay
581  (and (eq_attr "type" "cbranch")
582       (ne (symbol_ref "TARGET_SH2") (const_int 0)))
583  ;; SH2e has a hardware bug that pretty much prohibits the use of
584  ;; annuled delay slots.
585  [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
586					  (not (eq_attr "cpu" "sh2e"))) (nil)])
587
588;; -------------------------------------------------------------------------
589;; SImode signed integer comparisons
590;; -------------------------------------------------------------------------
591
592(define_insn ""
593  [(set (reg:SI T_REG)
594	(eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
595		       (match_operand:SI 1 "logical_operand" "K08,r"))
596	       (const_int 0)))]
597  "TARGET_SH1"
598  "tst	%1,%0"
599  [(set_attr "type" "mt_group")])
600
601;; ??? Perhaps should only accept reg/constant if the register is reg 0.
602;; That would still allow reload to create cmpi instructions, but would
603;; perhaps allow forcing the constant into a register when that is better.
604;; Probably should use r0 for mem/imm compares, but force constant into a
605;; register for pseudo/imm compares.
606
607(define_insn "cmpeqsi_t"
608  [(set (reg:SI T_REG)
609	(eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
610	       (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
611  "TARGET_SH1"
612  "@
613	tst	%0,%0
614	cmp/eq	%1,%0
615	cmp/eq	%1,%0"
616   [(set_attr "type" "mt_group")])
617
618(define_insn "cmpgtsi_t"
619  [(set (reg:SI T_REG)
620	(gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
621	       (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
622  "TARGET_SH1"
623  "@
624	cmp/gt	%1,%0
625	cmp/pl	%0"
626   [(set_attr "type" "mt_group")])
627
628(define_insn "cmpgesi_t"
629  [(set (reg:SI T_REG)
630	(ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
631	       (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
632  "TARGET_SH1"
633  "@
634	cmp/ge	%1,%0
635	cmp/pz	%0"
636   [(set_attr "type" "mt_group")])
637
638;; -------------------------------------------------------------------------
639;; SImode compare and branch
640;; -------------------------------------------------------------------------
641
642(define_expand "cbranchsi4"
643  [(set (pc)
644	(if_then_else (match_operator 0 "comparison_operator"
645			[(match_operand:SI 1 "arith_operand" "")
646			 (match_operand:SI 2 "arith_operand" "")])
647		      (label_ref (match_operand 3 "" ""))
648		      (pc)))
649   (clobber (reg:SI T_REG))]
650  ""
651  "if (TARGET_SHMEDIA)
652      emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
653					     operands[2], operands[3]));
654   else if (TARGET_CBRANCHDI4)
655     expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
656   else
657     sh_emit_compare_and_branch (operands, SImode);
658   DONE;")
659
660;; -------------------------------------------------------------------------
661;; SImode unsigned integer comparisons
662;; -------------------------------------------------------------------------
663
664(define_insn_and_split "cmpgeusi_t"
665  [(set (reg:SI T_REG)
666	(geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
667		(match_operand:SI 1 "arith_reg_or_0_operand" "rN")))]
668  "TARGET_SH1"
669  "cmp/hs	%1,%0"
670  "&& operands[1] == CONST0_RTX (SImode)"
671  [(pc)]
672  "
673{
674  emit_insn (gen_sett ());
675  DONE;
676}"
677   [(set_attr "type" "mt_group")])
678
679(define_insn "cmpgtusi_t"
680  [(set (reg:SI T_REG)
681	(gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
682		(match_operand:SI 1 "arith_reg_operand" "r")))]
683  "TARGET_SH1"
684  "cmp/hi	%1,%0"
685   [(set_attr "type" "mt_group")])
686
687
688;; -------------------------------------------------------------------------
689;; DImode compare and branch
690;; -------------------------------------------------------------------------
691
692
693;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
694;; Therefore, we aim to have a set of three branches that go straight to the
695;; destination, i.e. only one of them is taken at any one time.
696;; This mechanism should also be slightly better for the sh4-200.
697
698(define_expand "cbranchdi4"
699  [(set (pc)
700	(if_then_else (match_operator 0 "comparison_operator"
701			[(match_operand:DI 1 "arith_operand" "")
702			 (match_operand:DI 2 "arith_operand" "")])
703		      (label_ref (match_operand 3 "" ""))
704		      (pc)))
705   (clobber (match_dup 4))
706   (clobber (reg:SI T_REG))]
707  "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
708  "
709{
710  enum rtx_code comparison;
711
712  if (TARGET_SHMEDIA)
713    {
714      emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
715					     operands[2], operands[3]));
716      DONE;
717    }
718
719  else if (!TARGET_CBRANCHDI4)
720    {
721      sh_emit_compare_and_branch (operands, DImode);
722      DONE;
723    }
724
725  else
726    {
727      if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
728	DONE;
729
730      comparison = prepare_cbranch_operands (operands, DImode,
731					     LAST_AND_UNUSED_RTX_CODE);
732      if (comparison != GET_CODE (operands[0]))
733        operands[0]
734          = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
735       operands[4] = gen_rtx_SCRATCH (SImode);
736    }
737}")
738
739(define_insn_and_split "cbranchdi4_i"
740  [(set (pc)
741	(if_then_else (match_operator 0 "comparison_operator"
742			[(match_operand:DI 1 "arith_operand" "r,r")
743			 (match_operand:DI 2 "arith_operand" "rN,I08")])
744		      (label_ref (match_operand 3 "" ""))
745		      (pc)))
746   (clobber (match_scratch:SI 4 "=X,&r"))
747   (clobber (reg:SI T_REG))]
748  "TARGET_CBRANCHDI4"
749  "#"
750  "&& reload_completed"
751  [(pc)]
752  "
753{
754  if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
755    FAIL;
756  DONE;
757}")
758
759;; -------------------------------------------------------------------------
760;; DImode signed integer comparisons
761;; -------------------------------------------------------------------------
762
763(define_insn ""
764  [(set (reg:SI T_REG)
765	(eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
766		       (match_operand:DI 1 "arith_operand" "r"))
767	       (const_int 0)))]
768  "TARGET_SH1"
769  "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
770				 insn, operands);"
771  [(set_attr "length" "6")
772   (set_attr "type" "arith3b")])
773
774(define_insn "cmpeqdi_t"
775  [(set (reg:SI T_REG)
776	(eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
777	       (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
778  "TARGET_SH1"
779  "@
780	tst	%S0,%S0\;bf	%,Ldi%=\;tst	%R0,%R0\\n%,Ldi%=:
781	cmp/eq	%S1,%S0\;bf	%,Ldi%=\;cmp/eq	%R1,%R0\\n%,Ldi%=:"
782  [(set_attr "length" "6")
783   (set_attr "type" "arith3b")])
784
785(define_split
786  [(set (reg:SI T_REG)
787	(eq:SI (match_operand:DI 0 "arith_reg_operand" "")
788	       (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
789;; If we applied this split when not optimizing, it would only be
790;; applied during the machine-dependent reorg, when no new basic blocks
791;; may be created.
792  "TARGET_SH1 && reload_completed && optimize"
793  [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
794   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
795			   (label_ref (match_dup 6))
796			   (pc)))
797   (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
798   (match_dup 6)]
799  "
800{
801  operands[2]
802    = gen_rtx_REG (SImode,
803		   true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
804  operands[3]
805    = (operands[1] == const0_rtx
806       ? const0_rtx
807       : gen_rtx_REG (SImode,
808		      true_regnum (operands[1])
809		      + (TARGET_LITTLE_ENDIAN ? 1 : 0)));
810  operands[4] = gen_lowpart (SImode, operands[0]);
811  operands[5] = gen_lowpart (SImode, operands[1]);
812  operands[6] = gen_label_rtx ();
813}")
814
815(define_insn "cmpgtdi_t"
816  [(set (reg:SI T_REG)
817	(gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
818	       (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
819  "TARGET_SH2"
820  "@
821	cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
822	tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
823  [(set_attr "length" "8")
824   (set_attr "type" "arith3")])
825
826(define_insn "cmpgedi_t"
827  [(set (reg:SI T_REG)
828	(ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
829	       (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
830  "TARGET_SH2"
831  "@
832	cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
833	cmp/pz\\t%S0"
834  [(set_attr "length" "8,2")
835   (set_attr "type" "arith3,mt_group")])
836
837;; -------------------------------------------------------------------------
838;; DImode unsigned integer comparisons
839;; -------------------------------------------------------------------------
840
841(define_insn "cmpgeudi_t"
842  [(set (reg:SI T_REG)
843	(geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
844		(match_operand:DI 1 "arith_reg_operand" "r")))]
845  "TARGET_SH2"
846  "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
847  [(set_attr "length" "8")
848   (set_attr "type" "arith3")])
849
850(define_insn "cmpgtudi_t"
851  [(set (reg:SI T_REG)
852	(gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
853		(match_operand:DI 1 "arith_reg_operand" "r")))]
854  "TARGET_SH2"
855  "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
856  [(set_attr "length" "8")
857   (set_attr "type" "arith3")])
858
859(define_insn "cmpeqsi_media"
860  [(set (match_operand:SI 0 "register_operand" "=r")
861	(eq:SI (match_operand:SI 1 "logical_operand" "%r")
862	       (match_operand:SI 2 "cmp_operand" "Nr")))]
863  "TARGET_SHMEDIA"
864  "cmpeq	%1, %N2, %0"
865  [(set_attr "type" "cmp_media")])
866
867(define_insn "cmpeqdi_media"
868  [(set (match_operand:SI 0 "register_operand" "=r")
869	(eq:SI (match_operand:DI 1 "register_operand" "%r")
870	       (match_operand:DI 2 "cmp_operand" "Nr")))]
871  "TARGET_SHMEDIA"
872  "cmpeq	%1, %N2, %0"
873  [(set_attr "type" "cmp_media")])
874
875(define_insn "cmpgtsi_media"
876  [(set (match_operand:SI 0 "register_operand" "=r")
877	(gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
878	       (match_operand:SI 2 "cmp_operand" "rN")))]
879  "TARGET_SHMEDIA"
880  "cmpgt	%N1, %N2, %0"
881  [(set_attr "type" "cmp_media")])
882
883(define_insn "cmpgtdi_media"
884  [(set (match_operand:SI 0 "register_operand" "=r")
885	(gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
886	       (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
887  "TARGET_SHMEDIA"
888  "cmpgt	%N1, %N2, %0"
889  [(set_attr "type" "cmp_media")])
890
891(define_insn "cmpgtusi_media"
892  [(set (match_operand:SI 0 "register_operand" "=r")
893	(gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
894		(match_operand:SI 2 "cmp_operand" "rN")))]
895  "TARGET_SHMEDIA"
896  "cmpgtu	%N1, %N2, %0"
897  [(set_attr "type" "cmp_media")])
898
899(define_insn "cmpgtudi_media"
900  [(set (match_operand:SI 0 "register_operand" "=r")
901	(gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
902		(match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
903  "TARGET_SHMEDIA"
904  "cmpgtu	%N1, %N2, %0"
905  [(set_attr "type" "cmp_media")])
906
907; These two patterns are for combine.
908(define_insn "*cmpne0sisi_media"
909  [(set (match_operand:SI 0 "register_operand" "=r")
910	(ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
911  "TARGET_SHMEDIA"
912  "cmpgtu	%1,r63,%0"
913  [(set_attr "type" "cmp_media")])
914
915;; -------------------------------------------------------------------------
916;; Conditional move instructions
917;; -------------------------------------------------------------------------
918
919;; The insn names may seem reversed, but note that cmveq performs the move
920;; if op1 == 0, and cmvne does it if op1 != 0.
921
922(define_insn "movdicc_false"
923  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
924	(if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
925			     (const_int 0))
926	 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
927	 (match_operand:DI 3 "arith_reg_operand" "0")))]
928  "TARGET_SHMEDIA"
929  "cmveq	%1, %N2, %0"
930  [(set_attr "type" "arith_media")])
931
932(define_insn "movdicc_true"
933  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
934	(if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
935			     (const_int 0))
936	 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
937	 (match_operand:DI 3 "arith_reg_operand" "0")))]
938  "TARGET_SHMEDIA"
939  "cmvne	%1, %N2, %0"
940  [(set_attr "type" "arith_media")])
941
942(define_peephole2
943  [(set (match_operand:DI 0 "arith_reg_dest" "")
944	(if_then_else:DI (match_operator 3 "equality_comparison_operator"
945			   [(match_operand:DI 1 "arith_reg_operand" "")
946			    (const_int 0)])
947	 (match_operand:DI 2 "arith_reg_dest" "")
948	 (match_dup 0)))
949   (set (match_dup 2) (match_dup 0))]
950  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
951  [(set (match_dup 2)
952	(if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
953  "
954{
955  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
956				VOIDmode, operands[1], CONST0_RTX (DImode));
957}")
958
959(define_peephole2
960  [(set (match_operand:DI 0 "general_movdst_operand" "")
961	(match_operand:DI 1 "arith_reg_or_0_operand" ""))
962   (set (match_operand:DI 2 "arith_reg_dest" "")
963	(if_then_else:DI (match_operator 4 "equality_comparison_operator"
964			   [(match_operand:DI 3 "arith_reg_operand" "")
965			    (const_int 0)])
966	 (match_dup 0)
967	 (match_dup 2)))]
968  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
969  [(set (match_dup 2)
970	(if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
971  "")
972
973(define_expand "movdicc"
974  [(set (match_operand:DI 0 "register_operand" "")
975	(if_then_else:DI (match_operand 1 "comparison_operator" "")
976			 (match_operand:DI 2 "register_operand" "")
977			 (match_operand:DI 3 "register_operand" "")))]
978  "TARGET_SHMEDIA"
979  "
980{
981  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
982      && GET_MODE (XEXP (operands[1], 0)) == DImode
983      && XEXP (operands[1], 1) == const0_rtx)
984    ;
985  else
986    {
987      if (!can_create_pseudo_p ())
988	FAIL;
989
990      operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
991					      GET_CODE (operands[1]),
992					      XEXP (operands[1], 0),
993	                                      XEXP (operands[1], 1));
994      if (!operands[1])
995	FAIL;
996    }
997}")
998
999;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1000;; SImode to DImode.
1001(define_insn "movsicc_false"
1002  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1003	(if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1004			  (const_int 0))
1005	 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1006	 (match_operand:SI 3 "arith_reg_operand" "0")))]
1007  "TARGET_SHMEDIA"
1008  "cmveq	%1, %N2, %0"
1009  [(set_attr "type" "arith_media")])
1010
1011(define_insn "movsicc_true"
1012  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1013	(if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1014			  (const_int 0))
1015	 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1016	 (match_operand:SI 3 "arith_reg_operand" "0")))]
1017  "TARGET_SHMEDIA"
1018  "cmvne	%1, %N2, %0"
1019  [(set_attr "type" "arith_media")])
1020
1021(define_peephole2
1022  [(set (match_operand:SI 0 "arith_reg_dest" "")
1023	(if_then_else:SI (match_operator 3 "equality_comparison_operator"
1024			   [(match_operand:SI 1 "arith_reg_operand" "")
1025			    (const_int 0)])
1026	 (match_operand:SI 2 "arith_reg_dest" "")
1027	 (match_dup 0)))
1028   (set (match_dup 2) (match_dup 0))]
1029  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1030  [(set (match_dup 2)
1031	(if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1032  "
1033{
1034  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1035				VOIDmode, operands[1], CONST0_RTX (SImode));
1036}")
1037
1038(define_peephole2
1039  [(set (match_operand:SI 0 "general_movdst_operand" "")
1040	(match_operand:SI 1 "arith_reg_or_0_operand" ""))
1041   (set (match_operand:SI 2 "arith_reg_dest" "")
1042	(if_then_else:SI (match_operator 4 "equality_comparison_operator"
1043			   [(match_operand:SI 3 "arith_reg_operand" "")
1044			    (const_int 0)])
1045	 (match_dup 0)
1046	 (match_dup 2)))]
1047  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1048   && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1049  [(set (match_dup 2)
1050	(if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1051  "
1052{
1053  replace_rtx (operands[4], operands[0], operands[1]);
1054}")
1055
1056(define_peephole2
1057  [(set (match_operand 0 "any_register_operand" "")
1058	(match_operand 1 "any_register_operand" ""))
1059   (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1060   (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1061  "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1062    <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1063   && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1064   && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1065   && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1066   && ! reg_overlap_mentioned_p (operands[0], operands[3])
1067   && ! reg_overlap_mentioned_p (operands[2], operands[0])
1068   && ! reg_overlap_mentioned_p (operands[0], operands[1])
1069   && (REGNO_REG_CLASS (REGNO (operands[0]))
1070       == REGNO_REG_CLASS (REGNO (operands[2])))
1071   && (REGNO_REG_CLASS (REGNO (operands[1]))
1072       == REGNO_REG_CLASS (REGNO (operands[0])))"
1073  [(set (match_dup 0) (match_dup 3))
1074   (set (match_dup 4) (match_dup 5))]
1075  "
1076{
1077  rtx set1, set2, insn2;
1078  rtx replacements[4];
1079
1080  /* We want to replace occurrences of operands[0] with operands[1] and
1081     operands[2] with operands[0] in operands[4]/operands[5].
1082     Doing just two replace_rtx calls naively would result in the second
1083     replacement undoing all that the first did if operands[1] and operands[2]
1084     are identical, so we must do this simultaneously.  */
1085  replacements[0] = operands[0];
1086  replacements[1] = operands[1];
1087  replacements[2] = operands[2];
1088  replacements[3] = operands[0];
1089  if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1090      || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1091      || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1092    FAIL;
1093
1094  operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1095  replace_n_hard_rtx (operands[4], replacements, 2, 1);
1096  operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1097  /* The operands array is aliased to recog_data.operand, which gets
1098     clobbered by extract_insn, so finish with it now.  */
1099  set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1100  set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1101  /* ??? The last insn might be a jump insn, but the generic peephole2 code
1102     always uses emit_insn.  */
1103  /* Check that we don't violate matching constraints or earlyclobbers.  */
1104  extract_insn (emit_insn (set1));
1105  if (! constrain_operands (1))
1106    goto failure;
1107  insn2 = emit (set2);
1108  if (GET_CODE (insn2) == BARRIER)
1109    goto failure;
1110  extract_insn (insn2);
1111  if (! constrain_operands (1))
1112    {
1113      rtx tmp;
1114    failure:
1115      tmp = replacements[0];
1116      replacements[0] = replacements[1];
1117      replacements[1] = tmp;
1118      tmp = replacements[2];
1119      replacements[2] = replacements[3];
1120      replacements[3] = tmp;
1121      replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1122      replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1123      replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1124      FAIL;
1125    }
1126  DONE;
1127}")
1128
1129;; The register allocator is rather clumsy in handling multi-way conditional
1130;; moves, so allow the combiner to make them, and we split them up after
1131;; reload.  */
1132(define_insn_and_split "*movsicc_umin"
1133  [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1134	(umin:SI (if_then_else:SI
1135		   (eq (match_operand:SI 1 "arith_reg_operand" "r")
1136		       (const_int 0))
1137		   (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1138		   (match_operand:SI 3 "register_operand" "0"))
1139		 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1140   (clobber (match_scratch:SI 5 "=&r"))]
1141  "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1142  "#"
1143  "TARGET_SHMEDIA && reload_completed"
1144  [(pc)]
1145  "
1146{
1147  emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1148				operands[3]));
1149  emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1150  emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1151				operands[0]));
1152  DONE;
1153}")
1154
1155(define_insn "*movsicc_t_false"
1156  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1157	(if_then_else (eq (reg:SI T_REG) (const_int 0))
1158		      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1159		      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1160  "TARGET_PRETEND_CMOVE
1161   && (arith_reg_operand (operands[1], SImode)
1162       || (immediate_operand (operands[1], SImode)
1163	   && satisfies_constraint_I08 (operands[1])))"
1164  "bt 0f\;mov %1,%0\\n0:"
1165  [(set_attr "type" "mt_group,arith") ;; poor approximation
1166   (set_attr "length" "4")])
1167
1168(define_insn "*movsicc_t_true"
1169  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1170	(if_then_else (ne (reg:SI T_REG) (const_int 0))
1171		      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1172		      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1173  "TARGET_PRETEND_CMOVE
1174   && (arith_reg_operand (operands[1], SImode)
1175       || (immediate_operand (operands[1], SImode)
1176	   && satisfies_constraint_I08 (operands[1])))"
1177  "bf 0f\;mov %1,%0\\n0:"
1178  [(set_attr "type" "mt_group,arith") ;; poor approximation
1179   (set_attr "length" "4")])
1180
1181(define_expand "movsicc"
1182  [(set (match_operand:SI 0 "arith_reg_dest" "")
1183	(if_then_else:SI (match_operand 1 "comparison_operator" "")
1184			 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1185			 (match_operand:SI 3 "arith_reg_operand" "")))]
1186  "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1187  "
1188{
1189  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1190      && GET_MODE (XEXP (operands[1], 0)) == SImode
1191      && (TARGET_SHMEDIA
1192	  || (REG_P (XEXP (operands[1], 0))
1193	      && REGNO (XEXP (operands[1], 0)) == T_REG))
1194      && XEXP (operands[1], 1) == const0_rtx)
1195    ;
1196
1197  else if (TARGET_PRETEND_CMOVE)
1198    {
1199      enum rtx_code code = GET_CODE (operands[1]);
1200      enum rtx_code new_code = code;
1201      rtx op0 = XEXP (operands[1], 0);
1202      rtx op1 = XEXP (operands[1], 1);
1203
1204      if (! currently_expanding_to_rtl)
1205	FAIL;
1206      switch (code)
1207	{
1208	case LT: case LE: case LEU: case LTU:
1209	  if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1210	    break;
1211	case NE:
1212	  new_code = reverse_condition (code);
1213	  break;
1214	case EQ: case GT: case GE: case GEU: case GTU:
1215	  break;
1216	default:
1217	  FAIL;
1218	}
1219      sh_emit_scc_to_t (new_code, op0, op1);
1220      operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1221				    gen_rtx_REG (SImode, T_REG), const0_rtx);
1222    }
1223  else
1224    {
1225      if (!can_create_pseudo_p ())
1226	FAIL;
1227
1228      operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1229					      GET_CODE (operands[1]),
1230					      XEXP (operands[1], 0),
1231	                                      XEXP (operands[1], 1));
1232      if (!operands[1])
1233	FAIL;
1234    }
1235}")
1236
1237(define_expand "movqicc"
1238  [(set (match_operand:QI 0 "register_operand" "")
1239	(if_then_else:QI (match_operand 1 "comparison_operator" "")
1240			 (match_operand:QI 2 "register_operand" "")
1241			 (match_operand:QI 3 "register_operand" "")))]
1242  "TARGET_SHMEDIA"
1243  "
1244{
1245  operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1246  operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1247  operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1248  emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1249  DONE;
1250}")
1251
1252;; -------------------------------------------------------------------------
1253;; Addition instructions
1254;; -------------------------------------------------------------------------
1255
1256(define_expand "adddi3"
1257  [(set (match_operand:DI 0 "arith_reg_operand" "")
1258	(plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1259		 (match_operand:DI 2 "arith_operand" "")))]
1260  ""
1261  "
1262{
1263  if (TARGET_SH1)
1264    {
1265      if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
1266        FAIL;
1267      operands[2] = force_reg (DImode, operands[2]);
1268      emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1269      DONE;
1270    }
1271}")
1272
1273(define_insn "*adddi3_media"
1274  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1275	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1276		 (match_operand:DI 2 "arith_operand" "r,I10")))]
1277  "TARGET_SHMEDIA"
1278  "@
1279	add	%1, %2, %0
1280	addi	%1, %2, %0"
1281  [(set_attr "type" "arith_media")])
1282
1283(define_insn "*adddisi3_media"
1284  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1285	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1286		 (match_operand:DI 2 "arith_operand" "r,I10")))]
1287  "TARGET_SHMEDIA"
1288  "@
1289	add.l	%1, %2, %0
1290	addi.l	%1, %2, %0"
1291  [(set_attr "type" "arith_media")
1292   (set_attr "highpart" "ignore")])
1293
1294(define_insn "adddi3z_media"
1295  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1296	(zero_extend:DI
1297	 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1298		  (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1299  "TARGET_SHMEDIA"
1300  "addz.l	%1, %N2, %0"
1301  [(set_attr "type" "arith_media")
1302   (set_attr "highpart" "ignore")])
1303
1304(define_insn "adddi3_compact"
1305  [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1306	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1307		 (match_operand:DI 2 "arith_reg_operand" "r")))
1308   (clobber (reg:SI T_REG))]
1309  "TARGET_SH1"
1310  "#"
1311  [(set_attr "length" "6")])
1312
1313(define_split
1314  [(set (match_operand:DI 0 "arith_reg_dest" "")
1315	(plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1316		 (match_operand:DI 2 "arith_reg_operand" "")))
1317   (clobber (reg:SI T_REG))]
1318  "TARGET_SH1 && reload_completed"
1319  [(const_int 0)]
1320  "
1321{
1322  rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1323  high0 = gen_rtx_REG (SImode,
1324		       true_regnum (operands[0])
1325		       + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1326  high2 = gen_rtx_REG (SImode,
1327		       true_regnum (operands[2])
1328		       + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1329  emit_insn (gen_clrt ());
1330  emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1331  emit_insn (gen_addc1 (high0, high0, high2));
1332  DONE;
1333}")
1334
1335(define_insn "addc"
1336  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1337	(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1338			  (match_operand:SI 2 "arith_reg_operand" "r"))
1339		 (reg:SI T_REG)))
1340   (set (reg:SI T_REG)
1341	(ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1342  "TARGET_SH1"
1343  "addc	%2,%0"
1344  [(set_attr "type" "arith")])
1345
1346(define_insn "addc1"
1347  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1348	(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1349			  (match_operand:SI 2 "arith_reg_operand" "r"))
1350		 (reg:SI T_REG)))
1351   (clobber (reg:SI T_REG))]
1352  "TARGET_SH1"
1353  "addc	%2,%0"
1354  [(set_attr "type" "arith")])
1355
1356(define_expand "addsi3"
1357  [(set (match_operand:SI 0 "arith_reg_operand" "")
1358	(plus:SI (match_operand:SI 1 "arith_operand" "")
1359		 (match_operand:SI 2 "arith_operand" "")))]
1360  ""
1361  "
1362{
1363  if (TARGET_SHMEDIA)
1364    operands[1] = force_reg (SImode, operands[1]);
1365}")
1366
1367(define_insn "addsi3_media"
1368  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1369	(plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1370		 (match_operand:SI 2 "arith_operand" "r,I10")))]
1371  "TARGET_SHMEDIA"
1372  "@
1373	add.l	%1, %2, %0
1374	addi.l	%1, %2, %0"
1375  [(set_attr "type" "arith_media")
1376   (set_attr "highpart" "ignore")])
1377
1378(define_insn "addsidi3_media"
1379  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1380	(sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1381				  "%r,r")
1382				 (match_operand:SI 2 "arith_operand"
1383				  "r,I10"))))]
1384  "TARGET_SHMEDIA"
1385  "@
1386	add.l	%1, %2, %0
1387	addi.l	%1, %2, %0"
1388  [(set_attr "type" "arith_media")
1389   (set_attr "highpart" "ignore")])
1390
1391(define_insn "*addsi3_compact"
1392  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1393	(plus:SI (match_operand:SI 1 "arith_operand" "%0")
1394		 (match_operand:SI 2 "arith_operand" "rI08")))]
1395  "TARGET_SH1"
1396  "add	%2,%0"
1397  [(set_attr "type" "arith")])
1398
1399;; -------------------------------------------------------------------------
1400;; Subtraction instructions
1401;; -------------------------------------------------------------------------
1402
1403(define_expand "subdi3"
1404  [(set (match_operand:DI 0 "arith_reg_operand" "")
1405	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1406		  (match_operand:DI 2 "arith_reg_operand" "")))]
1407  ""
1408  "
1409{
1410  if (TARGET_SH1)
1411    {
1412      operands[1] = force_reg (DImode, operands[1]);
1413      emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1414      DONE;
1415    }
1416}")
1417
1418(define_insn "*subdi3_media"
1419  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1420	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1421		  (match_operand:DI 2 "arith_reg_operand" "r")))]
1422  "TARGET_SHMEDIA"
1423  "sub	%N1, %2, %0"
1424  [(set_attr "type" "arith_media")])
1425  
1426(define_insn "subdisi3_media"
1427  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1428	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1429		  (match_operand:DI 2 "arith_reg_operand" "r")))]
1430  "TARGET_SHMEDIA"
1431  "sub.l	%N1, %2, %0"
1432  [(set_attr "type" "arith_media")
1433   (set_attr "highpart" "ignore")])
1434
1435(define_insn "subdi3_compact"
1436  [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1437	(minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1438		 (match_operand:DI 2 "arith_reg_operand" "r")))
1439   (clobber (reg:SI T_REG))]
1440  "TARGET_SH1"
1441  "#"
1442  [(set_attr "length" "6")])
1443
1444(define_split
1445  [(set (match_operand:DI 0 "arith_reg_dest" "")
1446	(minus:DI (match_operand:DI 1 "arith_reg_operand" "")
1447		  (match_operand:DI 2 "arith_reg_operand" "")))
1448   (clobber (reg:SI T_REG))]
1449  "TARGET_SH1 && reload_completed"
1450  [(const_int 0)]
1451  "
1452{
1453  rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
1454  high0 = gen_rtx_REG (SImode,
1455		       true_regnum (operands[0])
1456		       + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1457  high2 = gen_rtx_REG (SImode,
1458		       true_regnum (operands[2])
1459		       + (TARGET_LITTLE_ENDIAN ? 1 : 0));
1460  emit_insn (gen_clrt ());
1461  emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1462  emit_insn (gen_subc1 (high0, high0, high2));
1463  DONE;
1464}")
1465
1466(define_insn "subc"
1467  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1468	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1469			    (match_operand:SI 2 "arith_reg_operand" "r"))
1470		  (reg:SI T_REG)))
1471   (set (reg:SI T_REG)
1472	(gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1473			  (reg:SI T_REG))
1474		(match_dup 1)))]
1475  "TARGET_SH1"
1476  "subc	%2,%0"
1477  [(set_attr "type" "arith")])
1478
1479(define_insn "subc1"
1480  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1481	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1482			    (match_operand:SI 2 "arith_reg_operand" "r"))
1483		  (reg:SI T_REG)))
1484   (clobber (reg:SI T_REG))]
1485  "TARGET_SH1"
1486  "subc	%2,%0"
1487  [(set_attr "type" "arith")])
1488
1489;; life_analysis thinks rn is live before subc rn,rn, so make a special
1490;; pattern for this case.  This helps multimedia applications that compute
1491;; the sum of absolute differences.
1492(define_insn "mov_neg_si_t"
1493  [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))]
1494  "TARGET_SH1"
1495  "subc	%0,%0"
1496  [(set_attr "type" "arith")])
1497
1498(define_insn "*subsi3_internal"
1499  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1500	(minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1501		  (match_operand:SI 2 "arith_reg_operand" "r")))]
1502  "TARGET_SH1"
1503  "sub	%2,%0"
1504  [(set_attr "type" "arith")])
1505
1506(define_insn_and_split "*subsi3_media"
1507  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1508	(minus:SI (match_operand:SI 1 "minuend_operand" "rN")
1509		  (match_operand:SI 2 "extend_reg_operand" "r")))]
1510  "TARGET_SHMEDIA
1511   && (operands[1] != constm1_rtx
1512       || (GET_CODE (operands[2]) != TRUNCATE
1513	   && GET_CODE (operands[2]) != SUBREG))"
1514  "sub.l	%N1, %2, %0"
1515  "operands[1] == constm1_rtx"
1516  [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
1517  ""
1518  [(set_attr "type" "arith_media")
1519   (set_attr "highpart" "ignore")])
1520
1521(define_split
1522  [(set (match_operand:SI 0 "arith_reg_dest" "")
1523	(zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1524						       "general_extend_operand"
1525						       "") 0)) 0)))]
1526  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
1527  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1528   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1529  "")
1530
1531(define_split
1532  [(set (match_operand:SI 0 "arith_reg_dest" "")
1533	(zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
1534						       "general_extend_operand"
1535						       "") 0)) 3)))]
1536  "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
1537  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
1538   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
1539  "")
1540;; Convert `constant - reg' to `neg rX; add rX, #const' since this
1541;; will sometimes save one instruction.  Otherwise we might get
1542;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
1543;; are the same.
1544
1545(define_expand "subsi3"
1546  [(set (match_operand:SI 0 "arith_reg_operand" "")
1547	(minus:SI (match_operand:SI 1 "arith_operand" "")
1548		  (match_operand:SI 2 "arith_reg_operand" "")))]
1549  ""
1550  "
1551{
1552  if (TARGET_SH1 && CONST_INT_P (operands[1]))
1553    {
1554      emit_insn (gen_negsi2 (operands[0], operands[2]));
1555      emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
1556      DONE;
1557    }
1558  if (TARGET_SHMEDIA)
1559    {
1560      if (!can_create_pseudo_p ()
1561	  && ! arith_reg_or_0_operand (operands[1], SImode))
1562	FAIL;
1563      if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
1564	operands[1] = force_reg (SImode, operands[1]);
1565    }
1566}")
1567
1568;; -------------------------------------------------------------------------
1569;; Division instructions
1570;; -------------------------------------------------------------------------
1571
1572;; We take advantage of the library routines which don't clobber as many
1573;; registers as a normal function call would.
1574
1575;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
1576;; also has an effect on the register that holds the address of the sfunc.
1577;; To make this work, we have an extra dummy insn that shows the use
1578;; of this register for reorg.
1579
1580(define_insn "use_sfunc_addr"
1581  [(set (reg:SI PR_REG)
1582	(unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
1583  "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1584  ""
1585  [(set_attr "length" "0")])
1586
1587(define_insn "udivsi3_sh2a"
1588  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1589	(udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
1590		(match_operand:SI 2 "arith_reg_operand" "z")))]
1591  "TARGET_SH2A"
1592  "divu	%2,%1"
1593  [(set_attr "type" "arith")
1594   (set_attr "in_delay_slot" "no")])
1595
1596;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
1597;; hard register 0.  If we used hard register 0, then the next instruction
1598;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
1599;; gets allocated to a stack slot that needs its address reloaded, then
1600;; there is nothing to prevent reload from using r0 to reload the address.
1601;; This reload would clobber the value in r0 we are trying to store.
1602;; If we let reload allocate r0, then this problem can never happen.
1603
1604(define_insn "udivsi3_i1"
1605  [(set (match_operand:SI 0 "register_operand" "=z")
1606	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1607   (clobber (reg:SI T_REG))
1608   (clobber (reg:SI PR_REG))
1609   (clobber (reg:SI R4_REG))
1610   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1611  "TARGET_SH1 && ! TARGET_SH4"
1612  "jsr	@%1%#"
1613  [(set_attr "type" "sfunc")
1614   (set_attr "needs_delay_slot" "yes")])
1615
1616; Since shmedia-nofpu code could be linked against shcompact code, and
1617; the udivsi3 libcall has the same name, we must consider all registers
1618; clobbered that are in the union of the registers clobbered by the
1619; shmedia and the shcompact implementation.  Note, if the shcompact
1620; implementation actually used shcompact code, we'd need to clobber
1621; also r23 and fr23.
1622(define_insn "udivsi3_i1_media"
1623  [(set (match_operand:SI 0 "register_operand" "=z")
1624	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1625   (clobber (reg:SI T_MEDIA_REG))
1626   (clobber (reg:SI PR_MEDIA_REG))
1627   (clobber (reg:SI R20_REG))
1628   (clobber (reg:SI R21_REG))
1629   (clobber (reg:SI R22_REG))
1630   (clobber (reg:DI TR0_REG))
1631   (clobber (reg:DI TR1_REG))
1632   (clobber (reg:DI TR2_REG))
1633   (use (match_operand 1 "target_reg_operand" "b"))]
1634  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1635  "blink	%1, r18"
1636  [(set_attr "type" "sfunc")
1637   (set_attr "needs_delay_slot" "yes")])
1638
1639(define_expand "udivsi3_i4_media"
1640  [(set (match_dup 3)
1641	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
1642   (set (match_dup 4)
1643	(zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1644   (set (match_dup 5) (float:DF (match_dup 3)))
1645   (set (match_dup 6) (float:DF (match_dup 4)))
1646   (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
1647   (set (match_dup 8) (fix:DI (match_dup 7)))
1648   (set (match_operand:SI 0 "register_operand" "")
1649	(truncate:SI (match_dup 8)))]
1650  "TARGET_SHMEDIA_FPU"
1651  "
1652{
1653  operands[3] = gen_reg_rtx (DImode);
1654  operands[4] = gen_reg_rtx (DImode);
1655  operands[5] = gen_reg_rtx (DFmode);
1656  operands[6] = gen_reg_rtx (DFmode);
1657  operands[7] = gen_reg_rtx (DFmode);
1658  operands[8] = gen_reg_rtx (DImode);
1659}")
1660
1661(define_insn "udivsi3_i4"
1662  [(set (match_operand:SI 0 "register_operand" "=y")
1663	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1664   (clobber (reg:SI T_REG))
1665   (clobber (reg:SI PR_REG))
1666   (clobber (reg:DF DR0_REG))
1667   (clobber (reg:DF DR2_REG))
1668   (clobber (reg:DF DR4_REG))
1669   (clobber (reg:SI R0_REG))
1670   (clobber (reg:SI R1_REG))
1671   (clobber (reg:SI R4_REG))
1672   (clobber (reg:SI R5_REG))
1673   (use (reg:PSI FPSCR_REG))
1674   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1675  "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1676  "jsr	@%1%#"
1677  [(set_attr "type" "sfunc")
1678   (set_attr "fp_mode" "double")
1679   (set_attr "needs_delay_slot" "yes")])
1680
1681(define_insn "udivsi3_i4_single"
1682  [(set (match_operand:SI 0 "register_operand" "=y")
1683	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1684   (clobber (reg:SI T_REG))
1685   (clobber (reg:SI PR_REG))
1686   (clobber (reg:DF DR0_REG))
1687   (clobber (reg:DF DR2_REG))
1688   (clobber (reg:DF DR4_REG))
1689   (clobber (reg:SI R0_REG))
1690   (clobber (reg:SI R1_REG))
1691   (clobber (reg:SI R4_REG))
1692   (clobber (reg:SI R5_REG))
1693   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1694  "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1695  "jsr	@%1%#"
1696  [(set_attr "type" "sfunc")
1697   (set_attr "needs_delay_slot" "yes")])
1698
1699(define_insn "udivsi3_i4_int"
1700  [(set (match_operand:SI 0 "register_operand" "=z")
1701	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1702   (clobber (reg:SI T_REG))
1703   (clobber (reg:SI R1_REG))
1704   (clobber (reg:SI PR_REG))
1705   (clobber (reg:SI MACH_REG))
1706   (clobber (reg:SI MACL_REG))
1707   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1708  "TARGET_SH1"
1709  "jsr	@%1%#"
1710  [(set_attr "type" "sfunc")
1711   (set_attr "needs_delay_slot" "yes")])
1712
1713
1714(define_expand "udivsi3"
1715  [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
1716   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1717   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1718   (parallel [(set (match_operand:SI 0 "register_operand" "")
1719		   (udiv:SI (reg:SI R4_REG)
1720			    (reg:SI R5_REG)))
1721	      (clobber (reg:SI T_REG))
1722	      (clobber (reg:SI PR_REG))
1723	      (clobber (reg:SI R4_REG))
1724	      (use (match_dup 3))])]
1725  ""
1726  "
1727{
1728  rtx last;
1729
1730  operands[3] = gen_reg_rtx (Pmode);
1731  /* Emit the move of the address to a pseudo outside of the libcall.  */
1732  if (TARGET_DIVIDE_CALL_TABLE)
1733    {
1734      /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
1735	 that causes problems when the divide code is supposed to come from a
1736	 separate library.  Division by zero is undefined, so dividing 1 can be
1737	 implemented by comparing with the divisor.  */
1738      if (operands[1] == const1_rtx && currently_expanding_to_rtl)
1739	{
1740	  rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
1741	  emit_insn (gen_cstoresi4 (operands[0], test,
1742				    operands[1], operands[2]));
1743	  DONE;
1744	}
1745      else if (operands[2] == const0_rtx)
1746	{
1747	  emit_move_insn (operands[0], operands[2]);
1748	  DONE;
1749	}
1750      function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
1751      last = gen_udivsi3_i4_int (operands[0], operands[3]);
1752    }
1753  else if (TARGET_DIVIDE_CALL_FP)
1754    {
1755      function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC);
1756      if (TARGET_FPU_SINGLE)
1757	last = gen_udivsi3_i4_single (operands[0], operands[3]);
1758      else
1759	last = gen_udivsi3_i4 (operands[0], operands[3]);
1760    }
1761  else if (TARGET_SHMEDIA_FPU)
1762    {
1763      operands[1] = force_reg (SImode, operands[1]);
1764      operands[2] = force_reg (SImode, operands[2]);
1765      emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
1766      DONE;
1767    }
1768  else if (TARGET_SH2A)
1769    {
1770      operands[1] = force_reg (SImode, operands[1]);
1771      operands[2] = force_reg (SImode, operands[2]);
1772      emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
1773      DONE;
1774    }
1775  else if (TARGET_SH5)
1776    {
1777      function_symbol (operands[3],
1778		       TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\",
1779		       SFUNC_STATIC);
1780
1781      if (TARGET_SHMEDIA)
1782	last = gen_udivsi3_i1_media (operands[0], operands[3]);
1783      else if (TARGET_FPU_ANY)
1784	last = gen_udivsi3_i4_single (operands[0], operands[3]);
1785      else
1786	last = gen_udivsi3_i1 (operands[0], operands[3]);
1787    }
1788  else
1789    {
1790      function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
1791      last = gen_udivsi3_i1 (operands[0], operands[3]);
1792    }
1793  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
1794  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
1795  emit_insn (last);
1796  DONE;
1797}")
1798
1799(define_insn "divsi3_sh2a"
1800  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1801	(div:SI (match_operand:SI 1 "arith_reg_operand" "0")
1802		(match_operand:SI 2 "arith_reg_operand" "z")))]
1803  "TARGET_SH2A"
1804  "divs	%2,%1"
1805  [(set_attr "type" "arith")
1806   (set_attr "in_delay_slot" "no")])
1807
1808(define_insn "divsi3_i1"
1809  [(set (match_operand:SI 0 "register_operand" "=z")
1810	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1811   (clobber (reg:SI T_REG))
1812   (clobber (reg:SI PR_REG))
1813   (clobber (reg:SI R1_REG))
1814   (clobber (reg:SI R2_REG))
1815   (clobber (reg:SI R3_REG))
1816   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1817  "TARGET_SH1 && ! TARGET_SH4"
1818  "jsr	@%1%#"
1819  [(set_attr "type" "sfunc")
1820   (set_attr "needs_delay_slot" "yes")])
1821
1822(define_insn "divsi3_i1_media"
1823  [(set (match_operand:SI 0 "register_operand" "=z")
1824	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1825   (clobber (reg:SI T_MEDIA_REG))
1826   (clobber (reg:SI PR_MEDIA_REG))
1827   (clobber (reg:SI R1_REG))
1828   (clobber (reg:SI R20_REG))
1829   (clobber (reg:SI R21_REG))
1830   (clobber (reg:SI TR0_REG))
1831   (use (match_operand 1 "target_reg_operand" "b"))]
1832  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1833  "blink	%1, r18"
1834  [(set_attr "type" "sfunc")])
1835
1836(define_insn "divsi3_media_2"
1837  [(set (match_operand:SI 0 "register_operand" "=z")
1838	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1839   (clobber (reg:SI T_MEDIA_REG))
1840   (clobber (reg:SI PR_MEDIA_REG))
1841   (clobber (reg:SI R1_REG))
1842   (clobber (reg:SI R21_REG))
1843   (clobber (reg:SI TR0_REG))
1844   (use (reg:SI R20_REG))
1845   (use (match_operand 1 "target_reg_operand" "b"))]
1846  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
1847  "blink	%1, r18"
1848  [(set_attr "type" "sfunc")])
1849
1850;; This pattern acts as a placeholder for -mdiv=inv:call to carry
1851;; hard reg clobbers and data dependencies that we need when we want
1852;; to rematerialize the division into a call.
1853(define_insn_and_split "divsi_inv_call"
1854  [(set (match_operand:SI 0 "register_operand" "=r")
1855	(div:SI (match_operand:SI 1 "register_operand" "r")
1856		(match_operand:SI 2 "register_operand" "r")))
1857   (clobber (reg:SI R4_REG))
1858   (clobber (reg:SI R5_REG))
1859   (clobber (reg:SI T_MEDIA_REG))
1860   (clobber (reg:SI PR_MEDIA_REG))
1861   (clobber (reg:SI R1_REG))
1862   (clobber (reg:SI R21_REG))
1863   (clobber (reg:SI TR0_REG))
1864   (clobber (reg:SI R20_REG))
1865   (use (match_operand:SI 3 "register_operand" "r"))]
1866  "TARGET_SHMEDIA"
1867  "#"
1868  "&& (high_life_started || reload_completed)"
1869  [(set (match_dup 0) (match_dup 3))]
1870  ""
1871  [(set_attr "highpart" "must_split")])
1872
1873;; This is the combiner pattern for -mdiv=inv:call .
1874(define_insn_and_split "*divsi_inv_call_combine"
1875  [(set (match_operand:SI 0 "register_operand" "=z")
1876	(div:SI (match_operand:SI 1 "register_operand" "r")
1877		(match_operand:SI 2 "register_operand" "r")))
1878   (clobber (reg:SI R4_REG))
1879   (clobber (reg:SI R5_REG))
1880   (clobber (reg:SI T_MEDIA_REG))
1881   (clobber (reg:SI PR_MEDIA_REG))
1882   (clobber (reg:SI R1_REG))
1883   (clobber (reg:SI R21_REG))
1884   (clobber (reg:SI TR0_REG))
1885   (clobber (reg:SI R20_REG))
1886   (use (unspec:SI [(match_dup 1)
1887		    (match_operand:SI 3 "" "")
1888		    (unspec:SI [(match_operand:SI 4 "" "")
1889				(match_dup 3)
1890				(match_operand:DI 5 "" "")]
1891		     UNSPEC_DIV_INV_M2)
1892		    (match_operand:DI 6 "" "")
1893		    (const_int 0)
1894		    (const_int 0)]
1895	 UNSPEC_DIV_INV_M3))]
1896  "TARGET_SHMEDIA"
1897  "#"
1898  "&& (high_life_started || reload_completed)"
1899  [(pc)]
1900  "
1901{
1902  const char *name = sh_divsi3_libfunc;
1903  enum sh_function_kind kind = SFUNC_GOT;
1904  rtx sym;
1905
1906  emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
1907  emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
1908  while (TARGET_DIVIDE_INV_CALL2)
1909    {
1910      rtx x = operands[3];
1911
1912      if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
1913	break;
1914      x = XVECEXP (x, 0, 0);
1915      name = \"__sdivsi3_2\";
1916      kind = SFUNC_STATIC;
1917      emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
1918      break;
1919    }
1920  sym = function_symbol (NULL, name, kind);
1921  emit_insn (gen_divsi3_media_2 (operands[0], sym));
1922  DONE;
1923}"
1924  [(set_attr "highpart" "must_split")])
1925
1926(define_expand "divsi3_i4_media"
1927  [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
1928   (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
1929   (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
1930   (set (match_operand:SI 0 "register_operand" "=r")
1931	(fix:SI (match_dup 5)))]
1932  "TARGET_SHMEDIA_FPU"
1933  "
1934{
1935  operands[3] = gen_reg_rtx (DFmode);
1936  operands[4] = gen_reg_rtx (DFmode);
1937  operands[5] = gen_reg_rtx (DFmode);
1938}")
1939
1940(define_insn "divsi3_i4"
1941  [(set (match_operand:SI 0 "register_operand" "=y")
1942	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1943   (clobber (reg:SI PR_REG))
1944   (clobber (reg:DF DR0_REG))
1945   (clobber (reg:DF DR2_REG))
1946   (use (reg:PSI FPSCR_REG))
1947   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1948  "TARGET_SH4 && ! TARGET_FPU_SINGLE"
1949  "jsr	@%1%#"
1950  [(set_attr "type" "sfunc")
1951   (set_attr "fp_mode" "double")
1952   (set_attr "needs_delay_slot" "yes")])
1953
1954(define_insn "divsi3_i4_single"
1955  [(set (match_operand:SI 0 "register_operand" "=y")
1956	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1957   (clobber (reg:SI PR_REG))
1958   (clobber (reg:DF DR0_REG))
1959   (clobber (reg:DF DR2_REG))
1960   (clobber (reg:SI R2_REG))
1961   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1962  "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1963  "jsr	@%1%#"
1964  [(set_attr "type" "sfunc")
1965   (set_attr "needs_delay_slot" "yes")])
1966
1967(define_insn "divsi3_i4_int"
1968  [(set (match_operand:SI 0 "register_operand" "=z")
1969	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
1970   (clobber (reg:SI T_REG))
1971   (clobber (reg:SI PR_REG))
1972   (clobber (reg:SI R1_REG))
1973   (clobber (reg:SI MACH_REG))
1974   (clobber (reg:SI MACL_REG))
1975   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
1976  "TARGET_SH1"
1977  "jsr	@%1%#"
1978  [(set_attr "type" "sfunc")
1979   (set_attr "needs_delay_slot" "yes")])
1980
1981(define_expand "divsi3"
1982  [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
1983   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
1984   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
1985   (parallel [(set (match_operand:SI 0 "register_operand" "")
1986		   (div:SI (reg:SI R4_REG)
1987			   (reg:SI R5_REG)))
1988	      (clobber (reg:SI T_REG))
1989	      (clobber (reg:SI PR_REG))
1990	      (clobber (reg:SI R1_REG))
1991	      (clobber (reg:SI R2_REG))
1992	      (clobber (reg:SI R3_REG))
1993	      (use (match_dup 3))])]
1994  ""
1995  "
1996{
1997  rtx last;
1998
1999  operands[3] = gen_reg_rtx (Pmode);
2000  /* Emit the move of the address to a pseudo outside of the libcall.  */
2001  if (TARGET_DIVIDE_CALL_TABLE)
2002    {
2003      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2004      last = gen_divsi3_i4_int (operands[0], operands[3]);
2005    }
2006  else if (TARGET_DIVIDE_CALL_FP)
2007    {
2008      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2009      if (TARGET_FPU_SINGLE)
2010	last = gen_divsi3_i4_single (operands[0], operands[3]);
2011      else
2012	last = gen_divsi3_i4 (operands[0], operands[3]);
2013    }
2014  else if (TARGET_SH2A)
2015    {
2016      operands[1] = force_reg (SImode, operands[1]);
2017      operands[2] = force_reg (SImode, operands[2]);
2018      emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2019      DONE;
2020    }
2021  else if (TARGET_DIVIDE_INV)
2022    {
2023      rtx dividend = operands[1];
2024      rtx divisor = operands[2];
2025      rtx tab_base;
2026      rtx nsb_res = gen_reg_rtx (DImode);
2027      rtx norm64 = gen_reg_rtx (DImode);
2028      rtx tab_ix = gen_reg_rtx (DImode);
2029      rtx norm32 = gen_reg_rtx (SImode);
2030      rtx i92 = force_reg (DImode, GEN_INT (92));
2031      rtx scratch0a = gen_reg_rtx (DImode);
2032      rtx scratch0b = gen_reg_rtx (DImode);
2033      rtx inv0 = gen_reg_rtx (SImode);
2034      rtx scratch1a = gen_reg_rtx (DImode);
2035      rtx scratch1b = gen_reg_rtx (DImode);
2036      rtx shift = gen_reg_rtx (DImode);
2037      rtx i2p27, i43;
2038      rtx inv1 = gen_reg_rtx (SImode);
2039      rtx scratch2a = gen_reg_rtx (DImode);
2040      rtx scratch2b = gen_reg_rtx (SImode);
2041      rtx inv2 = gen_reg_rtx (SImode);
2042      rtx scratch3a = gen_reg_rtx (DImode);
2043      rtx scratch3b = gen_reg_rtx (DImode);
2044      rtx scratch3c = gen_reg_rtx (DImode);
2045      rtx scratch3d = gen_reg_rtx (SImode);
2046      rtx scratch3e = gen_reg_rtx (DImode);
2047      rtx result = gen_reg_rtx (SImode);
2048
2049      if (! arith_reg_or_0_operand (dividend, SImode))
2050	dividend = force_reg (SImode, dividend);
2051      if (! arith_reg_operand (divisor, SImode))
2052	divisor = force_reg (SImode, divisor);
2053      if (flag_pic && Pmode != DImode)
2054	{
2055	  tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2056	  tab_base = gen_datalabel_ref (tab_base);
2057	  tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2058	}
2059      else
2060	{
2061	  tab_base = gen_rtx_SYMBOL_REF (DImode, \"__div_table\");
2062	  tab_base = gen_datalabel_ref (tab_base);
2063	  tab_base = force_reg (DImode, tab_base);
2064	}
2065      if (TARGET_DIVIDE_INV20U)
2066	i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2067      else
2068	i2p27 = GEN_INT (0);
2069      if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2070	i43 = force_reg (DImode, GEN_INT (43));
2071      else
2072	i43 = GEN_INT (0);
2073      emit_insn (gen_nsbdi (nsb_res,
2074			    simplify_gen_subreg (DImode, divisor, SImode, 0)));
2075      emit_insn (gen_ashldi3_media (norm64,
2076				    gen_rtx_SUBREG (DImode, divisor, 0),
2077				    nsb_res));
2078      emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2079      emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2080      emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2081				   inv0, scratch0a, scratch0b,
2082				   scratch1a, scratch1b));
2083      emit_insn (gen_subdi3 (shift, i92, nsb_res));
2084      emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2085				   scratch2a));
2086      emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2087				   i2p27, i43,
2088				   scratch3a, scratch3b, scratch3c,
2089				   scratch2a, scratch2b, scratch3d, scratch3e));
2090      if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2091	emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2092      else if (TARGET_DIVIDE_INV_FP)
2093	emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2094				     gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2095				     gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2096				     gen_reg_rtx (DFmode)));
2097      else
2098	emit_move_insn (operands[0], result);
2099      DONE;
2100    }
2101  else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2102    {
2103      operands[1] = force_reg (SImode, operands[1]);
2104      operands[2] = force_reg (SImode, operands[2]);
2105      emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2106      DONE;
2107    }
2108  else if (TARGET_SH5)
2109    {
2110      if (TARGET_DIVIDE_CALL2)
2111	{
2112	  rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\");
2113	  tab_base = gen_datalabel_ref (tab_base);
2114	  emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2115	}
2116      if (TARGET_FPU_ANY && TARGET_SH1)
2117	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2118      else if (TARGET_DIVIDE_CALL2)
2119	function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC);
2120      else
2121	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2122
2123      if (TARGET_SHMEDIA)
2124	last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2125		(operands[0], operands[3]));
2126      else if (TARGET_FPU_ANY)
2127	last = gen_divsi3_i4_single (operands[0], operands[3]);
2128      else
2129	last = gen_divsi3_i1 (operands[0], operands[3]);
2130    }
2131  else
2132    {
2133      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2134      last = gen_divsi3_i1 (operands[0], operands[3]);
2135    }
2136  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2137  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2138  emit_insn (last);
2139  DONE;
2140}")
2141
2142;; operands: scratch, tab_base, tab_ix
2143;; These are unspecs because we could generate an indexed addressing mode
2144;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2145;; confuse reload.  See PR27117.
2146
2147(define_insn "divsi_inv_qitable"
2148  [(set (match_operand:DI 0 "register_operand" "=r")
2149	(zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2150				    (match_operand:DI 2 "register_operand" "r")]
2151			 UNSPEC_DIV_INV_TABLE)))]
2152  "TARGET_SHMEDIA"
2153  "@
2154	ldx.ub	%1, %2, %0"
2155  [(set_attr "type" "load_media")
2156   (set_attr "highpart" "user")])
2157
2158;; operands: scratch, tab_base, tab_ix
2159(define_insn "divsi_inv_hitable"
2160  [(set (match_operand:DI 0 "register_operand" "=r")
2161	(sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2162				    (match_operand:DI 2 "register_operand" "r")]
2163			 UNSPEC_DIV_INV_TABLE)))]
2164  "TARGET_SHMEDIA"
2165  "@
2166	ldx.w	%1, %2, %0"
2167  [(set_attr "type" "load_media")
2168   (set_attr "highpart" "user")])
2169
2170;; operands: inv0, tab_base, tab_ix, norm32
2171;; scratch equiv in sdivsi3_2: r19, r21
2172(define_expand "divsi_inv_m0"
2173  [(set (match_operand:SI 0 "register_operand" "=r")
2174	(unspec:SI [(match_operand:DI 1 "register_operand" "r")
2175		    (match_operand:DI 2 "register_operand" "r")
2176		    (match_operand:SI 3 "register_operand" "r")]
2177	 UNSPEC_DIV_INV_M0))
2178   (clobber (match_operand:DI 4 "register_operand" "=r"))
2179   (clobber (match_operand:DI 5 "register_operand" "=r"))]
2180  "TARGET_SHMEDIA"
2181  "
2182{
2183/*
2184tab_base: r20
2185tab_ix: r21
2186norm32: r25
2187 ldx.ub r20, r21, r19 // u0.8
2188 shlli r21, 1, r21
2189 muls.l r25, r19, r19 // s2.38
2190 ldx.w r20, r21, r21  // s2.14
2191 shari r19, 24, r19   // truncate to s2.14
2192 sub r21, r19, r19    // some 11 bit inverse in s1.14
2193*/
2194
2195  rtx inv0 = operands[0];
2196  rtx tab_base = operands[1];
2197  rtx tab_ix = operands[2];
2198  rtx norm32 = operands[3];
2199  rtx scratch0 = operands[4];
2200  rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2201  rtx scratch1 = operands[5];
2202
2203  emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2204  emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2205  emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2206  emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2207  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2208  emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2209  DONE;
2210}")
2211
2212;; operands: inv1, tab_base, tab_ix, norm32
2213(define_insn_and_split "divsi_inv_m1"
2214  [(set (match_operand:SI 0 "register_operand" "=r")
2215	(unspec:SI [(match_operand:DI 1 "register_operand" "r")
2216		    (match_operand:DI 2 "register_operand" "r")
2217		    (match_operand:SI 3 "register_operand" "r")]
2218	 UNSPEC_DIV_INV_M1))
2219   (clobber (match_operand:SI 4 "register_operand" "=r"))
2220   (clobber (match_operand:DI 5 "register_operand" "=r"))
2221   (clobber (match_operand:DI 6 "register_operand" "=r"))
2222   (clobber (match_operand:DI 7 "register_operand" "=r"))
2223   (clobber (match_operand:DI 8 "register_operand" "=r"))]
2224  "TARGET_SHMEDIA"
2225  "#"
2226  "&& !can_create_pseudo_p ()"
2227  [(pc)]
2228  "
2229{
2230/* inv0: r19
2231 muls.l r19, r19, r18 // u0.28
2232 muls.l r25, r18, r18 // s2.58
2233 shlli r19, 45, r0    // multiply by two and convert to s2.58
2234 sub r0, r18, r18
2235 shari r18, 28, r18   // some 18 bit inverse in s1.30
2236*/
2237
2238  rtx inv1 = operands[0];
2239  rtx tab_base = operands[1];
2240  rtx tab_ix = operands[2];
2241  rtx norm32 = operands[3];
2242  rtx inv0 = operands[4];
2243  rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2244  rtx scratch0a = operands[5];
2245  rtx scratch0b = operands[6];
2246  rtx scratch0 = operands[7];
2247  rtx scratch1 = operands[8];
2248  rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2249
2250  emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2251			       scratch0a, scratch0b));
2252  emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2253  emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2254  emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2255  emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2256  emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2257  DONE;
2258}")
2259
2260;; operands: inv2, norm32, inv1, i92
2261(define_insn_and_split "divsi_inv_m2"
2262  [(set (match_operand:SI 0 "register_operand" "=r")
2263	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
2264		    (match_operand:SI 2 "register_operand" "r")
2265		    (match_operand:DI 3 "register_operand" "r")]
2266	 UNSPEC_DIV_INV_M2))
2267   (clobber (match_operand:DI 4 "register_operand" "=r"))]
2268  "TARGET_SHMEDIA"
2269  "#"
2270  "&& !can_create_pseudo_p ()"
2271  [(pc)]
2272  "
2273{
2274/*
2275 muls.l r18, r25, r0  // s2.60
2276 shari r0, 16, r0     // s-16.44
2277  sub
2278 muls.l r0, r18, r19  // s-16.74
2279 shari r19, 30, r19   // s-16.44
2280*/
2281  rtx inv2 = operands[0];
2282  rtx norm32 = operands[1];
2283  rtx inv1 = operands[2];
2284  rtx i92 = operands[3];
2285  rtx scratch0 = operands[4];
2286  rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2287
2288  emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2289  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2290  emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2291  emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2292  emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2293  DONE;
2294}")
2295
2296(define_insn_and_split "divsi_inv_m3"
2297  [(set (match_operand:SI 0 "register_operand" "=r")
2298	(unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2299		    (match_operand:SI 2 "register_operand" "r")
2300		    (match_operand:SI 3 "register_operand" "r")
2301		    (match_operand:DI 4 "register_operand" "r")
2302		    (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2303		    (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2304	 UNSPEC_DIV_INV_M3))
2305   (clobber (match_operand:DI 7 "register_operand" "=r"))
2306   (clobber (match_operand:DI 8 "register_operand" "=r"))
2307   (clobber (match_operand:DI 9 "register_operand" "=r"))
2308   (clobber (match_operand:DI 10 "register_operand" "=r"))
2309   (clobber (match_operand:SI 11 "register_operand" "=r"))
2310   (clobber (match_operand:SI 12 "register_operand" "=r"))
2311   (clobber (match_operand:DI 13 "register_operand" "=r"))]
2312  "TARGET_SHMEDIA"
2313  "#"
2314  "&& !can_create_pseudo_p ()"
2315  [(pc)]
2316  "
2317{
2318/*
2319  r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
2320  r0: scratch0  r19: scratch1 r21: scratch2
2321
2322  muls.l r18, r4, r25 // s32.30
2323 muls.l r19, r4, r19  // s15.30
2324 shari r25, 63, r21
2325  shari r19, 14, r19  // s18.-14
2326 sub r25, r19, r0
2327 shard r0, r1, r0
2328 sub r0, r21, r0
2329*/
2330
2331  rtx result = operands[0];
2332  rtx dividend = operands[1];
2333  rtx inv1 = operands[2];
2334  rtx inv2 = operands[3];
2335  rtx shift = operands[4];
2336  rtx scratch0 = operands[7];
2337  rtx scratch1 = operands[8];
2338  rtx scratch2 = operands[9];
2339
2340  if (satisfies_constraint_N (dividend))
2341    {
2342      emit_move_insn (result, dividend);
2343      DONE;
2344    }
2345
2346  emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2347  emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2348  emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2349  emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2350  emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2351  emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2352  emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2353  DONE;
2354}")
2355
2356;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2357;; inv1: tab_base, tab_ix, norm32
2358;; inv2: norm32, inv1, i92
2359(define_insn_and_split "divsi_inv_m1_3"
2360  [(set (match_operand:SI 0 "register_operand" "=r")
2361	(unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2362		    (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2363				(match_operand:DI 3 "register_operand" "r")
2364				(match_operand:SI 4 "register_operand" "r")]
2365		     UNSPEC_DIV_INV_M1)
2366		    (unspec:SI [(match_dup 4)
2367				(unspec:SI [(match_dup 2)
2368					    (match_dup 3)
2369					    (match_dup 4)] UNSPEC_DIV_INV_M1)
2370				(match_operand:SI 5 "" "")]
2371		     UNSPEC_DIV_INV_M2)
2372		    (match_operand:DI 6 "register_operand" "r")
2373		    (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2374		    (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2375	 UNSPEC_DIV_INV_M3))
2376   (clobber (match_operand:DI 9 "register_operand" "=r"))
2377   (clobber (match_operand:DI 10 "register_operand" "=r"))
2378   (clobber (match_operand:DI 11 "register_operand" "=r"))
2379   (clobber (match_operand:DI 12 "register_operand" "=r"))
2380   (clobber (match_operand:SI 13 "register_operand" "=r"))
2381   (clobber (match_operand:SI 14 "register_operand" "=r"))
2382   (clobber (match_operand:DI 15 "register_operand" "=r"))]
2383  "TARGET_SHMEDIA
2384   && (TARGET_DIVIDE_INV_MINLAT
2385       || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2386  "#"
2387  "&& !can_create_pseudo_p ()"
2388  [(pc)]
2389  "
2390{
2391  rtx result = operands[0];
2392  rtx dividend = operands[1];
2393  rtx tab_base = operands[2];
2394  rtx tab_ix = operands[3];
2395  rtx norm32 = operands[4];
2396  /* rtx i92 = operands[5]; */
2397  rtx shift = operands[6];
2398  rtx i2p27 = operands[7];
2399  rtx i43 = operands[8];
2400  rtx scratch0 = operands[9];
2401  rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF);
2402  rtx scratch1 = operands[10];
2403  rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF);
2404  rtx scratch2 = operands[11];
2405  rtx scratch3 = operands[12];
2406  rtx scratch4 = operands[13];
2407  rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2408  rtx scratch5 = operands[14];
2409  rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2410  rtx scratch6 = operands[15];
2411
2412  emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2413			       scratch0, scratch1));
2414  /* inv0 == scratch4 */
2415  if (! TARGET_DIVIDE_INV20U)
2416    {
2417      emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2418      i2p27 = scratch0;
2419      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2420    }
2421  else
2422    {
2423      emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2424      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2425    }
2426  emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2427  emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2428  emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2429  /* inv1 == scratch4 */
2430
2431  if (TARGET_DIVIDE_INV_MINLAT)
2432    {
2433      emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2434      emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2435      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2436      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2437      emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2438      emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2439      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2440      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2441      emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2442      emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2443      emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2444    }
2445  else
2446    {
2447      rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2448      /* Use separate scratch regs for nsb and sign to allow scheduling.  */
2449      emit_insn (gen_nsbdi (scratch6,
2450			    simplify_gen_subreg (DImode, dividend, SImode, 0)));
2451      emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2452      emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2453      emit_insn (gen_divsi_inv20 (scratch2,
2454				  norm32, scratch4, dividend,
2455				  scratch6, scratch3, i43,
2456				  /* scratch0 may be shared with i2p27.  */
2457				  scratch0, scratch1, scratch5,
2458				  label, label, i2p27));
2459    }
2460  emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2461  emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2462  DONE;
2463}")
2464
2465(define_insn "divsi_inv20"
2466  [(set (match_operand:DI 0 "register_operand" "=&r")
2467	(unspec:DI [(match_operand:SI 1 "register_operand" "r")
2468		    (match_operand:SI 2 "register_operand" "r")
2469		    (match_operand:SI 3 "register_operand" "r")
2470		    (match_operand:DI 4 "register_operand" "r")
2471		    (match_operand:DI 5 "register_operand" "r")
2472		    (match_operand:DI 6 "register_operand" "r")
2473		    (match_operand:DI 12 "register_operand" "r")
2474		    (match_operand 10 "target_operand" "b")
2475		    (match_operand 11 "immediate_operand" "i")]
2476	 UNSPEC_DIV_INV20))
2477   (clobber (match_operand:DI 7 "register_operand" "=&r"))
2478   (clobber (match_operand:DI 8 "register_operand" "=&r"))
2479   (clobber (match_operand:SI 9 "register_operand" "=r"))]
2480  "TARGET_SHMEDIA
2481   && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2482  "*
2483{
2484/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2485	     %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2486	     %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2487	     %10 label (tr), %11 label (imm)
2488
2489 muls.l inv1, norm32, scratch0  // s2.60
2490  muls.l inv1, dividend, result // s32.30
2491  xor i2p27, result_sign, round_scratch
2492 bge/u dividend_nsb, i43, tr.. (label)
2493 shari scratch0, 16, scratch0   // s-16.44
2494 muls.l sratch0_si, inv1, scratch0 // s-16.74
2495  sub result, round_scratch, result
2496  shari dividend, 14, scratch1   // s19.-14
2497 shari scratch0, 30, scratch0   // s-16.44
2498 muls.l scratch0, scratch1, round_scratch // s15.30
2499label:
2500 sub result, round_scratch, result */
2501
2502  int likely = TARGET_DIVIDE_INV20L;
2503
2504  if (! likely) output_asm_insn (\"muls.l\t%2, %1 , %8\", operands);
2505  output_asm_insn (\"muls.l\t%2, %3, %0\;xor\t%12, %5, %7\", operands);
2506  output_asm_insn (likely
2507		   ? \"bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8\"
2508		   : \"bge/u\t%4, %6, %10\", operands);
2509  output_asm_insn (\"shari\t%8, 16, %8\;muls.l\t%8, %2, %8\", operands);
2510  if (! likely) output_asm_insn (\"sub\t%0, %7, %0\", operands);
2511  output_asm_insn (\"shari\t%3, 14, %9\;shari\t%8, 30, %8\", operands);
2512  return (likely
2513	  ? \"muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0\"
2514	  : \"muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0\");
2515}")
2516
2517(define_insn_and_split "divsi_inv_fp"
2518  [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
2519	(div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
2520		(match_operand:SI 2 "register_operand" "rf")))
2521   (use (match_operand:SI 3 "general_movsrc_operand" "r"))
2522   (clobber (match_operand:SI 4 "register_operand" "=r"))
2523   (clobber (match_operand:SI 5 "register_operand" "=r"))
2524   (clobber (match_operand:DF 6 "register_operand" "=r"))
2525   (clobber (match_operand:DF 7 "register_operand" "=r"))
2526   (clobber (match_operand:DF 8 "register_operand" "=r"))]
2527  "TARGET_SHMEDIA_FPU"
2528  "#"
2529  "&& (high_life_started || reload_completed)"
2530  [(set (match_dup 0) (match_dup 3))]
2531  ""
2532  [(set_attr "highpart" "must_split")])
2533
2534;; If a matching group of divide-by-inverse instructions is in the same
2535;; basic block after gcse & loop optimizations, we want to transform them
2536;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
2537(define_insn_and_split "*divsi_inv_fp_combine"
2538  [(set (match_operand:SI 0 "register_operand" "=f")
2539	(div:SI (match_operand:SI 1 "register_operand" "f")
2540		(match_operand:SI 2 "register_operand" "f")))
2541   (use (unspec:SI [(match_dup 1)
2542		    (match_operand:SI 3 "" "")
2543		    (unspec:SI [(match_operand:SI 4 "" "")
2544				(match_dup 3)
2545				(match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
2546		    (match_operand:DI 6 "" "")
2547		    (const_int 0)
2548		    (const_int 0)] UNSPEC_DIV_INV_M3))
2549   (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
2550   (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
2551   (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
2552   (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
2553   (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
2554  "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
2555  "#"
2556  "&& 1"
2557  [(set (match_dup 9) (float:DF (match_dup 1)))
2558   (set (match_dup 10) (float:DF (match_dup 2)))
2559   (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
2560   (set (match_dup 8)
2561	(fix:SI (match_dup 11)))
2562   (set (match_dup 0) (match_dup 8))]
2563  "
2564{
2565  if (! fp_arith_reg_operand (operands[1], SImode))
2566    {
2567      emit_move_insn (operands[7], operands[1]);
2568      operands[1] = operands[7];
2569    }
2570  if (! fp_arith_reg_operand (operands[2], SImode))
2571    {
2572      emit_move_insn (operands[8], operands[2]);
2573      operands[2] = operands[8];
2574    }
2575}"
2576  [(set_attr "highpart" "must_split")])
2577
2578;; -------------------------------------------------------------------------
2579;; Multiplication instructions
2580;; -------------------------------------------------------------------------
2581
2582(define_insn "umulhisi3_i"
2583  [(set (reg:SI MACL_REG)
2584	(mult:SI (zero_extend:SI
2585		  (match_operand:HI 0 "arith_reg_operand" "r"))
2586		 (zero_extend:SI
2587		  (match_operand:HI 1 "arith_reg_operand" "r"))))]
2588  "TARGET_SH1"
2589  "mulu.w	%1,%0"
2590  [(set_attr "type" "smpy")])
2591
2592(define_insn "mulhisi3_i"
2593  [(set (reg:SI MACL_REG)
2594	(mult:SI (sign_extend:SI
2595		  (match_operand:HI 0 "arith_reg_operand" "r"))
2596		 (sign_extend:SI
2597		  (match_operand:HI 1 "arith_reg_operand" "r"))))]
2598  "TARGET_SH1"
2599  "muls.w	%1,%0"
2600  [(set_attr "type" "smpy")])
2601
2602(define_expand "mulhisi3"
2603  [(set (reg:SI MACL_REG)
2604	(mult:SI (sign_extend:SI
2605		  (match_operand:HI 1 "arith_reg_operand" ""))
2606		 (sign_extend:SI
2607		  (match_operand:HI 2 "arith_reg_operand" ""))))
2608   (set (match_operand:SI 0 "arith_reg_operand" "")
2609	(reg:SI MACL_REG))]
2610  "TARGET_SH1"
2611  "
2612{
2613  rtx insn, macl;
2614
2615  macl = gen_rtx_REG (SImode, MACL_REG);
2616  start_sequence ();
2617  emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
2618  insn = get_insns ();  
2619  end_sequence ();
2620  /* expand_binop can't find a suitable code in umul_widen_optab to
2621     make a REG_EQUAL note from, so make one here.
2622     See also smulsi3_highpart.
2623     ??? Alternatively, we could put this at the calling site of expand_binop,
2624     i.e. expand_expr.  */
2625  /* Use emit_libcall_block for loop invariant code motion and to make
2626     a REG_EQUAL note.  */
2627  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2628
2629  DONE;
2630}")
2631
2632(define_expand "umulhisi3"
2633  [(set (reg:SI MACL_REG)
2634	(mult:SI (zero_extend:SI
2635		  (match_operand:HI 1 "arith_reg_operand" ""))
2636		 (zero_extend:SI
2637		  (match_operand:HI 2 "arith_reg_operand" ""))))
2638   (set (match_operand:SI 0 "arith_reg_operand" "")
2639	(reg:SI MACL_REG))]
2640  "TARGET_SH1"
2641  "
2642{
2643  rtx insn, macl;
2644
2645  macl = gen_rtx_REG (SImode, MACL_REG);
2646  start_sequence ();
2647  emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
2648  insn = get_insns ();  
2649  end_sequence ();
2650  /* expand_binop can't find a suitable code in umul_widen_optab to
2651     make a REG_EQUAL note from, so make one here.
2652     See also smulsi3_highpart.
2653     ??? Alternatively, we could put this at the calling site of expand_binop,
2654     i.e. expand_expr.  */
2655  /* Use emit_libcall_block for loop invariant code motion and to make
2656     a REG_EQUAL note.  */
2657  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
2658
2659  DONE;
2660}")
2661
2662;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
2663;; a call to a routine which clobbers known registers.
2664
2665(define_insn ""
2666  [(set (match_operand:SI 1 "register_operand" "=z")
2667	(mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2668   (clobber (reg:SI MACL_REG))
2669   (clobber (reg:SI T_REG))
2670   (clobber (reg:SI PR_REG))
2671   (clobber (reg:SI R3_REG))
2672   (clobber (reg:SI R2_REG))
2673   (clobber (reg:SI R1_REG))
2674   (use (match_operand:SI 0 "arith_reg_operand" "r"))]
2675  "TARGET_SH1"
2676  "jsr	@%0%#"
2677  [(set_attr "type" "sfunc")
2678   (set_attr "needs_delay_slot" "yes")])
2679
2680(define_expand "mulsi3_call"
2681  [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2682   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2683   (parallel[(set (match_operand:SI 0 "register_operand" "")
2684		  (mult:SI (reg:SI R4_REG)
2685			   (reg:SI R5_REG)))
2686	     (clobber (reg:SI MACL_REG))
2687	     (clobber (reg:SI T_REG))
2688	     (clobber (reg:SI PR_REG))
2689	     (clobber (reg:SI R3_REG))
2690	     (clobber (reg:SI R2_REG))
2691	     (clobber (reg:SI R1_REG))
2692	     (use (match_operand:SI 3 "register_operand" ""))])]
2693  "TARGET_SH1"
2694  "")
2695
2696(define_insn "mul_r"
2697  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2698	(mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
2699		 (match_operand:SI 2 "arith_reg_operand" "z")))]
2700  "TARGET_SH2A"
2701  "mulr	%2,%0"
2702  [(set_attr "type" "dmpy")])
2703
2704(define_insn "mul_l"
2705  [(set (reg:SI MACL_REG)
2706	(mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
2707		 (match_operand:SI 1 "arith_reg_operand" "r")))]
2708  "TARGET_SH2"
2709  "mul.l	%1,%0"
2710  [(set_attr "type" "dmpy")])
2711
2712(define_expand "mulsi3"
2713  [(set (reg:SI MACL_REG)
2714	(mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
2715		  (match_operand:SI 2 "arith_reg_operand" "")))
2716   (set (match_operand:SI 0 "arith_reg_operand" "")
2717	(reg:SI MACL_REG))]
2718  "TARGET_SH1"
2719  "
2720{
2721  if (!TARGET_SH2)
2722    {
2723      /* The address must be set outside the libcall,
2724	 since it goes into a pseudo.  */
2725      rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC);
2726      rtx addr = force_reg (SImode, sym);
2727      rtx insns = gen_mulsi3_call (operands[0], operands[1],
2728				   operands[2], addr);
2729      emit_insn (insns);
2730    }
2731  else
2732    {
2733      rtx macl = gen_rtx_REG (SImode, MACL_REG);
2734
2735      emit_insn (gen_mul_l (operands[1], operands[2]));
2736      /* consec_sets_giv can only recognize the first insn that sets a
2737	 giv as the giv insn.  So we must tag this also with a REG_EQUAL
2738	 note.  */
2739      emit_insn (gen_movsi_i ((operands[0]), macl));
2740    }
2741  DONE;
2742}")
2743
2744(define_insn "mulsidi3_i"
2745  [(set (reg:SI MACH_REG)
2746	(truncate:SI
2747	 (lshiftrt:DI
2748	  (mult:DI
2749	   (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2750	   (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2751	  (const_int 32))))
2752   (set (reg:SI MACL_REG)
2753	(mult:SI (match_dup 0)
2754		 (match_dup 1)))]
2755  "TARGET_SH2"
2756  "dmuls.l	%1,%0"
2757  [(set_attr "type" "dmpy")])
2758
2759(define_expand "mulsidi3"
2760  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2761	(mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2762		 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2763  "TARGET_SH2 || TARGET_SHMEDIA"
2764  "
2765{
2766  if (TARGET_SH2)
2767    {
2768       emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
2769					operands[2]));
2770       DONE;
2771    }
2772}")
2773
2774(define_insn "mulsidi3_media"
2775  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2776	(mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2777		 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2778  "TARGET_SHMEDIA"
2779  "muls.l	%1, %2, %0"
2780  [(set_attr "type" "dmpy_media")
2781   (set_attr "highpart" "ignore")])
2782
2783(define_insn "mulsidi3_compact"
2784  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2785	(mult:DI
2786	 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2787	 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2788   (clobber (reg:SI MACH_REG))
2789   (clobber (reg:SI MACL_REG))]
2790  "TARGET_SH2"
2791  "#")
2792
2793(define_split
2794  [(set (match_operand:DI 0 "arith_reg_dest" "")
2795	(mult:DI
2796	 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2797	 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2798   (clobber (reg:SI MACH_REG))
2799   (clobber (reg:SI MACL_REG))]
2800  "TARGET_SH2"
2801  [(const_int 0)]
2802  "
2803{
2804  rtx low_dst = gen_lowpart (SImode, operands[0]);
2805  rtx high_dst = gen_highpart (SImode, operands[0]);
2806
2807  emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
2808
2809  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2810  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2811  /* We need something to tag the possible REG_EQUAL notes on to.  */
2812  emit_move_insn (operands[0], operands[0]);
2813  DONE;
2814}")
2815
2816(define_insn "umulsidi3_i"
2817  [(set (reg:SI MACH_REG)
2818	(truncate:SI
2819	 (lshiftrt:DI
2820	  (mult:DI
2821	   (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2822	   (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2823	  (const_int 32))))
2824   (set (reg:SI MACL_REG)
2825	(mult:SI (match_dup 0)
2826		 (match_dup 1)))]
2827  "TARGET_SH2"
2828  "dmulu.l	%1,%0"
2829  [(set_attr "type" "dmpy")])
2830
2831(define_expand "umulsidi3"
2832  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
2833	(mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2834		 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
2835  "TARGET_SH2 || TARGET_SHMEDIA"
2836  "
2837{
2838  if (TARGET_SH2)
2839    {
2840       emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
2841					 operands[2]));
2842       DONE;
2843    }
2844}")
2845
2846(define_insn "umulsidi3_media"
2847  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2848	(mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
2849		 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
2850  "TARGET_SHMEDIA"
2851  "mulu.l	%1, %2, %0"
2852  [(set_attr "type" "dmpy_media")
2853   (set_attr "highpart" "ignore")])
2854
2855(define_insn "umulsidi3_compact"
2856  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2857	(mult:DI
2858	 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
2859	 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
2860   (clobber (reg:SI MACH_REG))
2861   (clobber (reg:SI MACL_REG))]
2862  "TARGET_SH2"
2863  "#")
2864
2865(define_split
2866  [(set (match_operand:DI 0 "arith_reg_dest" "")
2867	(mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2868		 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
2869   (clobber (reg:SI MACH_REG))
2870   (clobber (reg:SI MACL_REG))]
2871  "TARGET_SH2"
2872  [(const_int 0)]
2873  "
2874{
2875  rtx low_dst = gen_lowpart (SImode, operands[0]);
2876  rtx high_dst = gen_highpart (SImode, operands[0]);
2877
2878  emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
2879
2880  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
2881  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
2882  /* We need something to tag the possible REG_EQUAL notes on to.  */
2883  emit_move_insn (operands[0], operands[0]);
2884  DONE;
2885}")
2886
2887(define_insn "smulsi3_highpart_i"
2888  [(set (reg:SI MACH_REG)
2889	(truncate:SI
2890	 (lshiftrt:DI
2891	  (mult:DI
2892	   (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2893	   (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2894	  (const_int 32))))
2895   (clobber (reg:SI MACL_REG))]
2896  "TARGET_SH2"
2897  "dmuls.l	%1,%0"
2898  [(set_attr "type" "dmpy")])
2899
2900(define_expand "smulsi3_highpart"
2901  [(parallel
2902    [(set (reg:SI MACH_REG)
2903	  (truncate:SI
2904	   (lshiftrt:DI
2905	    (mult:DI
2906	     (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2907	     (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
2908	    (const_int 32))))
2909    (clobber (reg:SI MACL_REG))])
2910   (set (match_operand:SI 0 "arith_reg_operand" "")
2911	(reg:SI MACH_REG))]
2912  "TARGET_SH2"
2913  "
2914{
2915  rtx insn, mach;
2916
2917  mach = gen_rtx_REG (SImode, MACH_REG);
2918  start_sequence ();
2919  emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
2920  insn = get_insns ();  
2921  end_sequence ();
2922  /* expand_binop can't find a suitable code in mul_highpart_optab to
2923     make a REG_EQUAL note from, so make one here.
2924     See also {,u}mulhisi.
2925     ??? Alternatively, we could put this at the calling site of expand_binop,
2926     i.e. expand_mult_highpart.  */
2927  /* Use emit_libcall_block for loop invariant code motion and to make
2928     a REG_EQUAL note.  */
2929  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
2930
2931  DONE;
2932}")
2933
2934(define_insn "umulsi3_highpart_i"
2935  [(set (reg:SI MACH_REG)
2936	(truncate:SI
2937	 (lshiftrt:DI
2938	  (mult:DI
2939	   (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
2940	   (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
2941	  (const_int 32))))
2942   (clobber (reg:SI MACL_REG))]
2943  "TARGET_SH2"
2944  "dmulu.l	%1,%0"
2945  [(set_attr "type" "dmpy")])
2946
2947(define_expand "umulsi3_highpart"
2948  [(parallel
2949    [(set (reg:SI MACH_REG)
2950	  (truncate:SI
2951	   (lshiftrt:DI
2952	    (mult:DI
2953	     (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
2954	     (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
2955	    (const_int 32))))
2956    (clobber (reg:SI MACL_REG))])
2957   (set (match_operand:SI 0 "arith_reg_operand" "")
2958	(reg:SI MACH_REG))]
2959  "TARGET_SH2"
2960  "
2961{
2962  rtx insn, mach;
2963
2964  mach = gen_rtx_REG (SImode, MACH_REG);
2965  start_sequence ();
2966  emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
2967  insn = get_insns ();  
2968  end_sequence ();
2969  /* Use emit_libcall_block for loop invariant code motion and to make
2970     a REG_EQUAL note.  */
2971  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
2972
2973  DONE;
2974}")
2975
2976(define_insn_and_split "muldi3"
2977  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2978	(mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
2979		 (match_operand:DI 2 "arith_reg_operand" "r")))
2980   (clobber (match_scratch:DI 3 "=&r"))
2981   (clobber (match_scratch:DI 4 "=r"))]
2982  "TARGET_SHMEDIA"
2983  "#"
2984  "reload_completed"
2985  [(const_int 0)]
2986  "
2987{
2988  rtx op3_v2si, op2_v2si;
2989
2990  op3_v2si = operands[3];
2991  if (GET_CODE (op3_v2si) == SIGN_EXTEND)
2992    {
2993      op3_v2si = XEXP (op3_v2si, 0);
2994      op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
2995    }
2996  op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
2997  op2_v2si = operands[2];
2998  if (GET_CODE (op2_v2si) == SIGN_EXTEND)
2999    {
3000      op2_v2si = XEXP (op2_v2si, 0);
3001      op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3002    }
3003  op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3004  emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3005  emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3006  emit_insn (gen_umulsidi3_media (operands[4],
3007				 sh_gen_truncate (SImode, operands[1], 0),
3008				 sh_gen_truncate (SImode, operands[2], 0)));
3009  emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3010  emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3011  emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3012  emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3013  DONE;
3014}")
3015
3016
3017;; -------------------------------------------------------------------------
3018;; Logical operations
3019;; -------------------------------------------------------------------------
3020
3021(define_insn "*andsi3_compact"
3022  [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3023	(and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3024		(match_operand:SI 2 "logical_operand" "r,K08")))]
3025  "TARGET_SH1"
3026  "and	%2,%0"
3027  [(set_attr "type" "arith")])
3028
3029(define_insn "*andsi3_media"
3030  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3031	(and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3032		(match_operand:SI 2 "logical_operand" "r,I10")))]
3033  "TARGET_SHMEDIA"
3034  "@
3035	and	%1, %2, %0
3036	andi	%1, %2, %0"
3037  [(set_attr "type" "arith_media")])
3038
3039(define_insn "*andsi3_bclr"
3040  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3041	(and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3042		(match_operand:SI 2 "const_int_operand" "Psz")))]
3043  "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3044  "bclr\\t%W2,%0"
3045  [(set_attr "type" "arith")])
3046
3047;; If the constant is 255, then emit an extu.b instruction instead of an
3048;; and, since that will give better code.
3049
3050(define_expand "andsi3"
3051  [(set (match_operand:SI 0 "arith_reg_operand" "")
3052	(and:SI (match_operand:SI 1 "logical_reg_operand" "")
3053		(match_operand:SI 2 "logical_operand" "")))]
3054  ""
3055  "
3056{
3057  if (TARGET_SH1
3058      && CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 255)
3059    {
3060      emit_insn (gen_zero_extendqisi2 (operands[0],
3061				       gen_lowpart (QImode, operands[1])));
3062      DONE;
3063    }
3064}")
3065
3066(define_insn_and_split "anddi3"
3067  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3068	(and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3069		(match_operand:DI 2 "and_operand" "r,I10,J16")))]
3070  "TARGET_SHMEDIA"
3071  "@
3072	and	%1, %2, %0
3073	andi	%1, %2, %0
3074	#"
3075  "reload_completed
3076   && ! logical_operand (operands[2], DImode)"
3077  [(const_int 0)]
3078  "
3079{
3080  if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3081    emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3082  else
3083    emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3084  DONE;
3085}"
3086  [(set_attr "type" "arith_media")])
3087
3088(define_insn "andcsi3"
3089  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3090	(and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3091		(not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3092  "TARGET_SHMEDIA"
3093  "andc	%1,%2,%0"
3094  [(set_attr "type" "arith_media")])
3095
3096(define_insn "andcdi3"
3097  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3098	(and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3099		(not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3100  "TARGET_SHMEDIA"
3101  "andc	%1,%2,%0"
3102  [(set_attr "type" "arith_media")])
3103
3104(define_expand "iorsi3"
3105  [(set (match_operand:SI 0 "arith_reg_operand" "")
3106	(ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3107		(match_operand:SI 2 "logical_operand" "")))]
3108  ""
3109  "")
3110
3111(define_insn "*iorsi3_compact"
3112  [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3113	(ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3114		(match_operand:SI 2 "logical_operand" "r,K08")))]
3115  "TARGET_SH1
3116   && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3117  "or	%2,%0"
3118  [(set_attr "type" "arith")])
3119
3120(define_insn "*iorsi3_media"
3121  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3122	(ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3123		(match_operand:SI 2 "logical_operand" "r,I10")))]
3124  "TARGET_SHMEDIA"
3125  "@
3126	or	%1, %2, %0
3127	ori	%1, %2, %0"
3128  [(set_attr "type" "arith_media")])
3129
3130(define_insn "*iorsi3_bset"
3131  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3132	(ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3133	(match_operand:SI 2 "const_int_operand" "Pso")))]
3134  "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3135  "bset\\t%V2,%0"
3136  [(set_attr "type" "arith")])
3137
3138(define_insn "iordi3"
3139  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3140	(ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3141		(match_operand:DI 2 "logical_operand" "r,I10")))]
3142  "TARGET_SHMEDIA"
3143  "@
3144	or	%1, %2, %0
3145	ori	%1, %2, %0"
3146  [(set_attr "type" "arith_media")])
3147
3148(define_insn_and_split "*logical_sidi3"
3149  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3150	(sign_extend:DI (match_operator:SI 3 "logical_operator"
3151			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3152			   (match_operand:SI 2 "logical_operand" "r,I10")])))]
3153  "TARGET_SHMEDIA"
3154  "#"
3155  "&& reload_completed"
3156  [(set (match_dup 0) (match_dup 3))]
3157  "
3158{
3159  operands[3]
3160    = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3161		      simplify_gen_subreg (DImode, operands[1], SImode, 0),
3162		      simplify_gen_subreg (DImode, operands[2], SImode, 0));
3163}")
3164
3165(define_insn_and_split "*logical_sidisi3"
3166  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3167	(truncate:SI (sign_extend:DI
3168			(match_operator:SI 3 "logical_operator"
3169			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3170			   (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3171  "TARGET_SHMEDIA"
3172  "#"
3173  "&& 1"
3174  [(set (match_dup 0) (match_dup 3))])
3175
3176(define_insn_and_split "*logical_sidi3_2"
3177  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3178	(sign_extend:DI (truncate:SI (sign_extend:DI
3179			(match_operator:SI 3 "logical_operator"
3180			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3181			   (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3182  "TARGET_SHMEDIA"
3183  "#"
3184  "&& 1"
3185  [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3186
3187(define_expand "xorsi3"
3188  [(set (match_operand:SI 0 "arith_reg_operand" "")
3189	(xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3190		(match_operand:SI 2 "xor_operand" "")))]
3191  ""
3192  "")
3193
3194(define_insn "*xorsi3_compact"
3195  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3196	(xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3197		(match_operand:SI 2 "logical_operand" "K08,r")))]
3198  "TARGET_SH1"
3199  "xor	%2,%0"
3200  [(set_attr "type" "arith")])
3201
3202(define_insn "*xorsi3_media"
3203  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3204	(xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3205		(match_operand:SI 2 "xor_operand" "r,I06")))]
3206  "TARGET_SHMEDIA"
3207  "@
3208	xor	%1, %2, %0
3209	xori	%1, %2, %0"
3210  [(set_attr "type" "arith_media")])
3211
3212;; Store the complements of the T bit in a register.
3213(define_insn "xorsi3_movrt"
3214  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3215	(xor:SI (reg:SI T_REG)
3216		(const_int 1)))]
3217  "TARGET_SH2A"
3218  "movrt\\t%0"
3219  [(set_attr "type" "arith")])
3220
3221(define_insn "xordi3"
3222  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3223	(xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3224		(match_operand:DI 2 "xor_operand" "r,I06")))]
3225  "TARGET_SHMEDIA"
3226  "@
3227	xor	%1, %2, %0
3228	xori	%1, %2, %0"
3229  [(set_attr "type" "arith_media")])
3230
3231;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3232;; converts 2 * sign extend -> logical op into logical op -> sign extend
3233(define_split
3234  [(set (match_operand:DI 0 "arith_reg_dest" "")
3235	(sign_extend:DI (match_operator 4 "binary_logical_operator"
3236			  [(match_operand 1 "any_register_operand" "")
3237			   (match_operand 2 "any_register_operand" "")])))]
3238  "TARGET_SHMEDIA"
3239  [(set (match_dup 5) (match_dup 4))
3240   (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3241"
3242{
3243  enum machine_mode inmode = GET_MODE (operands[1]);
3244  int offset = 0;
3245
3246  if (GET_CODE (operands[0]) == SUBREG)
3247    {
3248      offset = SUBREG_BYTE (operands[0]);
3249      operands[0] = SUBREG_REG (operands[0]);
3250    }
3251  gcc_assert (REG_P (operands[0]));
3252  if (! TARGET_LITTLE_ENDIAN)
3253    offset += 8 - GET_MODE_SIZE (inmode);
3254  operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3255}")
3256
3257;; -------------------------------------------------------------------------
3258;; Shifts and rotates
3259;; -------------------------------------------------------------------------
3260
3261(define_expand "rotldi3"
3262  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3263	(rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3264		   (match_operand:HI 2 "mextr_bit_offset" "i")))]
3265  "TARGET_SHMEDIA"
3266  "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3267
3268(define_insn "rotldi3_mextr"
3269  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3270	(rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3271		   (match_operand:HI 2 "mextr_bit_offset" "i")))]
3272  "TARGET_SHMEDIA"
3273  "*
3274{
3275  static char templ[16];
3276
3277  sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\",
3278	   8 - (int) (INTVAL (operands[2]) >> 3));
3279  return templ;
3280}"
3281  [(set_attr "type" "arith_media")])
3282
3283(define_expand "rotrdi3"
3284  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3285	(rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3286		     (match_operand:HI 2 "mextr_bit_offset" "i")))]
3287  "TARGET_SHMEDIA"
3288  "if (! mextr_bit_offset (operands[2], HImode)) FAIL;")
3289
3290(define_insn "rotrdi3_mextr"
3291  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3292	(rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3293		     (match_operand:HI 2 "mextr_bit_offset" "i")))]
3294  "TARGET_SHMEDIA"
3295  "*
3296{
3297  static char templ[16];
3298
3299  sprintf (templ, \"mextr%d\\t%%1,%%1,%%0\", (int) INTVAL (operands[2]) >> 3);
3300  return templ;
3301}"
3302  [(set_attr "type" "arith_media")])
3303
3304(define_split
3305  [(set (match_operand:DI 0 "arith_reg_dest" "")
3306	(ior:DI (zero_extend:DI (mem:QI (match_operand 1
3307					 "ua_address_operand" "")))
3308		(ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3309			   (const_int 8))))
3310   (clobber (match_operand:DI 3 "register_operand" ""))]
3311  "TARGET_SHMEDIA"
3312  [(match_dup 4) (match_dup 5)]
3313  "
3314{
3315  operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3316		 (operands[3], operands[1]));
3317  operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3318			      GEN_INT (56), GEN_INT (8));
3319}")
3320
3321(define_insn "rotlsi3_1"
3322  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3323	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3324		   (const_int 1)))
3325   (set (reg:SI T_REG)
3326	(lshiftrt:SI (match_dup 1) (const_int 31)))]
3327  "TARGET_SH1"
3328  "rotl	%0"
3329  [(set_attr "type" "arith")])
3330
3331(define_insn "rotlsi3_31"
3332  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3333	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3334		   (const_int 31)))
3335   (clobber (reg:SI T_REG))]
3336  "TARGET_SH1"
3337  "rotr	%0"
3338  [(set_attr "type" "arith")])
3339
3340(define_insn "rotlsi3_16"
3341  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3342	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3343		   (const_int 16)))]
3344  "TARGET_SH1"
3345  "swap.w	%1,%0"
3346  [(set_attr "type" "arith")])
3347
3348(define_expand "rotlsi3"
3349  [(set (match_operand:SI 0 "arith_reg_dest" "")
3350	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
3351		   (match_operand:SI 2 "immediate_operand" "")))]
3352  "TARGET_SH1"
3353  "
3354{
3355  static const char rot_tab[] = {
3356    000, 000, 000, 000, 000, 000, 010, 001,
3357    001, 001, 011, 013, 003, 003, 003, 003,
3358    003, 003, 003, 003, 003, 013, 012, 002,
3359    002, 002, 010, 000, 000, 000, 000, 000,
3360  };
3361
3362  int count, choice;
3363
3364  if (!CONST_INT_P (operands[2]))
3365    FAIL;
3366  count = INTVAL (operands[2]);
3367  choice = rot_tab[count];
3368  if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3369    FAIL;
3370  choice &= 7;
3371  switch (choice)
3372    {
3373    case 0:
3374      emit_move_insn (operands[0], operands[1]);
3375      count -= (count & 16) * 2;
3376      break;
3377    case 3:
3378     emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3379     count -= 16;
3380     break;
3381    case 1:
3382    case 2:
3383      {
3384	rtx parts[2];
3385	parts[0] = gen_reg_rtx (SImode);
3386	parts[1] = gen_reg_rtx (SImode);
3387	emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3388	emit_move_insn (parts[choice-1], operands[1]);
3389	emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3390	emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3391	emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3392	count = (count & ~16) - 8;
3393      }
3394    }
3395
3396  for (; count > 0; count--)
3397    emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3398  for (; count < 0; count++)
3399    emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3400
3401  DONE;
3402}")
3403
3404(define_insn "*rotlhi3_8"
3405  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3406	(rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3407		   (const_int 8)))]
3408  "TARGET_SH1"
3409  "swap.b	%1,%0"
3410  [(set_attr "type" "arith")])
3411
3412(define_expand "rotlhi3"
3413  [(set (match_operand:HI 0 "arith_reg_operand" "")
3414	(rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
3415		   (match_operand:HI 2 "immediate_operand" "")))]
3416  "TARGET_SH1"
3417  "
3418{
3419  if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 8)
3420    FAIL;
3421}")
3422
3423;;
3424;; shift left
3425
3426(define_insn "ashlsi3_sh2a"
3427  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3428	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3429		   (match_operand:SI 2 "arith_reg_operand" "r")))]
3430  "TARGET_SH2A"
3431  "shad	%2,%0"
3432  [(set_attr "type" "arith")
3433   (set_attr "length" "4")])
3434
3435;; This pattern is used by init_expmed for computing the costs of shift
3436;; insns.
3437
3438(define_insn_and_split "ashlsi3_std"
3439  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
3440	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
3441		   (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
3442   (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
3443  "TARGET_SH3
3444   || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
3445  "@
3446   shld	%2,%0
3447   add	%0,%0
3448   shll%O2	%0
3449   #"
3450  "TARGET_SH3
3451   && reload_completed
3452   && CONST_INT_P (operands[2])
3453   && ! satisfies_constraint_P27 (operands[2])"
3454  [(set (match_dup 3) (match_dup 2))
3455   (parallel
3456    [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
3457     (clobber (match_dup 4))])]
3458  "operands[4] = gen_rtx_SCRATCH (SImode);"
3459  [(set_attr "length" "*,*,*,4")
3460   (set_attr "type" "dyn_shift,arith,arith,arith")])
3461
3462(define_insn "ashlhi3_k"
3463  [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
3464	(ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
3465		   (match_operand:HI 2 "const_int_operand" "M,P27")))]
3466  "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
3467  "@
3468	add	%0,%0
3469	shll%O2	%0"
3470  [(set_attr "type" "arith")])
3471
3472(define_insn "ashlsi3_n"
3473  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3474	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
3475		   (match_operand:SI 2 "const_int_operand" "n")))
3476   (clobber (reg:SI T_REG))]
3477  "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3478  "#"
3479  [(set (attr "length")
3480	(cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3481	       (const_string "2")
3482	       (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3483	       (const_string "4")
3484	       (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3485	       (const_string "6")]
3486	      (const_string "8")))
3487   (set_attr "type" "arith")])
3488
3489(define_split
3490  [(set (match_operand:SI 0 "arith_reg_dest" "")
3491	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3492		   (match_operand:SI 2 "const_int_operand" "")))
3493   (clobber (reg:SI T_REG))]
3494  "TARGET_SH1 && reload_completed"
3495  [(use (reg:SI R0_REG))]
3496  "
3497{
3498  gen_shifty_op (ASHIFT, operands);
3499  DONE;
3500}")
3501
3502(define_insn "ashlsi3_media"
3503  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3504	(ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3505		   (match_operand:SI 2 "shift_count_operand" "r,n")))]
3506  "TARGET_SHMEDIA"
3507  "@
3508	shlld.l	%1, %2, %0
3509	shlli.l	%1, %2, %0"
3510  [(set_attr "type" "arith_media")
3511   (set_attr "highpart" "ignore")])
3512
3513(define_expand "ashlsi3"
3514  [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3515		   (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
3516			      (match_operand:SI 2 "nonmemory_operand" "")))
3517	      (clobber (reg:SI T_REG))])]
3518  ""
3519  "
3520{
3521  if (TARGET_SHMEDIA)
3522    {
3523      emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
3524      DONE;
3525    }
3526  if (CONST_INT_P (operands[2])
3527      && sh_dynamicalize_shift_p (operands[2]))
3528    operands[2] = force_reg (SImode, operands[2]);
3529  if (TARGET_SH3)
3530    {
3531      emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
3532      DONE;
3533    }
3534  if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3535    FAIL;
3536}")
3537
3538(define_insn "*ashlhi3_n"
3539  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3540	(ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
3541		   (match_operand:HI 2 "const_int_operand" "n")))
3542   (clobber (reg:SI T_REG))]
3543  "TARGET_SH1"
3544  "#"
3545  [(set (attr "length")
3546	(cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3547	       (const_string "2")
3548	       (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3549	       (const_string "4")]
3550	      (const_string "6")))
3551   (set_attr "type" "arith")])
3552
3553(define_expand "ashlhi3"
3554  [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
3555		   (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3556			      (match_operand:SI 2 "nonmemory_operand" "")))
3557	      (clobber (reg:SI T_REG))])]
3558  "TARGET_SH1"
3559  "
3560{
3561  if (!CONST_INT_P (operands[2]))
3562    FAIL;
3563  /* It may be possible to call gen_ashlhi3 directly with more generic
3564     operands.  Make sure operands[1] is a HImode register here.  */
3565  if (!arith_reg_operand (operands[1], HImode))
3566    operands[1] = copy_to_mode_reg (HImode, operands[1]);
3567}")
3568
3569(define_split
3570  [(set (match_operand:HI 0 "arith_reg_dest" "")
3571	(ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
3572		   (match_operand:HI 2 "const_int_operand" "")))
3573   (clobber (reg:SI T_REG))]
3574  "TARGET_SH1 && reload_completed"
3575  [(use (reg:SI R0_REG))]
3576  "
3577{
3578  gen_shifty_hi_op (ASHIFT, operands);
3579  DONE;
3580}")
3581
3582;
3583; arithmetic shift right
3584;
3585
3586(define_insn "ashrsi3_sh2a"
3587  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3588	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3589		   (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3590  "TARGET_SH2A"
3591  "shad	%2,%0"
3592  [(set_attr "type" "dyn_shift")
3593   (set_attr "length" "4")])
3594
3595(define_insn "ashrsi3_k"
3596  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3597	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3598		     (match_operand:SI 2 "const_int_operand" "M")))
3599   (clobber (reg:SI T_REG))]
3600  "TARGET_SH1 && INTVAL (operands[2]) == 1"
3601  "shar	%0"
3602  [(set_attr "type" "arith")])
3603
3604;; We can't do HImode right shifts correctly unless we start out with an
3605;; explicit zero / sign extension; doing that would result in worse overall
3606;; code, so just let the machine independent code widen the mode.
3607;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
3608
3609
3610;; ??? This should be a define expand.
3611
3612(define_insn "ashrsi2_16"
3613  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3614        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3615                     (const_int 16)))]
3616  "TARGET_SH1"
3617  "#"
3618  [(set_attr "length" "4")])
3619
3620(define_split
3621  [(set (match_operand:SI 0 "arith_reg_dest" "")
3622        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3623		     (const_int 16)))]
3624  "TARGET_SH1"
3625  [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
3626   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3627  "operands[2] = gen_lowpart (HImode, operands[0]);")
3628
3629;; ??? This should be a define expand.
3630
3631(define_insn "ashrsi2_31"
3632  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3633	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3634		     (const_int 31)))
3635   (clobber (reg:SI T_REG))]
3636  "TARGET_SH1"
3637  "#"
3638  [(set_attr "length" "4")])
3639
3640(define_split
3641  [(set (match_operand:SI 0 "arith_reg_dest" "")
3642	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3643		     (const_int 31)))
3644   (clobber (reg:SI T_REG))]
3645  "TARGET_SH1"
3646  [(const_int 0)]
3647  "
3648{
3649  emit_insn (gen_ashlsi_c (operands[0], operands[1]));
3650  emit_insn (gen_mov_neg_si_t (copy_rtx (operands[0])));
3651  DONE;
3652}")
3653
3654(define_peephole2
3655  [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
3656   (set (reg:SI T_REG)
3657	(gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
3658  "TARGET_SH1
3659   && peep2_reg_dead_p (2, operands[0])
3660   && peep2_reg_dead_p (2, operands[1])"
3661  [(const_int 0)]
3662  "
3663{
3664  emit_insn (gen_ashlsi_c (operands[1], operands[1]));
3665  DONE;
3666}")
3667
3668(define_insn "ashlsi_c"
3669  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3670	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
3671   (set (reg:SI T_REG)
3672	(lt:SI (match_dup 1) (const_int 0)))]
3673  "TARGET_SH1"
3674  "shll	%0"
3675  [(set_attr "type" "arith")])
3676
3677(define_insn "*ashlsi_c_void"
3678  [(set (reg:SI T_REG)
3679	(lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
3680   (clobber (match_scratch:SI 1 "=0"))]
3681  "TARGET_SH1 && cse_not_expected"
3682  "shll	%0"
3683  [(set_attr "type" "arith")])
3684
3685(define_insn "ashrsi3_d"
3686  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3687	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3688		     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3689  "TARGET_SH3"
3690  "shad	%2,%0"
3691  [(set_attr "type" "dyn_shift")])
3692
3693(define_insn "ashrsi3_n"
3694  [(set (reg:SI R4_REG)
3695	(ashiftrt:SI (reg:SI R4_REG)
3696		     (match_operand:SI 0 "const_int_operand" "i")))
3697   (clobber (reg:SI T_REG))
3698   (clobber (reg:SI PR_REG))
3699   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3700  "TARGET_SH1"
3701  "jsr	@%1%#"
3702  [(set_attr "type" "sfunc")
3703   (set_attr "needs_delay_slot" "yes")])
3704
3705(define_insn "ashrsi3_media"
3706  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3707	(ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3708		     (match_operand:SI 2 "shift_count_operand" "r,n")))]
3709  "TARGET_SHMEDIA"
3710  "@
3711	shard.l	%1, %2, %0
3712	shari.l	%1, %2, %0"
3713  [(set_attr "type" "arith_media")
3714   (set_attr "highpart" "ignore")])
3715
3716(define_expand "ashrsi3"
3717  [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
3718		   (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3719				(match_operand:SI 2 "nonmemory_operand" "")))
3720	      (clobber (reg:SI T_REG))])]
3721  ""
3722  "
3723{
3724  if (TARGET_SHMEDIA)
3725    {
3726      emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
3727      DONE;
3728    }
3729  if (expand_ashiftrt (operands))
3730    DONE;
3731  else
3732    FAIL;
3733}")
3734
3735;; logical shift right
3736
3737(define_insn "lshrsi3_sh2a"
3738  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3739	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3740		     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3741  "TARGET_SH2A"
3742  "shld	%2,%0"
3743  [(set_attr "type" "dyn_shift")
3744   (set_attr "length" "4")])
3745
3746(define_insn "lshrsi3_d"
3747  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3748	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3749		     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3750  "TARGET_SH3"
3751  "shld	%2,%0"
3752  [(set_attr "type" "dyn_shift")])
3753
3754;;  Only the single bit shift clobbers the T bit.
3755
3756(define_insn "lshrsi3_m"
3757  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3758	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3759		     (match_operand:SI 2 "const_int_operand" "M")))
3760   (clobber (reg:SI T_REG))]
3761  "TARGET_SH1 && satisfies_constraint_M (operands[2])"
3762  "shlr	%0"
3763  [(set_attr "type" "arith")])
3764
3765(define_insn "lshrsi3_k"
3766  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3767	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3768		     (match_operand:SI 2 "const_int_operand" "P27")))]
3769  "TARGET_SH1 && satisfies_constraint_P27 (operands[2])
3770   && ! satisfies_constraint_M (operands[2])"
3771  "shlr%O2	%0"
3772  [(set_attr "type" "arith")])
3773
3774(define_insn "lshrsi3_n"
3775  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3776	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3777		     (match_operand:SI 2 "const_int_operand" "n")))
3778   (clobber (reg:SI T_REG))]
3779  "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
3780  "#"
3781  [(set (attr "length")
3782	(cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
3783	       (const_string "2")
3784	       (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
3785	       (const_string "4")
3786	       (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3))
3787	       (const_string "6")]
3788	      (const_string "8")))
3789   (set_attr "type" "arith")])
3790
3791(define_split
3792  [(set (match_operand:SI 0 "arith_reg_dest" "")
3793	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3794		     (match_operand:SI 2 "const_int_operand" "")))
3795   (clobber (reg:SI T_REG))]
3796  "TARGET_SH1 && reload_completed"
3797  [(use (reg:SI R0_REG))]
3798  "
3799{
3800  gen_shifty_op (LSHIFTRT, operands);
3801  DONE;
3802}")
3803
3804(define_insn "lshrsi3_media"
3805  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3806	(lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
3807		     (match_operand:SI 2 "shift_count_operand" "r,n")))]
3808  "TARGET_SHMEDIA"
3809  "@
3810	shlrd.l	%1, %2, %0
3811	shlri.l	%1, %2, %0"
3812  [(set_attr "type" "arith_media")
3813   (set_attr "highpart" "ignore")])
3814
3815(define_expand "lshrsi3"
3816  [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
3817		   (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
3818				(match_operand:SI 2 "nonmemory_operand" "")))
3819	      (clobber (reg:SI T_REG))])]
3820  ""
3821  "
3822{
3823  if (TARGET_SHMEDIA)
3824    {
3825      emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
3826      DONE;
3827    }
3828  if (CONST_INT_P (operands[2])
3829      && sh_dynamicalize_shift_p (operands[2]))
3830    operands[2] = force_reg (SImode, operands[2]);
3831  if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
3832    {
3833      rtx count = copy_to_mode_reg (SImode, operands[2]);
3834      emit_insn (gen_negsi2 (count, count));
3835      emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
3836      DONE;
3837    }
3838  if (! immediate_operand (operands[2], GET_MODE (operands[2])))
3839    FAIL;
3840}")
3841
3842;; ??? This should be a define expand.
3843
3844(define_insn "ashldi3_k"
3845  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3846	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
3847		   (const_int 1)))
3848   (clobber (reg:SI T_REG))]
3849  "TARGET_SH1"
3850  "shll	%R0\;rotcl	%S0"
3851  [(set_attr "length" "4")
3852   (set_attr "type" "arith")])
3853
3854;; Expander for DImode shift left with SImode operations.
3855
3856(define_expand "ashldi3_std"
3857  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3858	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3859                   (match_operand:DI 2 "const_int_operand" "n")))]
3860  "TARGET_SH1 && INTVAL (operands[2]) < 32"
3861  "
3862{
3863  int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
3864  int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
3865  rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
3866  rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
3867  rtx dst = gen_reg_rtx (DImode);
3868  rtx low_dst = operand_subword (dst, low_word, 1, DImode);
3869  rtx high_dst = operand_subword (dst, high_word, 1, DImode);
3870  rtx tmp0, tmp1;
3871
3872  tmp0 = gen_reg_rtx (SImode);
3873  tmp1 = gen_reg_rtx (SImode);
3874  emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
3875  emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));  
3876  emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));  
3877  emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
3878  emit_move_insn (operands[0], dst);
3879  DONE;
3880}")
3881
3882(define_insn "ashldi3_media"
3883  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3884	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3885		   (match_operand:DI 2 "shift_count_operand" "r,n")))]
3886  "TARGET_SHMEDIA"
3887  "@
3888	shlld	%1, %2, %0
3889	shlli	%1, %2, %0"
3890  [(set_attr "type" "arith_media")])
3891
3892(define_insn "*ashldisi3_media"
3893  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3894	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
3895		   (match_operand:DI 2 "const_int_operand" "n")))]
3896  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3897  "shlli.l	%1, %2, %0"
3898  [(set_attr "type" "arith_media")
3899   (set_attr "highpart" "ignore")])
3900
3901(define_expand "ashldi3"
3902  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3903		   (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
3904			      (match_operand:DI 2 "immediate_operand" "")))
3905	      (clobber (reg:SI T_REG))])]
3906  ""
3907  "
3908{
3909  if (TARGET_SHMEDIA)
3910    {
3911      emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
3912      DONE;
3913    }
3914  if (CONST_INT_P (operands[2])
3915      && INTVAL (operands[2]) == 1)
3916    {
3917      emit_insn (gen_ashldi3_k (operands[0], operands[1]));
3918      DONE;
3919    }
3920  else if (CONST_INT_P (operands[2])
3921      && INTVAL (operands[2]) < 32)
3922    {
3923      emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
3924      DONE;
3925    }
3926  else
3927    FAIL;
3928}")
3929
3930;; ??? This should be a define expand.
3931
3932(define_insn "lshrdi3_k"
3933  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3934	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
3935		     (const_int 1)))
3936   (clobber (reg:SI T_REG))]
3937  "TARGET_SH1"
3938  "shlr	%S0\;rotcr	%R0"
3939  [(set_attr "length" "4")
3940   (set_attr "type" "arith")])
3941
3942(define_insn "lshrdi3_media"
3943  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
3944	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3945		     (match_operand:DI 2 "shift_count_operand" "r,n")))]
3946  "TARGET_SHMEDIA
3947   && (arith_reg_dest (operands[0], DImode)
3948       || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
3949  "@
3950	shlrd	%1, %2, %0
3951	shlri	%1, %2, %0"
3952  [(set_attr "type" "arith_media")])
3953
3954(define_insn "*lshrdisi3_media"
3955  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
3956	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
3957		     (match_operand:DI 2 "const_int_operand" "n")))]
3958  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
3959  "shlri.l	%1, %2, %0"
3960  [(set_attr "type" "arith_media")
3961   (set_attr "highpart" "ignore")])
3962
3963(define_expand "lshrdi3"
3964  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
3965		   (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
3966			       (match_operand:DI 2 "immediate_operand" "")))
3967	     (clobber (reg:SI T_REG))])]
3968  ""
3969  "
3970{
3971  if (TARGET_SHMEDIA)
3972    {
3973      emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
3974      DONE;
3975    }
3976  if (!CONST_INT_P (operands[2])
3977      || INTVAL (operands[2]) != 1)
3978    FAIL;
3979}")
3980
3981;; ??? This should be a define expand.
3982
3983(define_insn "ashrdi3_k"
3984  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3985	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
3986		     (const_int 1)))
3987   (clobber (reg:SI T_REG))]
3988  "TARGET_SH1"
3989  "shar	%S0\;rotcr	%R0"
3990  [(set_attr "length" "4")
3991   (set_attr "type" "arith")])
3992
3993(define_insn "ashrdi3_media"
3994  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
3995	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
3996		     (match_operand:DI 2 "shift_count_operand" "r,n")))]
3997  "TARGET_SHMEDIA
3998   && (arith_reg_dest (operands[0], DImode)
3999       || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4000  "@
4001	shard	%1, %2, %0
4002	shari	%1, %2, %0"
4003  [(set_attr "type" "arith_media")])
4004
4005(define_insn "*ashrdisi3_media"
4006  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4007	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4008		     (match_operand:DI 2 "const_int_operand" "n")))]
4009  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4010  "shari.l	%1, %2, %0"
4011  [(set_attr "type" "arith_media")
4012   (set_attr "highpart" "ignore")])
4013
4014(define_insn "ashrdisi3_media_high"
4015  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4016	(truncate:SI
4017	   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4018			(match_operand:DI 2 "const_int_operand" "n"))))]
4019  "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4020  "shari	%1, %2, %0"
4021  [(set_attr "type" "arith_media")])
4022
4023(define_insn "ashrdisi3_media_opaque"
4024  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4025	(unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4026		    (match_operand:DI 2 "const_int_operand" "n")]
4027	 UNSPEC_ASHIFTRT))]
4028  "TARGET_SHMEDIA"
4029  "shari	%1, %2, %0"
4030  [(set_attr "type" "arith_media")])
4031
4032(define_expand "ashrdi3"
4033  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4034		   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4035				(match_operand:DI 2 "immediate_operand" "")))
4036	      (clobber (reg:SI T_REG))])]
4037  ""
4038  "
4039{
4040  if (TARGET_SHMEDIA)
4041    {
4042      emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4043      DONE;
4044    }
4045  if (!CONST_INT_P (operands[2])
4046      || INTVAL (operands[2]) != 1)
4047    FAIL;
4048}")
4049
4050;; combined left/right shift
4051
4052(define_split
4053  [(set (match_operand:SI 0 "register_operand" "")
4054	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4055			   (match_operand:SI 2 "const_int_operand" ""))
4056		(match_operand:SI 3 "const_int_operand" "")))]
4057  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4058  [(use (reg:SI R0_REG))]
4059  "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4060   DONE;")
4061
4062(define_split
4063  [(set (match_operand:SI 0 "register_operand" "")
4064	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4065			   (match_operand:SI 2 "const_int_operand" ""))
4066		(match_operand:SI 3 "const_int_operand" "")))
4067   (clobber (reg:SI T_REG))]
4068  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4069  [(use (reg:SI R0_REG))]
4070  "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
4071   DONE;")
4072
4073(define_insn ""
4074  [(set (match_operand:SI 0 "register_operand" "=r")
4075	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4076			   (match_operand:SI 2 "const_int_operand" "n"))
4077		(match_operand:SI 3 "const_int_operand" "n")))
4078   (clobber (reg:SI T_REG))]
4079  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4080 "#"
4081  [(set (attr "length")
4082	(cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4083	       (const_string "4")
4084	       (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4085	       (const_string "6")
4086	       (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4087	       (const_string "8")
4088	       (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4089	       (const_string "10")
4090	       (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4091	       (const_string "12")
4092	       (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4093	       (const_string "14")
4094	       (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4095	       (const_string "16")]
4096	      (const_string "18")))
4097   (set_attr "type" "arith")])
4098
4099(define_insn ""
4100  [(set (match_operand:SI 0 "register_operand" "=z")
4101	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4102			   (match_operand:SI 2 "const_int_operand" "n"))
4103		(match_operand:SI 3 "const_int_operand" "n")))
4104   (clobber (reg:SI T_REG))]
4105  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4106 "#"
4107  [(set (attr "length")
4108	(cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4109	       (const_string "4")
4110	       (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4111	       (const_string "6")
4112	       (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4113	       (const_string "8")]
4114	      (const_string "10")))
4115   (set_attr "type" "arith")])
4116
4117;; shift left / and combination with a scratch register: The combine pass
4118;; does not accept the individual instructions, even though they are
4119;; cheap.  But it needs a precise description so that it is usable after
4120;; reload.
4121(define_insn "and_shl_scratch"
4122  [(set (match_operand:SI 0 "register_operand" "=r,&r")
4123	(lshiftrt:SI
4124	 (ashift:SI
4125	  (and:SI
4126	   (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
4127			(match_operand:SI 2 "const_int_operand" "N,n"))
4128	   (match_operand:SI 3 "" "0,r"))
4129	  (match_operand:SI 4 "const_int_operand" "n,n"))
4130	 (match_operand:SI 5 "const_int_operand" "n,n")))
4131   (clobber (reg:SI T_REG))]
4132  "TARGET_SH1"
4133  "#"
4134  [(set (attr "length")
4135	(cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
4136	       (const_string "4")
4137	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
4138	       (const_string "6")
4139	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
4140	       (const_string "8")
4141	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
4142	       (const_string "10")]
4143	      (const_string "12")))
4144   (set_attr "type" "arith")])
4145
4146(define_split
4147  [(set (match_operand:SI 0 "register_operand" "")
4148	(lshiftrt:SI
4149	 (ashift:SI
4150	  (and:SI
4151	   (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
4152			(match_operand:SI 2 "const_int_operand" ""))
4153	   (match_operand:SI 3 "register_operand" ""))
4154	  (match_operand:SI 4 "const_int_operand" ""))
4155	 (match_operand:SI 5 "const_int_operand" "")))
4156   (clobber (reg:SI T_REG))]
4157  "TARGET_SH1"
4158  [(use (reg:SI R0_REG))]
4159  "
4160{
4161  rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
4162
4163  if (INTVAL (operands[2]))
4164    {
4165      gen_shifty_op (LSHIFTRT, operands);
4166    }
4167  emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
4168  operands[2] = operands[4];
4169  gen_shifty_op (ASHIFT, operands);
4170  if (INTVAL (operands[5]))
4171    {
4172      operands[2] = operands[5];
4173      gen_shifty_op (LSHIFTRT, operands);
4174    }
4175  DONE;
4176}")
4177
4178;; signed left/right shift combination.
4179(define_split
4180  [(set (match_operand:SI 0 "register_operand" "")
4181        (sign_extract:SI
4182	 (ashift:SI (match_operand:SI 1 "register_operand" "")
4183		    (match_operand:SI 2 "const_int_operand" ""))
4184	 (match_operand:SI 3 "const_int_operand" "")
4185	 (const_int 0)))
4186   (clobber (reg:SI T_REG))]
4187  "TARGET_SH1"
4188  [(use (reg:SI R0_REG))]
4189  "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
4190   DONE;")
4191
4192(define_insn "shl_sext_ext"
4193  [(set (match_operand:SI 0 "register_operand" "=r")
4194        (sign_extract:SI
4195	 (ashift:SI (match_operand:SI 1 "register_operand" "0")
4196		    (match_operand:SI 2 "const_int_operand" "n"))
4197	 (match_operand:SI 3 "const_int_operand" "n")
4198	 (const_int 0)))
4199   (clobber (reg:SI T_REG))]
4200  "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
4201  "#"
4202  [(set (attr "length")
4203	(cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
4204	       (const_string "2")
4205	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
4206	       (const_string "4")
4207	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4208	       (const_string "6")
4209	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4210	       (const_string "8")
4211	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4212	       (const_string "10")
4213	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4214	       (const_string "12")
4215	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
4216	       (const_string "14")
4217	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
4218	       (const_string "16")]
4219	      (const_string "18")))
4220    (set_attr "type" "arith")])
4221
4222(define_insn "shl_sext_sub"
4223  [(set (match_operand:SI 0 "register_operand" "=z")
4224        (sign_extract:SI
4225	 (ashift:SI (match_operand:SI 1 "register_operand" "0")
4226		    (match_operand:SI 2 "const_int_operand" "n"))
4227	 (match_operand:SI 3 "const_int_operand" "n")
4228	 (const_int 0)))
4229   (clobber (reg:SI T_REG))]
4230  "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
4231  "#"
4232  [(set (attr "length")
4233	(cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
4234	       (const_string "6")
4235	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
4236	       (const_string "8")
4237	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
4238	       (const_string "10")
4239	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
4240	       (const_string "12")]
4241	      (const_string "14")))
4242    (set_attr "type" "arith")])
4243
4244;; These patterns are found in expansions of DImode shifts by 16, and
4245;; allow the xtrct instruction to be generated from C source.
4246
4247(define_insn "xtrct_left"
4248  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4249        (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
4250			   (const_int 16))
4251 	        (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
4252			     (const_int 16))))]
4253  "TARGET_SH1"
4254  "xtrct	%1,%0"
4255  [(set_attr "type" "arith")])
4256
4257(define_insn "xtrct_right"
4258  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4259        (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4260			     (const_int 16))
4261 	        (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
4262			   (const_int 16))))]
4263  "TARGET_SH1"
4264  "xtrct	%2,%0"
4265  [(set_attr "type" "arith")])
4266
4267;; -------------------------------------------------------------------------
4268;; Unary arithmetic
4269;; -------------------------------------------------------------------------
4270
4271(define_insn "negc"
4272  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4273	(neg:SI (plus:SI (reg:SI T_REG)
4274			 (match_operand:SI 1 "arith_reg_operand" "r"))))
4275   (set (reg:SI T_REG)
4276	(ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
4277	       (const_int 0)))]
4278  "TARGET_SH1"
4279  "negc	%1,%0"
4280  [(set_attr "type" "arith")])
4281
4282(define_insn "*negdi_media"
4283  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4284	(neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
4285  "TARGET_SHMEDIA"
4286  "sub	r63, %1, %0"
4287  [(set_attr "type" "arith_media")])
4288
4289(define_expand "negdi2"
4290  [(set (match_operand:DI 0 "arith_reg_operand" "")
4291	(neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
4292  ""
4293  "
4294{
4295  if (TARGET_SH1)
4296    {
4297      int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
4298      int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
4299
4300      rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
4301      rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
4302
4303      rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
4304      rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
4305
4306      emit_insn (gen_clrt ());
4307      emit_insn (gen_negc (low_dst, low_src));
4308      emit_insn (gen_negc (high_dst, high_src));
4309      DONE;
4310    }
4311}")
4312
4313(define_insn "negsi2"
4314  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4315	(neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4316  "TARGET_SH1"
4317  "neg	%1,%0"
4318  [(set_attr "type" "arith")])
4319
4320(define_insn "one_cmplsi2"
4321  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4322	(not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
4323  "TARGET_SH1"
4324  "not	%1,%0"
4325  [(set_attr "type" "arith")])
4326
4327(define_expand "one_cmpldi2"
4328  [(set (match_operand:DI 0 "arith_reg_dest" "")
4329	(xor:DI (match_operand:DI 1 "arith_reg_operand" "")
4330		(const_int -1)))]
4331  "TARGET_SHMEDIA" "")
4332
4333/* The SH4 202 can do zero-offset branches without pipeline stalls.
4334   This can be used as some kind of conditional execution, which is useful
4335   for abs.  */
4336(define_split
4337  [(set (match_operand:SI 0 "arith_reg_dest" "")
4338	(plus:SI (xor:SI (neg:SI (reg:SI T_REG))
4339			 (match_operand:SI 1 "arith_reg_operand" ""))
4340		 (reg:SI T_REG)))]
4341  "TARGET_HARD_SH4"
4342  [(const_int 0)]
4343  "emit_insn (gen_movsi_i (operands[0], operands[1]));
4344   emit_insn (gen_cneg (operands[0], operands[0], operands[0]));
4345   DONE;")
4346
4347(define_insn "cneg"
4348  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4349	(if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
4350		      (match_operand:SI 1 "arith_reg_operand" "0")
4351		      (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4352  "TARGET_HARD_SH4"
4353  "bf 0f\;neg %2,%0\\n0:"
4354  [(set_attr "type" "arith") ;; poor approximation
4355   (set_attr "length" "4")])
4356
4357
4358;; -------------------------------------------------------------------------
4359;; Zero extension instructions
4360;; -------------------------------------------------------------------------
4361
4362(define_insn "zero_extendsidi2"
4363  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4364	(zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
4365  "TARGET_SHMEDIA"
4366  "addz.l	%1, r63, %0"
4367  [(set_attr "type" "arith_media")
4368   (set_attr "highpart" "extend")])
4369
4370(define_insn "zero_extendhidi2"
4371  [(set (match_operand:DI 0 "register_operand" "=r,r")
4372	(zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4373  "TARGET_SHMEDIA"
4374  "@
4375	#
4376	ld%M1.uw	%m1, %0"
4377  [(set_attr "type" "*,load_media")
4378   (set (attr "highpart")
4379	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4380	       (const_string "user")]
4381	      (const_string "ignore")))])
4382
4383(define_split
4384  [(set (match_operand:DI 0 "register_operand" "")
4385	(zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4386  "TARGET_SHMEDIA && reload_completed"
4387  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4388   (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
4389  "
4390{
4391  if (GET_CODE (operands[1]) == TRUNCATE)
4392    operands[1] = XEXP (operands[1], 0);
4393}")
4394
4395;; ??? when a truncated input to a zero_extend is reloaded, reload will
4396;; reload the entire truncate expression.
4397(define_insn_and_split "*loaddi_trunc"
4398  [(set (match_operand 0 "any_register_operand" "=r")
4399	(truncate (match_operand:DI 1 "memory_operand" "m")))]
4400  "TARGET_SHMEDIA && reload_completed"
4401  "#"
4402  "TARGET_SHMEDIA && reload_completed"
4403  [(set (match_dup 0) (match_dup 1))]
4404  "operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));")
4405
4406(define_insn "zero_extendqidi2"
4407  [(set (match_operand:DI 0 "register_operand" "=r,r")
4408	(zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4409  "TARGET_SHMEDIA"
4410  "@
4411	andi	%1, 255, %0
4412	ld%M1.ub	%m1, %0"
4413  [(set_attr "type" "arith_media,load_media")
4414   (set (attr "highpart")
4415	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4416	       (const_string "user")]
4417	      (const_string "ignore")))])
4418
4419(define_expand "zero_extendhisi2"
4420  [(set (match_operand:SI 0 "arith_reg_operand" "")
4421	(zero_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
4422  ""
4423  "
4424{
4425  if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], HImode))
4426    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4427}")
4428
4429(define_insn "*zero_extendhisi2_compact"
4430  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4431	(zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
4432  "TARGET_SH1"
4433  "extu.w	%1,%0"
4434  [(set_attr "type" "arith")])
4435
4436(define_insn "*zero_extendhisi2_media"
4437  [(set (match_operand:SI 0 "register_operand" "=r,r")
4438	(zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4439  "TARGET_SHMEDIA"
4440  "@
4441	#
4442	ld%M1.uw	%m1, %0"
4443  [(set_attr "type" "arith_media,load_media")
4444   (set (attr "highpart")
4445	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4446	       (const_string "user")]
4447	      (const_string "ignore")))])
4448
4449(define_split
4450  [(set (match_operand:SI 0 "register_operand" "")
4451	(zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4452  "TARGET_SHMEDIA && reload_completed"
4453  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4454   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4455  "
4456{
4457  rtx op1 = operands[1];
4458
4459  if (GET_CODE (op1) == TRUNCATE)
4460    op1 = XEXP (op1, 0);
4461  operands[2]
4462    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4463			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
4464}")
4465
4466(define_expand "zero_extendqisi2"
4467  [(set (match_operand:SI 0 "arith_reg_operand" "")
4468	(zero_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
4469  ""
4470  "
4471{
4472  if (! TARGET_SHMEDIA && ! arith_reg_operand (operands[1], QImode))
4473    operands[1] = copy_to_mode_reg (QImode, operands[1]);
4474}")
4475
4476(define_insn "*zero_extendqisi2_compact"
4477  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4478	(zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
4479  "TARGET_SH1"
4480  "extu.b	%1,%0"
4481  [(set_attr "type" "arith")])
4482
4483(define_insn "*zero_extendqisi2_media"
4484  [(set (match_operand:SI 0 "register_operand" "=r,r")
4485	(zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4486  "TARGET_SHMEDIA"
4487  "@
4488	andi	%1, 255, %0
4489	ld%M1.ub	%m1, %0"
4490  [(set_attr "type" "arith_media,load_media")
4491   (set (attr "highpart")
4492	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4493	       (const_string "user")]
4494	      (const_string "ignore")))])
4495
4496(define_insn "zero_extendqihi2"
4497  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4498	(zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
4499  "TARGET_SH1"
4500  "extu.b	%1,%0"
4501  [(set_attr "type" "arith")])
4502
4503;; -------------------------------------------------------------------------
4504;; Sign extension instructions
4505;; -------------------------------------------------------------------------
4506
4507;; ??? This should be a define expand.
4508;; ??? Or perhaps it should be dropped?
4509
4510;; convert_move generates good code for SH[1-4].
4511(define_insn "extendsidi2"
4512  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
4513	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
4514  "TARGET_SHMEDIA"
4515  "@
4516	add.l	%1, r63, %0
4517	ld%M1.l	%m1, %0
4518	fmov.sl	%1, %0"
4519  [(set_attr "type" "arith_media,load_media,fpconv_media")
4520   (set (attr "highpart")
4521	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4522	       (const_string "user")]
4523	      (const_string "extend")))])
4524
4525(define_insn "extendhidi2"
4526  [(set (match_operand:DI 0 "register_operand" "=r,r")
4527	(sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4528  "TARGET_SHMEDIA"
4529  "@
4530	#
4531	ld%M1.w	%m1, %0"
4532  [(set_attr "type" "*,load_media")
4533   (set (attr "highpart")
4534	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4535	       (const_string "user")]
4536	      (const_string "ignore")))])
4537
4538(define_split
4539  [(set (match_operand:DI 0 "register_operand" "")
4540	(sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
4541  "TARGET_SHMEDIA && reload_completed"
4542  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
4543   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
4544  "
4545{
4546  if (GET_CODE (operands[1]) == TRUNCATE)
4547    operands[1] = XEXP (operands[1], 0);
4548}")
4549
4550(define_insn "extendqidi2"
4551  [(set (match_operand:DI 0 "register_operand" "=r,r")
4552	(sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4553  "TARGET_SHMEDIA"
4554  "@
4555	#
4556	ld%M1.b	%m1, %0"
4557  [(set_attr "type" "*,load_media")
4558   (set (attr "highpart")
4559	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4560	       (const_string "user")]
4561	      (const_string "ignore")))])
4562
4563(define_split
4564  [(set (match_operand:DI 0 "register_operand" "")
4565	(sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
4566  "TARGET_SHMEDIA && reload_completed"
4567  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
4568   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
4569  "
4570{
4571  if (GET_CODE (operands[1]) == TRUNCATE)
4572    operands[1] = XEXP (operands[1], 0);
4573}")
4574
4575(define_expand "extendhisi2"
4576  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4577	(sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4578  ""
4579  "")
4580
4581(define_insn "*extendhisi2_compact"
4582  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4583	(sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
4584  "TARGET_SH1"
4585  "@
4586	exts.w	%1,%0
4587	mov.w	%1,%0"
4588  [(set_attr "type" "arith,load")])
4589
4590(define_insn "*extendhisi2_media"
4591  [(set (match_operand:SI 0 "register_operand" "=r,r")
4592	(sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
4593  "TARGET_SHMEDIA"
4594  "@
4595	#
4596	ld%M1.w	%m1, %0"
4597  [(set_attr "type" "arith_media,load_media")
4598   (set (attr "highpart")
4599	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4600	       (const_string "user")]
4601	      (const_string "ignore")))])
4602
4603(define_split
4604  [(set (match_operand:SI 0 "register_operand" "")
4605	(sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
4606  "TARGET_SHMEDIA && reload_completed"
4607  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4608   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4609  "
4610{
4611  rtx op1 = operands[1];
4612  if (GET_CODE (op1) == TRUNCATE)
4613    op1 = XEXP (op1, 0);
4614  operands[2]
4615    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4616			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
4617}")
4618
4619(define_expand "extendqisi2"
4620  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4621	(sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4622  ""
4623  "")
4624
4625(define_insn "*extendqisi2_compact"
4626  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4627	(sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4628  "TARGET_SH1"
4629  "@
4630	exts.b	%1,%0
4631	mov.b	%1,%0"
4632  [(set_attr "type" "arith,load")
4633   (set_attr_alternative "length"
4634     [(const_int 2)
4635       (if_then_else
4636	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
4637	(const_int 4) (const_int 2))])])
4638
4639(define_insn "*extendqisi2_media"
4640  [(set (match_operand:SI 0 "register_operand" "=r,r")
4641	(sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
4642  "TARGET_SHMEDIA"
4643  "@
4644	#
4645	ld%M1.b	%m1, %0"
4646  [(set_attr "type" "arith_media,load_media")
4647   (set (attr "highpart")
4648	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4649	       (const_string "user")]
4650	      (const_string "ignore")))])
4651
4652(define_split
4653  [(set (match_operand:SI 0 "register_operand" "")
4654	(sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
4655  "TARGET_SHMEDIA && reload_completed"
4656  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4657   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4658   "
4659{
4660  rtx op1 = operands[1];
4661  if (GET_CODE (op1) == TRUNCATE)
4662    op1 = XEXP (op1, 0);
4663  operands[2]
4664    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
4665			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
4666}")
4667
4668(define_insn "extendqihi2"
4669  [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4670	(sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
4671  "TARGET_SH1"
4672  "@
4673	exts.b	%1,%0
4674	mov.b	%1,%0"
4675  [(set_attr "type" "arith,load")
4676   (set_attr_alternative "length"
4677     [(const_int 2)
4678       (if_then_else
4679	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
4680	(const_int 4) (const_int 2))])])
4681
4682/* It would seem useful to combine the truncXi patterns into the movXi
4683   patterns, but unary operators are ignored when matching constraints,
4684   so we need separate patterns.  */
4685(define_insn "truncdisi2"
4686  [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
4687	(truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
4688  "TARGET_SHMEDIA"
4689  "@
4690	add.l	%1, r63, %0
4691	st%M0.l	%m0, %1
4692	fst%M0.s	%m0, %T1
4693	fmov.ls	%1, %0
4694	fmov.sl	%T1, %0
4695	fmov.s	%T1, %0"
4696  [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
4697   (set (attr "highpart")
4698	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4699	       (const_string "user")]
4700	      (const_string "extend")))])
4701
4702(define_insn "truncdihi2"
4703  [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
4704	(truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
4705  "TARGET_SHMEDIA"
4706  "@
4707	shlli\\t%1,48,%0\;shlri\\t%0,48,%0
4708	st%M0.w	%m0, %1"
4709  [(set_attr "type"   "arith_media,store_media")
4710   (set_attr "length" "8,4")
4711   (set (attr "highpart")
4712	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4713	       (const_string "user")]
4714	      (const_string "extend")))])
4715
4716; N.B. This should agree with LOAD_EXTEND_OP and movqi.
4717; Because we use zero extension, we can't provide signed QImode compares
4718; using a simple compare or conditional branch insn.
4719(define_insn "truncdiqi2"
4720  [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
4721	(truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
4722  "TARGET_SHMEDIA"
4723  "@
4724	andi	%1, 255, %0
4725	st%M0.b	%m0, %1"
4726  [(set_attr "type"   "arith_media,store")
4727   (set (attr "highpart")
4728	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
4729	       (const_string "user")]
4730	      (const_string "extend")))])
4731;; -------------------------------------------------------------------------
4732;; Move instructions
4733;; -------------------------------------------------------------------------
4734
4735;; define push and pop so it is easy for sh.c
4736;; We can't use push and pop on SHcompact because the stack must always
4737;; be 8-byte aligned.
4738
4739(define_expand "push"
4740  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
4741	(match_operand:SI 0 "register_operand" "r,l,x"))]
4742  "TARGET_SH1 && ! TARGET_SH5"
4743  "")
4744
4745(define_expand "pop"
4746  [(set (match_operand:SI 0 "register_operand" "=r,l,x")
4747	(mem:SI (post_inc:SI (reg:SI SP_REG))))]
4748  "TARGET_SH1 && ! TARGET_SH5"
4749  "")
4750
4751(define_expand "push_e"
4752  [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
4753		   (match_operand:SF 0 "" ""))
4754	      (use (reg:PSI FPSCR_REG))
4755	      (clobber (scratch:SI))])]
4756  "TARGET_SH1 && ! TARGET_SH5"
4757  "")
4758
4759(define_insn "push_fpul"
4760  [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
4761  "TARGET_SH2E && ! TARGET_SH5"
4762  "sts.l	fpul,@-r15"
4763  [(set_attr "type" "fstore")
4764   (set_attr "late_fp_use" "yes")
4765   (set_attr "hit_stack" "yes")])
4766
4767;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
4768;; so use that.
4769(define_expand "push_4"
4770  [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
4771		   (match_operand:DF 0 "" ""))
4772	      (use (reg:PSI FPSCR_REG))
4773	      (clobber (scratch:SI))])]
4774  "TARGET_SH1 && ! TARGET_SH5"
4775  "")
4776
4777(define_expand "pop_e"
4778  [(parallel [(set (match_operand:SF 0 "" "")
4779	      (mem:SF (post_inc:SI (reg:SI SP_REG))))
4780	      (use (reg:PSI FPSCR_REG))
4781	      (clobber (scratch:SI))])]
4782  "TARGET_SH1 && ! TARGET_SH5"
4783  "")
4784
4785(define_insn "pop_fpul"
4786  [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
4787  "TARGET_SH2E && ! TARGET_SH5"
4788  "lds.l	@r15+,fpul"
4789  [(set_attr "type" "load")
4790   (set_attr "hit_stack" "yes")])
4791
4792(define_expand "pop_4"
4793  [(parallel [(set (match_operand:DF 0 "" "")
4794		   (mem:DF (post_inc:SI (reg:SI SP_REG))))
4795	      (use (reg:PSI FPSCR_REG))
4796	      (clobber (scratch:SI))])]
4797  "TARGET_SH1 && ! TARGET_SH5"
4798  "")
4799
4800(define_expand "push_fpscr"
4801  [(const_int 0)]
4802  "TARGET_SH2E"
4803  "
4804{
4805  rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
4806						 gen_rtx_PRE_DEC (Pmode,
4807							  stack_pointer_rtx)),
4808					get_fpscr_rtx ()));
4809  add_reg_note (insn, REG_INC, stack_pointer_rtx);
4810  DONE;
4811}")
4812
4813(define_expand "pop_fpscr"
4814  [(const_int 0)]
4815  "TARGET_SH2E"
4816  "
4817{
4818  rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
4819					gen_frame_mem (PSImode,
4820						 gen_rtx_POST_INC (Pmode,
4821							  stack_pointer_rtx))));
4822  add_reg_note (insn, REG_INC, stack_pointer_rtx);
4823  DONE;
4824}")
4825
4826;; These two patterns can happen as the result of optimization, when
4827;; comparisons get simplified to a move of zero or 1 into the T reg.
4828;; They don't disappear completely, because the T reg is a fixed hard reg.
4829
4830(define_insn "clrt"
4831  [(set (reg:SI T_REG) (const_int 0))]
4832  "TARGET_SH1"
4833  "clrt")
4834
4835(define_insn "sett"
4836  [(set (reg:SI T_REG) (const_int 1))]
4837  "TARGET_SH1"
4838  "sett")
4839
4840;; t/r must come after r/r, lest reload will try to reload stuff like
4841;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
4842;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
4843(define_insn "movsi_i"
4844  [(set (match_operand:SI 0 "general_movdst_operand"
4845	    "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
4846	(match_operand:SI 1 "general_movsrc_operand"
4847	 "Q,r,I08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
4848  "TARGET_SH1
4849   && ! TARGET_SH2E
4850   && ! TARGET_SH2A
4851   && (register_operand (operands[0], SImode)
4852       || register_operand (operands[1], SImode))"
4853  "@
4854	mov.l	%1,%0
4855	mov	%1,%0
4856	mov	%1,%0
4857	cmp/pl	%1
4858	mov.l	%1,%0
4859	sts	%1,%0
4860	sts	%1,%0
4861	movt	%0
4862	mov.l	%1,%0
4863	sts.l	%1,%0
4864	sts.l	%1,%0
4865	lds	%1,%0
4866	lds	%1,%0
4867	lds.l	%1,%0
4868	lds.l	%1,%0
4869	fake	%1,%0"
4870  [(set_attr "type" "pcload_si,move,movi8,mt_group,load_si,mac_gp,prget,arith,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,pcload_si")
4871   (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
4872
4873;; t/r must come after r/r, lest reload will try to reload stuff like
4874;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
4875;; ??? This allows moves from macl to fpul to be recognized, but these moves
4876;; will require a reload.
4877;; ??? We can't include f/f because we need the proper FPSCR setting when
4878;; TARGET_FMOVD is in effect, and mode switching is done before reload.
4879(define_insn "movsi_ie"
4880  [(set (match_operand:SI 0 "general_movdst_operand"
4881	    "=r,r,r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
4882	(match_operand:SI 1 "general_movsrc_operand"
4883	 "Q,r,I08,I20,I28,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
4884  "(TARGET_SH2E || TARGET_SH2A)
4885   && (register_operand (operands[0], SImode)
4886       || register_operand (operands[1], SImode))"
4887  "@
4888	mov.l	%1,%0
4889	mov	%1,%0
4890	mov	%1,%0
4891	movi20	%1,%0
4892	movi20s	%1,%0
4893	cmp/pl	%1
4894	mov.l	%1,%0
4895	sts	%1,%0
4896	sts	%1,%0
4897	movt	%0
4898	mov.l	%1,%0
4899	sts.l	%1,%0
4900	sts.l	%1,%0
4901	lds	%1,%0
4902	lds	%1,%0
4903	lds.l	%1,%0
4904	lds.l	%1,%0
4905	lds.l	%1,%0
4906	sts.l	%1,%0
4907	fake	%1,%0
4908	lds	%1,%0
4909	sts	%1,%0
4910	fsts	fpul,%0
4911	flds	%1,fpul
4912	fmov	%1,%0
4913	! move optimized away"
4914  [(set_attr "type" "pcload_si,move,movi8,move,move,*,load_si,mac_gp,prget,arith,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
4915   (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
4916   (set_attr_alternative "length"
4917     [(const_int 2)
4918      (const_int 2)
4919      (const_int 2)
4920      (const_int 4)
4921      (const_int 4)
4922      (const_int 2)
4923      (if_then_else
4924	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
4925	(const_int 4) (const_int 2))
4926      (const_int 2)
4927      (const_int 2)
4928      (const_int 2)
4929      (if_then_else
4930	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
4931	(const_int 4) (const_int 2))
4932      (const_int 2)
4933      (const_int 2)
4934      (const_int 2)
4935      (const_int 2)
4936      (const_int 2)
4937      (const_int 2)
4938      (const_int 2)
4939      (const_int 2)
4940      (const_int 2)
4941      (const_int 2)
4942      (const_int 2)
4943      (const_int 2)
4944      (const_int 2)
4945      (const_int 2)
4946      (const_int 0)])])
4947
4948(define_insn "movsi_i_lowpart"
4949  [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,r,m,r"))
4950	(match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,t,r,i"))]
4951   "TARGET_SH1
4952    && (register_operand (operands[0], SImode)
4953        || register_operand (operands[1], SImode))"
4954  "@
4955	mov.l	%1,%0
4956	mov	%1,%0
4957	mov	%1,%0
4958	mov.l	%1,%0
4959	sts	%1,%0
4960	sts	%1,%0
4961	movt	%0
4962	mov.l	%1,%0
4963	fake	%1,%0"
4964  [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,arith,store,pcload")])
4965
4966(define_insn_and_split "load_ra"
4967  [(set (match_operand:SI 0 "general_movdst_operand" "")
4968	(unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
4969  "TARGET_SH1"
4970  "#"
4971  "&& ! currently_expanding_to_rtl"
4972  [(set (match_dup 0) (match_dup 1))]
4973  "
4974{
4975  if (TARGET_SHCOMPACT && crtl->saves_all_registers)
4976    operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
4977}")
4978
4979;; The '?'s in the following constraints may not reflect the time taken
4980;; to perform the move. They are there to discourage the use of floating-
4981;; point registers for storing integer values.
4982(define_insn "*movsi_media"
4983  [(set (match_operand:SI 0 "general_movdst_operand"
4984	        "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
4985	(match_operand:SI 1 "general_movsrc_operand"
4986	 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
4987  "TARGET_SHMEDIA_FPU
4988   && (register_operand (operands[0], SImode)
4989       || sh_register_operand (operands[1], SImode)
4990       || GET_CODE (operands[1]) == TRUNCATE)"
4991  "@
4992	add.l	%1, r63, %0
4993	movi	%1, %0
4994	#
4995	ld%M1.l	%m1, %0
4996	st%M0.l	%m0, %N1
4997	fld%M1.s	%m1, %0
4998	fst%M0.s	%m0, %1
4999	fmov.ls	%N1, %0
5000	fmov.sl	%1, %0
5001	fmov.s	%1, %0
5002	ptabs	%1, %0
5003	gettr	%1, %0
5004	pt	%1, %0"
5005  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,fpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
5006   (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
5007   (set (attr "highpart")
5008	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5009	       (const_string "user")]
5010	      (const_string "ignore")))])
5011
5012(define_insn "*movsi_media_nofpu"
5013  [(set (match_operand:SI 0 "general_movdst_operand"
5014	        "=r,r,r,r,m,*b,r,*b")
5015	(match_operand:SI 1 "general_movsrc_operand"
5016	 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
5017  "TARGET_SHMEDIA
5018   && (register_operand (operands[0], SImode)
5019       || sh_register_operand (operands[1], SImode)
5020       || GET_CODE (operands[1]) == TRUNCATE)"
5021  "@
5022	add.l	%1, r63, %0
5023	movi	%1, %0
5024	#
5025	ld%M1.l	%m1, %0
5026	st%M0.l	%m0, %N1
5027	ptabs	%1, %0
5028	gettr	%1, %0
5029	pt	%1, %0"
5030  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5031   (set_attr "length" "4,4,8,4,4,4,4,12")
5032   (set (attr "highpart")
5033	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5034	       (const_string "user")]
5035	      (const_string "ignore")))])
5036
5037(define_expand "movsi_const"
5038  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5039	(const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5040			      (const_int 16)] UNSPEC_EXTRACT_S16)))
5041   (set (match_dup 0)
5042	(ior:SI (ashift:SI (match_dup 0) (const_int 16))
5043		(const:SI (unspec:SI [(match_dup 1)
5044				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
5045  "TARGET_SHMEDIA && reload_completed
5046   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5047  "
5048{
5049  if (GET_CODE (operands[1]) == LABEL_REF
5050      && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
5051    LABEL_NUSES (XEXP (operands[1], 0)) += 2;
5052  else if (GOTOFF_P (operands[1]))
5053    {
5054      rtx unspec = XEXP (operands[1], 0);
5055
5056      if (! UNSPEC_GOTOFF_P (unspec))
5057	{
5058	  unspec = XEXP (unspec, 0);
5059	  if (! UNSPEC_GOTOFF_P (unspec))
5060	    abort ();
5061	}
5062      if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
5063	  && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
5064	LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
5065    }
5066}")
5067
5068(define_expand "movsi_const_16bit"
5069  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
5070	(const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
5071			      (const_int 0)] UNSPEC_EXTRACT_S16)))]
5072  "TARGET_SHMEDIA && flag_pic && reload_completed
5073   && GET_CODE (operands[1]) == SYMBOL_REF"
5074  "")
5075
5076(define_split
5077  [(set (match_operand:SI 0 "arith_reg_dest" "")
5078	(match_operand:SI 1 "immediate_operand" ""))]
5079  "TARGET_SHMEDIA && reload_completed
5080   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5081  [(const_int 0)]
5082  "
5083{
5084  rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
5085
5086  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5087
5088  DONE;
5089}")
5090
5091(define_split
5092  [(set (match_operand:SI 0 "register_operand" "")
5093	(match_operand:SI 1 "immediate_operand" ""))]
5094  "TARGET_SHMEDIA && reload_completed
5095   && ((CONST_INT_P (operands[1])
5096	&& ! satisfies_constraint_I16 (operands[1]))
5097       || GET_CODE (operands[1]) == CONST_DOUBLE)"
5098  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5099
5100(define_expand "movsi"
5101  [(set (match_operand:SI 0 "general_movdst_operand" "")
5102	(match_operand:SI 1 "general_movsrc_operand" ""))]
5103  ""
5104  "{ if (prepare_move_operands (operands, SImode)) DONE; }")
5105
5106(define_expand "ic_invalidate_line"
5107  [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
5108				(match_dup 1)] UNSPEC_ICACHE)
5109	      (clobber (scratch:SI))])]
5110  "TARGET_HARD_SH4 || TARGET_SH5"
5111  "
5112{
5113  if (TARGET_SHMEDIA)
5114    {
5115      emit_insn (gen_ic_invalidate_line_media (operands[0]));
5116      DONE;
5117    }
5118  else if (TARGET_SHCOMPACT)
5119    {
5120      operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC);
5121      operands[1] = force_reg (Pmode, operands[1]);
5122      emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
5123      DONE;
5124    }
5125  else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
5126    {
5127      emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
5128      DONE;
5129    }
5130  operands[0] = force_reg (Pmode, operands[0]);
5131  operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
5132							       Pmode)));
5133}")
5134
5135;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
5136;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
5137;; the requirement *1*00 for associative address writes.  The alignment of
5138;; %0 implies that its least significant bit is cleared,
5139;; thus we clear the V bit of a matching entry if there is one.
5140(define_insn "ic_invalidate_line_i"
5141  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
5142		     (match_operand:SI 1 "register_operand" "r")]
5143		     UNSPEC_ICACHE)
5144   (clobber (match_scratch:SI 2 "=&r"))]
5145  "TARGET_HARD_SH4"
5146  "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
5147  [(set_attr "length" "8")
5148   (set_attr "type" "cwb")])
5149
5150(define_insn "ic_invalidate_line_sh4a"
5151  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
5152		    UNSPEC_ICACHE)]
5153  "TARGET_SH4A_ARCH || TARGET_SH4_300"
5154  "ocbwb\\t@%0\;synco\;icbi\\t@%0"
5155  [(set_attr "length" "16")
5156   (set_attr "type" "cwb")])
5157
5158;; ??? could make arg 0 an offsettable memory operand to allow to save
5159;; an add in the code that calculates the address.
5160(define_insn "ic_invalidate_line_media"
5161  [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
5162		    UNSPEC_ICACHE)]
5163  "TARGET_SHMEDIA"
5164  "ocbwb	%0,0\;synco\;icbi	%0, 0\;synci"
5165  [(set_attr "length" "16")
5166   (set_attr "type" "invalidate_line_media")])
5167
5168(define_insn "ic_invalidate_line_compact"
5169  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5170		     (match_operand:SI 1 "register_operand" "r")]
5171		    UNSPEC_ICACHE)
5172   (clobber (reg:SI PR_REG))]
5173  "TARGET_SHCOMPACT"
5174  "jsr @%1%#"
5175  [(set_attr "type" "sfunc")
5176   (set_attr "needs_delay_slot" "yes")])
5177
5178(define_expand "initialize_trampoline"
5179  [(match_operand:SI 0 "" "")
5180   (match_operand:SI 1 "" "")
5181   (match_operand:SI 2 "" "")]
5182  "TARGET_SHCOMPACT"
5183  "
5184{
5185  rtx sfun, tramp;
5186
5187  tramp = force_reg (Pmode, operands[0]);
5188  sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\",
5189					    SFUNC_STATIC));
5190  emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
5191  emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
5192
5193  emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
5194  DONE;
5195}")
5196
5197(define_insn "initialize_trampoline_compact"
5198  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
5199		     (match_operand:SI 1 "register_operand" "r")
5200		     (reg:SI R2_REG) (reg:SI R3_REG)]
5201		    UNSPEC_INIT_TRAMP)
5202
5203   (clobber (reg:SI PR_REG))]
5204  "TARGET_SHCOMPACT"
5205  "jsr @%1%#"
5206  [(set_attr "type" "sfunc")
5207   (set_attr "needs_delay_slot" "yes")])
5208
5209(define_insn "movqi_i"
5210  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m,r,r,l")
5211	(match_operand:QI 1 "general_movsrc_operand"  "r,i,m,r,t,l,r"))]
5212  "TARGET_SH1
5213   && (arith_reg_operand (operands[0], QImode)
5214       || arith_reg_operand (operands[1], QImode))"
5215  "@
5216	mov	%1,%0
5217	mov	%1,%0
5218	mov.b	%1,%0
5219	mov.b	%1,%0
5220	movt	%0
5221	sts	%1,%0
5222	lds	%1,%0"
5223 [(set_attr "type" "move,movi8,load,store,arith,prget,prset")
5224  (set_attr_alternative "length"
5225     [(const_int 2)
5226      (const_int 2)
5227      (if_then_else
5228	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
5229	(const_int 4) (const_int 2))
5230      (if_then_else
5231	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
5232	(const_int 4) (const_int 2))
5233      (const_int 2)
5234      (const_int 2)
5235      (const_int 2)])])
5236
5237(define_insn "*movqi_media"
5238  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
5239	(match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
5240  "TARGET_SHMEDIA
5241   && (arith_reg_operand (operands[0], QImode)
5242       || extend_reg_or_0_operand (operands[1], QImode))"
5243  "@
5244	add.l	%1, r63, %0
5245	movi	%1, %0
5246	ld%M1.ub	%m1, %0
5247	st%M0.b	%m0, %N1"
5248  [(set_attr "type" "arith_media,arith_media,load_media,store_media")
5249   (set (attr "highpart")
5250	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5251	       (const_string "user")]
5252	      (const_string "ignore")))])
5253
5254(define_expand "movqi"
5255  [(set (match_operand:QI 0 "general_operand" "")
5256	(match_operand:QI 1 "general_operand"  ""))]
5257  ""
5258  "{ if (prepare_move_operands (operands, QImode)) DONE; }")
5259
5260(define_expand "reload_inqi"
5261  [(set (match_operand:SI 2 "" "=&r")
5262	(match_operand:QI 1 "inqhi_operand" ""))
5263   (set (match_operand:QI 0 "arith_reg_operand" "=r")
5264	(truncate:QI (match_dup 3)))]
5265  "TARGET_SHMEDIA"
5266  "
5267{
5268  rtx inner = XEXP (operands[1], 0);
5269  int regno = REGNO (inner);
5270
5271  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5272  operands[1] = gen_rtx_REG (SImode, regno);
5273  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5274}")
5275
5276/* When storing r0, we have to avoid reg+reg addressing.  */
5277(define_insn "movhi_i"
5278  [(set (match_operand:HI 0 "general_movdst_operand"   "=r,r,r,r,m,r,l,r")
5279	(match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
5280  "TARGET_SH1
5281   && (arith_reg_operand (operands[0], HImode)
5282       || arith_reg_operand (operands[1], HImode))
5283   && (!MEM_P (operands[0])
5284       || GET_CODE (XEXP (operands[0], 0)) != PLUS
5285       || !REG_P (XEXP (XEXP (operands[0], 0), 1))
5286       || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
5287  "@
5288	mov.w	%1,%0
5289	mov	%1,%0
5290	mov.w	%1,%0
5291	movt	%0
5292	mov.w	%1,%0
5293	sts	%1,%0
5294	lds	%1,%0
5295	fake	%1,%0"
5296  [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
5297
5298(define_insn "*movhi_media"
5299  [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
5300	(match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
5301  "TARGET_SHMEDIA
5302   && (arith_reg_operand (operands[0], HImode)
5303       || arith_reg_or_0_operand (operands[1], HImode))"
5304  "@
5305	add.l	%1, r63, %0
5306	movi	%1, %0
5307	#
5308	ld%M1.w	%m1, %0
5309	st%M0.w	%m0, %N1"
5310  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
5311   (set (attr "highpart")
5312	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
5313	       (const_string "user")]
5314	      (const_string "ignore")))])
5315
5316(define_split
5317  [(set (match_operand:HI 0 "register_operand" "")
5318	(match_operand:HI 1 "immediate_operand" ""))]
5319  "TARGET_SHMEDIA && reload_completed
5320   && ! satisfies_constraint_I16 (operands[1])"
5321  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
5322
5323(define_expand "movhi"
5324  [(set (match_operand:HI 0 "general_movdst_operand" "")
5325	(match_operand:HI 1 "general_movsrc_operand"  ""))]
5326  ""
5327  "{ if (prepare_move_operands (operands, HImode)) DONE; }")
5328
5329(define_expand "reload_inhi"
5330  [(set (match_operand:SI 2 "" "=&r")
5331	(match_operand:HI 1 "inqhi_operand" ""))
5332   (set (match_operand:HI 0 "arith_reg_operand" "=r")
5333	(truncate:HI (match_dup 3)))]
5334  "TARGET_SHMEDIA"
5335  "
5336{
5337  rtx inner = XEXP (operands[1], 0);
5338  int regno = REGNO (inner);
5339
5340  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
5341  operands[1] = gen_rtx_REG (SImode, regno);
5342  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
5343}")
5344
5345;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
5346;; compiled with -m2 -ml -O3 -funroll-loops
5347(define_insn "*movdi_i"
5348  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
5349	(match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
5350  "TARGET_SH1
5351   && (arith_reg_operand (operands[0], DImode)
5352       || arith_reg_operand (operands[1], DImode))"
5353  "* return output_movedouble (insn, operands, DImode);"
5354  [(set_attr "length" "4")
5355   (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
5356
5357;; If the output is a register and the input is memory or a register, we have
5358;; to be careful and see which word needs to be loaded first.
5359
5360(define_split
5361  [(set (match_operand:DI 0 "general_movdst_operand" "")
5362	(match_operand:DI 1 "general_movsrc_operand" ""))]
5363  "TARGET_SH1 && reload_completed"
5364  [(set (match_dup 2) (match_dup 3))
5365   (set (match_dup 4) (match_dup 5))]
5366  "
5367{
5368  int regno;
5369
5370  if ((MEM_P (operands[0])
5371       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
5372      || (MEM_P (operands[1])
5373	  && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
5374    FAIL;
5375
5376  switch (GET_CODE (operands[0]))
5377    {
5378    case REG:
5379      regno = REGNO (operands[0]);
5380      break;
5381    case SUBREG:
5382      regno = subreg_regno (operands[0]);
5383      break;
5384    case MEM:
5385      regno = -1;
5386      break;
5387    default:
5388      gcc_unreachable ();
5389    }
5390
5391  if (regno == -1
5392      || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
5393    {
5394      operands[2] = operand_subword (operands[0], 0, 0, DImode);
5395      operands[3] = operand_subword (operands[1], 0, 0, DImode);
5396      operands[4] = operand_subword (operands[0], 1, 0, DImode);
5397      operands[5] = operand_subword (operands[1], 1, 0, DImode);
5398    }
5399  else
5400    {
5401      operands[2] = operand_subword (operands[0], 1, 0, DImode);
5402      operands[3] = operand_subword (operands[1], 1, 0, DImode);
5403      operands[4] = operand_subword (operands[0], 0, 0, DImode);
5404      operands[5] = operand_subword (operands[1], 0, 0, DImode);
5405    }
5406
5407  if (operands[2] == 0 || operands[3] == 0
5408      || operands[4] == 0 || operands[5] == 0)
5409    FAIL;
5410}")
5411
5412;; The '?'s in the following constraints may not reflect the time taken
5413;; to perform the move. They are there to discourage the use of floating-
5414;; point registers for storing integer values.
5415(define_insn "*movdi_media"
5416  [(set (match_operand:DI 0 "general_movdst_operand"
5417	         "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
5418	(match_operand:DI 1 "general_movsrc_operand"
5419	 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
5420  "TARGET_SHMEDIA_FPU
5421   && (register_operand (operands[0], DImode)
5422       || sh_register_operand (operands[1], DImode))"
5423  "@
5424	add	%1, r63, %0
5425	movi	%1, %0
5426	#
5427	ld%M1.q	%m1, %0
5428	st%M0.q	%m0, %N1
5429	fld%M1.d	%m1, %0
5430	fst%M0.d	%m0, %1
5431	fmov.qd	%N1, %0
5432	fmov.dq	%1, %0
5433	fmov.d	%1, %0
5434	ptabs	%1, %0
5435	gettr	%1, %0
5436	pt	%1, %0"
5437  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,dfpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
5438   (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
5439
5440(define_insn "*movdi_media_nofpu"
5441  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
5442	(match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
5443  "TARGET_SHMEDIA
5444   && (register_operand (operands[0], DImode)
5445       || sh_register_operand (operands[1], DImode))"
5446  "@
5447	add	%1, r63, %0
5448	movi	%1, %0
5449	#
5450	ld%M1.q	%m1, %0
5451	st%M0.q	%m0, %N1
5452	ptabs	%1, %0
5453	gettr	%1, %0
5454	pt	%1, %0"
5455  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
5456   (set_attr "length" "4,4,16,4,4,4,4,*")])
5457
5458(define_insn "*movdi_media_I16"
5459  [(set (match_operand:DI 0 "ext_dest_operand" "=r")
5460	(match_operand:DI 1 "const_int_operand" "I16"))]
5461  "TARGET_SHMEDIA && reload_completed"
5462  "movi	%1, %0"
5463  [(set_attr "type" "arith_media")
5464   (set_attr "length" "4")])
5465
5466(define_split
5467  [(set (match_operand:DI 0 "arith_reg_dest" "")
5468	(match_operand:DI 1 "immediate_operand" ""))]
5469  "TARGET_SHMEDIA && reload_completed
5470   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5471  [(set (match_dup 0) (match_dup 1))]
5472  "
5473{
5474  rtx insn;
5475
5476  if (TARGET_SHMEDIA64)
5477    insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
5478  else
5479    insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
5480
5481  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
5482
5483  DONE;
5484}")
5485
5486(define_expand "movdi_const"
5487  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5488	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5489		  	      (const_int 48)] UNSPEC_EXTRACT_S16)))
5490   (set (match_dup 0)
5491	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
5492		(const:DI (unspec:DI [(match_dup 1)
5493				      (const_int 32)] UNSPEC_EXTRACT_U16))))
5494   (set (match_dup 0)
5495	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
5496		(const:DI (unspec:DI [(match_dup 1)
5497				      (const_int 16)] UNSPEC_EXTRACT_U16))))
5498   (set (match_dup 0)
5499	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
5500		(const:DI (unspec:DI [(match_dup 1)
5501				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
5502  "TARGET_SHMEDIA64 && reload_completed
5503   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5504  "
5505{
5506  sh_mark_label (operands[1], 4);
5507}")
5508
5509(define_expand "movdi_const_32bit"
5510  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5511	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5512			      (const_int 16)] UNSPEC_EXTRACT_S16)))
5513   (set (match_dup 0)
5514	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
5515		(const:DI (unspec:DI [(match_dup 1)
5516				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
5517  "TARGET_SHMEDIA32 && reload_completed
5518   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
5519  "
5520{
5521  sh_mark_label (operands[1], 2);
5522}")
5523
5524(define_expand "movdi_const_16bit"
5525  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
5526	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
5527			      (const_int 0)] UNSPEC_EXTRACT_S16)))]
5528  "TARGET_SHMEDIA && flag_pic && reload_completed
5529   && GET_CODE (operands[1]) == SYMBOL_REF"
5530  "")
5531
5532(define_split
5533  [(set (match_operand:DI 0 "ext_dest_operand" "")
5534	(match_operand:DI 1 "immediate_operand" ""))]
5535  "TARGET_SHMEDIA && reload_completed
5536   && CONST_INT_P (operands[1])
5537   && ! satisfies_constraint_I16 (operands[1])"
5538  [(set (match_dup 0) (match_dup 2))
5539   (match_dup 1)]
5540  "
5541{
5542  unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5543  unsigned HOST_WIDE_INT low = val;
5544  unsigned HOST_WIDE_INT high = val;
5545  unsigned HOST_WIDE_INT sign;
5546  unsigned HOST_WIDE_INT val2 = val ^ (val-1);
5547
5548  /* Zero-extend the 16 least-significant bits.  */
5549  low &= 0xffff;
5550
5551  /* Arithmetic shift right the word by 16 bits.  */
5552  high >>= 16;
5553  if (GET_CODE (operands[0]) == SUBREG
5554      && GET_MODE (SUBREG_REG (operands[0])) == SImode)
5555    {
5556      high &= 0xffff;
5557      high ^= 0x8000;
5558      high -= 0x8000;
5559    }
5560  else
5561    {
5562      sign = 1;
5563      sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5564      high ^= sign;
5565      high -= sign;
5566    }
5567  do
5568    {
5569      /* If we can't generate the constant with a two-insn movi / shori
5570	 sequence, try some other strategies.  */
5571      if (! CONST_OK_FOR_I16 (high))
5572	{
5573	  /* Try constant load / left shift.  We know VAL != 0.  */
5574	  val2 = val ^ (val-1);
5575	  if (val2 > 0x1ffff)
5576	    {
5577	      int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
5578
5579	      if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
5580		  || (! CONST_OK_FOR_I16 (high >> 16)
5581		      && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
5582		{
5583		  val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
5584		  operands[1] = gen_ashldi3_media (operands[0], operands[0],
5585						   GEN_INT (trailing_zeroes));
5586		  break;
5587		}
5588	    }
5589	  /* Try constant load / right shift.  */
5590	  val2 = (val >> 15) + 1;
5591	  if (val2 == (val2 & -val2))
5592	    {
5593	      int shift = 49 - exact_log2 (val2);
5594
5595	      val2 = trunc_int_for_mode (val << shift, DImode);
5596	      if (CONST_OK_FOR_I16 (val2))
5597		{
5598		  operands[1] = gen_lshrdi3_media (operands[0], operands[0],
5599						   GEN_INT (shift));
5600		  break;
5601		}
5602	    }
5603	  /* Try mperm.w .  */
5604	  val2 = val & 0xffff;
5605	  if ((val >> 16 & 0xffff) == val2
5606	      && (val >> 32 & 0xffff) == val2
5607	      && (val >> 48 & 0xffff) == val2)
5608	    {
5609	      val2 = (HOST_WIDE_INT) val >> 48;
5610	      operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
5611	      operands[1] = gen_mperm_w0 (operands[1], operands[1]);
5612	      break;
5613	    }
5614	  /* Try movi / mshflo.l  */
5615	  val2 = (HOST_WIDE_INT) val >> 32;
5616	  if (val2 == ((unsigned HOST_WIDE_INT)
5617			trunc_int_for_mode (val, SImode)))
5618	    {
5619	      operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5620					     operands[0]);
5621	      break;
5622	    }
5623	  /* Try movi / mshflo.l w/ r63.  */
5624	  val2 = val + ((HOST_WIDE_INT) -1 << 32);
5625	  if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
5626	    {
5627	      operands[1] = gen_mshflo_l_di (operands[0], operands[0],
5628					     const0_rtx);
5629	      break;
5630	    }
5631	}
5632      val2 = high;
5633      operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
5634    }
5635  while (0);
5636  operands[2] = GEN_INT (val2);
5637}")
5638
5639(define_split
5640  [(set (match_operand:DI 0 "ext_dest_operand" "")
5641	(match_operand:DI 1 "immediate_operand" ""))]
5642  "TARGET_SHMEDIA && reload_completed
5643   && GET_CODE (operands[1]) == CONST_DOUBLE"
5644  [(set (match_dup 0) (match_dup 2))
5645  (set (match_dup 0)
5646       (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
5647  "
5648{
5649  unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
5650  unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
5651  unsigned HOST_WIDE_INT val = low;
5652  unsigned HOST_WIDE_INT sign;
5653
5654  /* Zero-extend the 16 least-significant bits.  */
5655  val &= 0xffff;
5656  operands[1] = GEN_INT (val);
5657
5658  /* Arithmetic shift right the double-word by 16 bits.  */
5659  low >>= 16;
5660  low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
5661  high >>= 16;
5662  sign = 1;
5663  sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
5664  high ^= sign;
5665  high -= sign;
5666
5667  /* This will only be true if high is a sign-extension of low, i.e.,
5668     it must be either 0 or (unsigned)-1, and be zero iff the
5669     most-significant bit of low is set.  */
5670  if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
5671    operands[2] = GEN_INT (low);
5672  else
5673    operands[2] = immed_double_const (low, high, DImode);
5674}")
5675
5676(define_insn "shori_media"
5677  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5678	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
5679			   (const_int 16))
5680		(match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
5681  "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
5682  "@
5683	shori	%u2, %0
5684	#"
5685  [(set_attr "type" "arith_media,*")])
5686
5687(define_insn "*shori_media_si"
5688  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5689	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5690			   (const_int 16))
5691		(match_operand:SI 2 "immediate_operand" "K16Csu")))]
5692  "TARGET_SHMEDIA"
5693  "shori	%u2, %0")
5694
5695(define_expand "movdi"
5696  [(set (match_operand:DI 0 "general_movdst_operand" "")
5697	(match_operand:DI 1 "general_movsrc_operand" ""))]
5698  ""
5699  "{ if (prepare_move_operands (operands, DImode)) DONE; }")
5700
5701(define_insn "movdf_media"
5702  [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
5703	(match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
5704  "TARGET_SHMEDIA_FPU
5705   && (register_operand (operands[0], DFmode)
5706       || sh_register_operand (operands[1], DFmode))"
5707  "@
5708	fmov.d	%1, %0
5709	fmov.qd	%N1, %0
5710	fmov.dq	%1, %0
5711	add	%1, r63, %0
5712	#
5713	fld%M1.d	%m1, %0
5714	fst%M0.d	%m0, %1
5715	ld%M1.q	%m1, %0
5716	st%M0.q	%m0, %N1"
5717  [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
5718
5719(define_insn "movdf_media_nofpu"
5720  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5721	(match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
5722  "TARGET_SHMEDIA
5723   && (register_operand (operands[0], DFmode)
5724       || sh_register_operand (operands[1], DFmode))"
5725  "@
5726	add	%1, r63, %0
5727	#
5728	ld%M1.q	%m1, %0
5729	st%M0.q	%m0, %N1"
5730  [(set_attr "type" "arith_media,*,load_media,store_media")])
5731
5732(define_split
5733  [(set (match_operand:DF 0 "arith_reg_dest" "")
5734	(match_operand:DF 1 "immediate_operand" ""))]
5735  "TARGET_SHMEDIA && reload_completed"
5736  [(set (match_dup 3) (match_dup 2))]
5737  "
5738{
5739  int endian = WORDS_BIG_ENDIAN ? 1 : 0;
5740  long values[2];
5741  REAL_VALUE_TYPE value;
5742
5743  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
5744  REAL_VALUE_TO_TARGET_DOUBLE (value, values);
5745
5746  if (HOST_BITS_PER_WIDE_INT >= 64)
5747    operands[2] = immed_double_const ((unsigned long) values[endian]
5748				      | ((HOST_WIDE_INT) values[1 - endian]
5749					 << 32), 0, DImode);
5750  else
5751    {
5752      gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
5753      operands[2] = immed_double_const (values[endian], values[1 - endian],
5754	  			        DImode);
5755    }
5756
5757  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5758}")
5759
5760;; ??? This should be a define expand.
5761
5762(define_insn "movdf_k"
5763  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
5764	(match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
5765  "TARGET_SH1
5766   && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
5767       /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
5768       || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
5769       || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
5770   && (arith_reg_operand (operands[0], DFmode)
5771       || arith_reg_operand (operands[1], DFmode))"
5772  "* return output_movedouble (insn, operands, DFmode);"
5773  [(set_attr "length" "4")
5774   (set_attr "type" "move,pcload,load,store")])
5775
5776;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
5777;; However, the d/F/c/z alternative cannot be split directly; it is converted
5778;; with special code in machine_dependent_reorg into a load of the R0_REG and
5779;; the d/m/c/X alternative, which is split later into single-precision
5780;; instructions.  And when not optimizing, no splits are done before fixing
5781;; up pcloads, so we need usable length information for that.
5782(define_insn "movdf_i4"
5783  [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
5784	(match_operand:DF 1 "general_movsrc_operand"  "d,r,F,m,d,FQ,m,r,d,r"))
5785   (use (match_operand:PSI 2 "fpscr_operand"          "c,c,c,c,c,c,c,c,c,c"))
5786   (clobber (match_scratch:SI 3                      "=X,X,&z,X,X,X,X,X,X,X"))]
5787  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5788   && (arith_reg_operand (operands[0], DFmode)
5789       || arith_reg_operand (operands[1], DFmode))"
5790  {
5791    switch (which_alternative)
5792    {
5793    case 0:
5794      if (TARGET_FMOVD)
5795	return "fmov	%1,%0";
5796      else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
5797	return "fmov	%R1,%R0\n\tfmov	%S1,%S0";
5798      else
5799	return "fmov	%S1,%S0\n\tfmov	%R1,%R0";
5800    case 3:
5801    case 4:
5802      return "fmov.d	%1,%0";
5803    default:
5804      return "#";
5805    }
5806  }
5807  [(set_attr_alternative "length"
5808     [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
5809      (const_int 4)
5810      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5811      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5812      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
5813      (const_int 4)
5814      (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
5815      ;; We can't use 4-byte push/pop on SHcompact, so we have to
5816      ;; increment or decrement r15 explicitly.
5817      (if_then_else
5818       (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5819       (const_int 10) (const_int 8))
5820      (if_then_else
5821       (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
5822       (const_int 10) (const_int 8))])
5823   (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
5824   (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
5825   (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
5826					   (const_string "double")
5827					   (const_string "none")))])
5828
5829;; Moving DFmode between fp/general registers through memory
5830;; (the top of the stack) is faster than moving through fpul even for
5831;; little endian.  Because the type of an instruction is important for its
5832;; scheduling,  it is beneficial to split these operations, rather than
5833;; emitting them in one single chunk, even if this will expose a stack
5834;; use that will prevent scheduling of other stack accesses beyond this
5835;; instruction.
5836(define_split
5837  [(set (match_operand:DF 0 "register_operand" "")
5838	(match_operand:DF 1 "register_operand" ""))
5839   (use (match_operand:PSI 2 "fpscr_operand" ""))
5840   (clobber (match_scratch:SI 3 "=X"))]
5841  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
5842   && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
5843  [(const_int 0)]
5844  "
5845{
5846  rtx insn, tos;
5847
5848  if (TARGET_SH5 && true_regnum (operands[1]) < 16)
5849    {
5850      emit_move_insn (stack_pointer_rtx,
5851		      plus_constant (stack_pointer_rtx, -8));
5852      tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5853    }
5854  else
5855    tos = gen_tmp_stack_mem (DFmode,
5856			     gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
5857  insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
5858  if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
5859    add_reg_note (insn, REG_INC, stack_pointer_rtx);
5860  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5861    tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
5862  else
5863    tos = gen_tmp_stack_mem (DFmode,
5864			     gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
5865  insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
5866  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
5867    emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
5868  else
5869    add_reg_note (insn, REG_INC, stack_pointer_rtx);
5870  DONE;
5871}")
5872
5873;; local-alloc sometimes allocates scratch registers even when not required,
5874;; so we must be prepared to handle these.
5875
5876;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
5877(define_split
5878  [(set (match_operand:DF 0 "general_movdst_operand" "")
5879	(match_operand:DF 1 "general_movsrc_operand"  ""))
5880   (use (match_operand:PSI 2 "fpscr_operand" ""))
5881   (clobber (match_scratch:SI 3 ""))]
5882  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
5883   && reload_completed
5884   && true_regnum (operands[0]) < 16
5885   && true_regnum (operands[1]) < 16"
5886  [(set (match_dup 0) (match_dup 1))]
5887  "
5888{
5889  /* If this was a reg <-> mem operation with base + index reg addressing,
5890     we have to handle this in a special way.  */
5891  rtx mem = operands[0];
5892  int store_p = 1;
5893  if (! memory_operand (mem, DFmode))
5894    {
5895      mem = operands[1];
5896      store_p = 0;
5897    }
5898  if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
5899    mem = SUBREG_REG (mem);
5900  if (MEM_P (mem))
5901    {
5902      rtx addr = XEXP (mem, 0);
5903      if (GET_CODE (addr) == PLUS
5904	  && REG_P (XEXP (addr, 0))
5905	  && REG_P (XEXP (addr, 1)))
5906	{
5907	  int offset;
5908	  rtx reg0 = gen_rtx_REG (Pmode, 0);
5909	  rtx regop = operands[store_p], word0 ,word1;
5910
5911	  if (GET_CODE (regop) == SUBREG)
5912	    alter_subreg (&regop);
5913	  if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
5914	    offset = 2;
5915	  else
5916	    offset = 4;
5917	  mem = copy_rtx (mem);
5918	  PUT_MODE (mem, SImode);
5919	  word0 = gen_rtx_SUBREG (SImode, regop, 0);
5920	  alter_subreg (&word0);
5921	  word1 = gen_rtx_SUBREG (SImode, regop, 4);
5922	  alter_subreg (&word1);
5923	  if (store_p || ! refers_to_regno_p (REGNO (word0),
5924					      REGNO (word0) + 1, addr, 0))
5925	    {
5926	      emit_insn (store_p
5927			 ? gen_movsi_ie (mem, word0)
5928			 : gen_movsi_ie (word0, mem));
5929	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5930	      mem = copy_rtx (mem);
5931	      emit_insn (store_p
5932			 ? gen_movsi_ie (mem, word1)
5933			 : gen_movsi_ie (word1, mem));
5934	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5935	    }
5936	  else
5937	    {
5938	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
5939	      emit_insn (gen_movsi_ie (word1, mem));
5940	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
5941	      mem = copy_rtx (mem);
5942	      emit_insn (gen_movsi_ie (word0, mem));
5943	    }
5944	  DONE;
5945	}
5946    }
5947}")
5948
5949;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
5950(define_split
5951  [(set (match_operand:DF 0 "register_operand" "")
5952	(match_operand:DF 1 "memory_operand"  ""))
5953   (use (match_operand:PSI 2 "fpscr_operand" ""))
5954   (clobber (reg:SI R0_REG))]
5955  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
5956  [(parallel [(set (match_dup 0) (match_dup 1))
5957	      (use (match_dup 2))
5958	      (clobber (scratch:SI))])]
5959  "")
5960
5961(define_expand "reload_indf__frn"
5962  [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
5963		   (match_operand:DF 1 "immediate_operand" "FQ"))
5964	      (use (reg:PSI FPSCR_REG))
5965	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
5966  "TARGET_SH1"
5967  "")
5968
5969(define_expand "reload_outdf__RnFRm"
5970  [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
5971		   (match_operand:DF 1 "register_operand" "af,r"))
5972	      (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
5973  "TARGET_SH1"
5974  "")
5975
5976;; Simplify no-op moves.
5977(define_split
5978  [(set (match_operand:SF 0 "register_operand" "")
5979	(match_operand:SF 1 "register_operand" ""))
5980   (use (match_operand:PSI 2 "fpscr_operand" ""))
5981   (clobber (match_scratch:SI 3 ""))]
5982  "TARGET_SH2E && reload_completed
5983   && true_regnum (operands[0]) == true_regnum (operands[1])"
5984  [(set (match_dup 0) (match_dup 0))]
5985  "")
5986
5987;; fmovd substitute post-reload splits
5988(define_split
5989  [(set (match_operand:DF 0 "register_operand" "")
5990	(match_operand:DF 1 "register_operand" ""))
5991   (use (match_operand:PSI 2 "fpscr_operand" ""))
5992   (clobber (match_scratch:SI 3 ""))]
5993  "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
5994   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
5995   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
5996  [(const_int 0)]
5997  "
5998{
5999  int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
6000  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
6001			   gen_rtx_REG (SFmode, src), operands[2]));
6002  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
6003			   gen_rtx_REG (SFmode, src + 1), operands[2]));
6004  DONE;
6005}")
6006
6007(define_split
6008  [(set (match_operand:DF 0 "register_operand" "")
6009	(mem:DF (match_operand:SI 1 "register_operand" "")))
6010   (use (match_operand:PSI 2 "fpscr_operand" ""))
6011   (clobber (match_scratch:SI 3 ""))]
6012  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6013   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
6014   && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
6015  [(const_int 0)]
6016  "
6017{
6018  int regno = true_regnum (operands[0]);
6019  rtx insn;
6020  rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
6021  rtx mem2
6022    = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
6023  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6024					   regno + !! TARGET_LITTLE_ENDIAN),
6025				  mem2, operands[2]));
6026  add_reg_note (insn, REG_INC, operands[1]);
6027  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
6028					       regno + ! TARGET_LITTLE_ENDIAN),
6029				  change_address (mem, SFmode, NULL_RTX),
6030				  operands[2]));
6031  DONE;
6032}")
6033
6034(define_split
6035  [(set (match_operand:DF 0 "register_operand" "")
6036	(match_operand:DF 1 "memory_operand" ""))
6037   (use (match_operand:PSI 2 "fpscr_operand" ""))
6038   (clobber (match_scratch:SI 3 ""))]
6039  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6040   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
6041  [(const_int 0)]
6042{
6043  int regno = true_regnum (operands[0]);
6044  rtx addr, insn;
6045  rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
6046  rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6047  rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6048
6049  operands[1] = copy_rtx (mem2);
6050  addr = XEXP (mem2, 0);
6051
6052  switch (GET_CODE (addr))
6053    {
6054    case REG:
6055      /* This is complicated.  If the register is an arithmetic register
6056         we can just fall through to the REG+DISP case below.  Otherwise
6057	 we have to use a combination of POST_INC and REG addressing...  */
6058      if (! arith_reg_operand (operands[1], SFmode))
6059        {
6060          XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
6061          insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
6062          add_reg_note (insn, REG_INC, XEXP (addr, 0));
6063	  
6064	  emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6065
6066          /* If we have modified the stack pointer, the value that we have
6067  	     read with post-increment might be modified by an interrupt,
6068	     so write it back.  */
6069          if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
6070	    emit_insn (gen_push_e (reg0));
6071          else
6072	    emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), GEN_INT (-4)));
6073	  break;
6074        }
6075      /* Fall through.  */
6076	 
6077    case PLUS:
6078      emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6079      operands[1] = copy_rtx (operands[1]);
6080      XEXP (operands[1], 0) = plus_constant (addr, 4);
6081      emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6082      break;
6083      
6084    case POST_INC:
6085      insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
6086      add_reg_note (insn, REG_INC, XEXP (addr, 0));
6087    
6088      insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
6089      add_reg_note (insn, REG_INC, XEXP (addr, 0));
6090      break;
6091
6092    default:
6093      debug_rtx (addr);
6094      gcc_unreachable ();
6095    }
6096
6097  DONE;
6098})
6099
6100(define_split
6101  [(set (match_operand:DF 0 "memory_operand" "")
6102	(match_operand:DF 1 "register_operand" ""))
6103   (use (match_operand:PSI 2 "fpscr_operand" ""))
6104   (clobber (match_scratch:SI 3 ""))]
6105  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
6106   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
6107  [(const_int 0)]
6108{
6109  int regno = true_regnum (operands[1]);
6110  rtx insn, addr;
6111  rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
6112  rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
6113
6114  operands[0] = copy_rtx (operands[0]);
6115  PUT_MODE (operands[0], SFmode);
6116  addr = XEXP (operands[0], 0);
6117
6118  switch (GET_CODE (addr))
6119    {
6120    case REG:
6121      /* This is complicated.  If the register is an arithmetic register
6122         we can just fall through to the REG+DISP case below.  Otherwise
6123	 we have to use a combination of REG and PRE_DEC addressing...  */
6124      if (! arith_reg_operand (operands[0], SFmode))
6125        {
6126	  emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
6127          emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6128
6129	  operands[0] = copy_rtx (operands[0]);
6130          XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
6131	  
6132          insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6133          add_reg_note (insn, REG_INC, XEXP (addr, 0));
6134	  break;
6135        }
6136      /* Fall through.  */
6137      
6138    case PLUS:
6139      /* Since REG+DISP addressing has already been decided upon by gcc
6140         we can rely upon it having chosen an arithmetic register as the
6141	 register component of the address.  Just emit the lower numbered
6142	 register first, to the lower address, then the higher numbered
6143	 register to the higher address.  */
6144      emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6145
6146      operands[0] = copy_rtx (operands[0]);
6147      XEXP (operands[0], 0) = plus_constant (addr, 4);
6148
6149      emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));	 
6150      break;
6151      
6152    case PRE_DEC:
6153      /* This is easy.  Output the word to go to the higher address
6154         first (ie the word in the higher numbered register) then the
6155	 word to go to the lower address.  */
6156
6157      insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
6158      add_reg_note (insn, REG_INC, XEXP (addr, 0));
6159
6160      insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
6161      add_reg_note (insn, REG_INC, XEXP (addr, 0));
6162      break;
6163      
6164    default:
6165      /* FAIL; */
6166      debug_rtx (addr);
6167      gcc_unreachable ();
6168    }
6169
6170  DONE;
6171})
6172
6173;; If the output is a register and the input is memory or a register, we have
6174;; to be careful and see which word needs to be loaded first.
6175
6176(define_split
6177  [(set (match_operand:DF 0 "general_movdst_operand" "")
6178	(match_operand:DF 1 "general_movsrc_operand" ""))]
6179  "TARGET_SH1 && reload_completed"
6180  [(set (match_dup 2) (match_dup 3))
6181   (set (match_dup 4) (match_dup 5))]
6182  "
6183{
6184  int regno;
6185
6186  if ((MEM_P (operands[0])
6187       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6188      || (MEM_P (operands[1])
6189	  && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6190    FAIL;
6191
6192  switch (GET_CODE (operands[0]))
6193    {
6194    case REG:
6195      regno = REGNO (operands[0]);
6196      break;
6197    case SUBREG:
6198      regno = subreg_regno (operands[0]);
6199      break;
6200    case MEM:
6201      regno = -1;
6202      break;
6203    default:
6204      gcc_unreachable ();
6205    }
6206
6207  if (regno == -1
6208      || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6209    {
6210      operands[2] = operand_subword (operands[0], 0, 0, DFmode);
6211      operands[3] = operand_subword (operands[1], 0, 0, DFmode);
6212      operands[4] = operand_subword (operands[0], 1, 0, DFmode);
6213      operands[5] = operand_subword (operands[1], 1, 0, DFmode);
6214    }
6215  else
6216    {
6217      operands[2] = operand_subword (operands[0], 1, 0, DFmode);
6218      operands[3] = operand_subword (operands[1], 1, 0, DFmode);
6219      operands[4] = operand_subword (operands[0], 0, 0, DFmode);
6220      operands[5] = operand_subword (operands[1], 0, 0, DFmode);
6221    }
6222
6223  if (operands[2] == 0 || operands[3] == 0
6224      || operands[4] == 0 || operands[5] == 0)
6225    FAIL;
6226}")
6227
6228;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
6229;; used only once, let combine add in the index again.
6230
6231(define_split
6232  [(set (match_operand:SI 0 "register_operand" "")
6233	(match_operand:SI 1 "" ""))
6234   (clobber (match_operand 2 "register_operand" ""))]
6235  "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6236   && ALLOW_INDEXED_ADDRESS"
6237  [(use (reg:SI R0_REG))]
6238  "
6239{
6240  rtx addr, reg, const_int;
6241
6242  if (!MEM_P (operands[1]))
6243    FAIL;
6244  addr = XEXP (operands[1], 0);
6245  if (GET_CODE (addr) != PLUS)
6246    FAIL;
6247  reg = XEXP (addr, 0);
6248  const_int = XEXP (addr, 1);
6249  if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6250	 && CONST_INT_P (const_int)))
6251    FAIL;
6252  emit_move_insn (operands[2], const_int);
6253  emit_move_insn (operands[0],
6254		  change_address (operands[1], VOIDmode,
6255				  gen_rtx_PLUS (SImode, reg, operands[2])));
6256  DONE;
6257}")
6258
6259(define_split
6260  [(set (match_operand:SI 1 "" "")
6261	(match_operand:SI 0 "register_operand" ""))
6262   (clobber (match_operand 2 "register_operand" ""))]
6263  "TARGET_SH1 && ! reload_in_progress && ! reload_completed
6264   && ALLOW_INDEXED_ADDRESS"
6265  [(use (reg:SI R0_REG))]
6266  "
6267{
6268  rtx addr, reg, const_int;
6269
6270  if (!MEM_P (operands[1]))
6271    FAIL;
6272  addr = XEXP (operands[1], 0);
6273  if (GET_CODE (addr) != PLUS)
6274    FAIL;
6275  reg = XEXP (addr, 0);
6276  const_int = XEXP (addr, 1);
6277  if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
6278	 && CONST_INT_P (const_int)))
6279    FAIL;
6280  emit_move_insn (operands[2], const_int);
6281  emit_move_insn (change_address (operands[1], VOIDmode,
6282				  gen_rtx_PLUS (SImode, reg, operands[2])),
6283		  operands[0]);
6284  DONE;
6285}")
6286
6287(define_expand "movdf"
6288  [(set (match_operand:DF 0 "general_movdst_operand" "")
6289	(match_operand:DF 1 "general_movsrc_operand" ""))]
6290  ""
6291  "
6292{
6293  if (prepare_move_operands (operands, DFmode)) DONE;
6294  if (TARGET_SHMEDIA)
6295    {
6296      if (TARGET_SHMEDIA_FPU)
6297	emit_insn (gen_movdf_media (operands[0], operands[1]));
6298      else
6299	emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
6300      DONE;
6301    }
6302  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
6303    {
6304      emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
6305      DONE;
6306    }
6307}")
6308
6309;;This is incompatible with the way gcc uses subregs.
6310;;(define_insn "movv2sf_i"
6311;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
6312;;	(match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
6313;;  "TARGET_SHMEDIA_FPU
6314;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
6315;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
6316;;  "@
6317;;	#
6318;;	fld%M1.p	%m1, %0
6319;;	fst%M0.p	%m0, %1"
6320;;  [(set_attr "type" "*,fload_media,fstore_media")])
6321
6322(define_insn_and_split "movv2sf_i"
6323  [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6324	(match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6325  "TARGET_SHMEDIA_FPU"
6326  "#"
6327  "TARGET_SHMEDIA_FPU && reload_completed"
6328  [(set (match_dup 0) (match_dup 1))]
6329  "
6330{
6331  operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
6332  operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
6333}")
6334
6335(define_expand "movv2sf"
6336  [(set (match_operand:V2SF 0 "general_movdst_operand" "")
6337	(match_operand:V2SF 1 "nonimmediate_operand" ""))]
6338  "TARGET_SHMEDIA_FPU"
6339  "
6340{
6341  if (prepare_move_operands (operands, V2SFmode))
6342    DONE;
6343}")
6344
6345(define_expand "addv2sf3"
6346  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6347   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6348   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6349  "TARGET_SHMEDIA_FPU"
6350  "
6351{
6352  sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
6353  DONE;
6354}")
6355
6356(define_expand "subv2sf3"
6357  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6358   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6359   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6360  "TARGET_SHMEDIA_FPU"
6361  "
6362{
6363  sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
6364  DONE;
6365}")
6366
6367(define_expand "mulv2sf3"
6368  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6369   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6370   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6371  "TARGET_SHMEDIA_FPU"
6372  "
6373{
6374  sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
6375  DONE;
6376}")
6377
6378(define_expand "divv2sf3"
6379  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
6380   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
6381   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
6382  "TARGET_SHMEDIA_FPU"
6383  "
6384{
6385  sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
6386  DONE;
6387}")
6388
6389(define_insn_and_split "*movv4sf_i"
6390  [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
6391	(match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
6392  "TARGET_SHMEDIA_FPU"
6393  "#"
6394  "&& reload_completed"
6395  [(const_int 0)]
6396  "
6397{
6398  int i;
6399
6400  for (i = 0; i < 4/2; i++)
6401    {
6402      rtx x, y;
6403
6404      if (MEM_P (operands[0]))
6405	x = adjust_address (operands[0], V2SFmode,
6406			    i * GET_MODE_SIZE (V2SFmode));
6407      else
6408	x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
6409
6410      if (MEM_P (operands[1]))
6411	y = adjust_address (operands[1], V2SFmode,
6412			    i * GET_MODE_SIZE (V2SFmode));
6413      else
6414	y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
6415
6416      emit_insn (gen_movv2sf_i (x, y));
6417    }
6418
6419  DONE;
6420}"
6421  [(set_attr "length" "8")])
6422
6423(define_expand "movv4sf"
6424  [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
6425	(match_operand:V4SF 1 "general_operand" ""))]
6426  "TARGET_SHMEDIA_FPU"
6427  "
6428{
6429  if (prepare_move_operands (operands, V4SFmode))
6430    DONE;
6431}")
6432
6433(define_insn_and_split "*movv16sf_i"
6434  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6435	(match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6436  "TARGET_SHMEDIA_FPU"
6437  "#"
6438  "&& reload_completed"
6439  [(const_int 0)]
6440  "
6441{
6442  int i;
6443
6444  for (i = 0; i < 16/2; i++)
6445    {
6446      rtx x,y;
6447
6448      if (MEM_P (operands[0]))
6449	x = adjust_address (operands[0], V2SFmode,
6450			    i * GET_MODE_SIZE (V2SFmode));
6451      else
6452	{
6453	  x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
6454	  alter_subreg (&x);
6455	}
6456
6457      if (MEM_P (operands[1]))
6458	y = adjust_address (operands[1], V2SFmode,
6459			    i * GET_MODE_SIZE (V2SFmode));
6460      else
6461	{
6462	  y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
6463	  alter_subreg (&y);
6464	}
6465
6466      emit_insn (gen_movv2sf_i (x, y));
6467    }
6468
6469  DONE;
6470}"
6471  [(set_attr "length" "32")])
6472
6473(define_expand "movv16sf"
6474  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
6475	(match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
6476  "TARGET_SHMEDIA_FPU"
6477  "
6478{
6479  if (prepare_move_operands (operands, V16SFmode))
6480    DONE;
6481}")
6482
6483(define_insn "movsf_media"
6484  [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
6485	(match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
6486  "TARGET_SHMEDIA_FPU
6487   && (register_operand (operands[0], SFmode)
6488       || sh_register_operand (operands[1], SFmode))"
6489  "@
6490	fmov.s	%1, %0
6491	fmov.ls	%N1, %0
6492	fmov.sl	%1, %0
6493	add.l	%1, r63, %0
6494	#
6495	fld%M1.s	%m1, %0
6496	fst%M0.s	%m0, %1
6497	ld%M1.l	%m1, %0
6498	st%M0.l	%m0, %N1"
6499  [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
6500   (set (attr "highpart")
6501	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6502	       (const_string "user")]
6503	      (const_string "ignore")))])
6504
6505(define_insn "movsf_media_nofpu"
6506  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
6507	(match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
6508  "TARGET_SHMEDIA
6509   && (register_operand (operands[0], SFmode)
6510       || sh_register_operand (operands[1], SFmode))"
6511  "@
6512	add.l	%1, r63, %0
6513	#
6514	ld%M1.l	%m1, %0
6515	st%M0.l	%m0, %N1"
6516  [(set_attr "type" "arith_media,*,load_media,store_media")
6517   (set (attr "highpart")
6518	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
6519	       (const_string "user")]
6520	      (const_string "ignore")))])
6521
6522(define_split
6523  [(set (match_operand:SF 0 "arith_reg_dest" "")
6524	(match_operand:SF 1 "immediate_operand" ""))]
6525  "TARGET_SHMEDIA && reload_completed
6526   && ! FP_REGISTER_P (true_regnum (operands[0]))"
6527  [(set (match_dup 3) (match_dup 2))]
6528  "
6529{
6530  long values;
6531  REAL_VALUE_TYPE value;
6532
6533  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
6534  REAL_VALUE_TO_TARGET_SINGLE (value, values);
6535  operands[2] = GEN_INT (values);
6536
6537  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6538}")
6539
6540(define_insn "movsf_i"
6541  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
6542	(match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
6543  "TARGET_SH1
6544   && (! TARGET_SH2E
6545       /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
6546       || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
6547       || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
6548   && (arith_reg_operand (operands[0], SFmode)
6549       || arith_reg_operand (operands[1], SFmode))"
6550  "@
6551	mov	%1,%0
6552	mov	#0,%0
6553	mov.l	%1,%0
6554	mov.l	%1,%0
6555	mov.l	%1,%0
6556	lds	%1,%0
6557	sts	%1,%0"
6558  [(set_attr "type" "move,move,pcload,load,store,move,move")])
6559
6560;; We may not split the ry/yr/XX alternatives to movsi_ie, since
6561;; update_flow_info would not know where to put REG_EQUAL notes
6562;; when the destination changes mode.
6563(define_insn "movsf_ie"
6564  [(set (match_operand:SF 0 "general_movdst_operand"
6565	 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
6566	(match_operand:SF 1 "general_movsrc_operand"
6567	  "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
6568   (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"))
6569   (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
6570
6571  "TARGET_SH2E
6572   && (arith_reg_operand (operands[0], SFmode)
6573       || arith_reg_operand (operands[1], SFmode)
6574       || arith_reg_operand (operands[3], SImode)
6575       || (fpul_operand (operands[0], SFmode)
6576	   && memory_operand (operands[1], SFmode)
6577	   && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
6578       || (fpul_operand (operands[1], SFmode)
6579	   && memory_operand (operands[0], SFmode)
6580	   && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
6581  "@
6582	fmov	%1,%0
6583	mov	%1,%0
6584	fldi0	%0
6585	fldi1	%0
6586	#
6587	fmov.s	%1,%0
6588	fmov.s	%1,%0
6589	mov.l	%1,%0
6590	mov.l	%1,%0
6591	mov.l	%1,%0
6592	fsts	fpul,%0
6593	flds	%1,fpul
6594	lds.l	%1,%0
6595	#
6596	sts	%1,%0
6597	lds	%1,%0
6598	sts.l	%1,%0
6599	lds.l	%1,%0
6600	! move optimized away"
6601  [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
6602   (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6603   (set_attr_alternative "length"
6604     [(const_int 2)
6605      (const_int 2)
6606      (const_int 2)
6607      (const_int 2)
6608      (const_int 4)
6609      (if_then_else
6610	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
6611	(const_int 4) (const_int 2))
6612      (if_then_else
6613	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
6614	(const_int 4) (const_int 2))
6615      (const_int 2)
6616      (if_then_else
6617	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
6618	(const_int 4) (const_int 2))
6619      (if_then_else
6620	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
6621	(const_int 4) (const_int 2))
6622      (const_int 2)
6623      (const_int 2)
6624      (const_int 2)
6625      (const_int 4)
6626      (const_int 2)
6627      (const_int 2)
6628      (const_int 2)
6629      (const_int 2)
6630      (const_int 0)])
6631   (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
6632					   (const_string "single")
6633					   (const_string "single")))])
6634
6635(define_split
6636  [(set (match_operand:SF 0 "register_operand" "")
6637	(match_operand:SF 1 "register_operand" ""))
6638   (use (match_operand:PSI 2 "fpscr_operand" ""))
6639   (clobber (reg:SI FPUL_REG))]
6640  "TARGET_SH1"
6641  [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
6642	      (use (match_dup 2))
6643	      (clobber (scratch:SI))])
6644   (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
6645	      (use (match_dup 2))
6646	      (clobber (scratch:SI))])]
6647  "")
6648
6649(define_expand "movsf"
6650  [(set (match_operand:SF 0 "general_movdst_operand" "")
6651        (match_operand:SF 1 "general_movsrc_operand" ""))]
6652  ""
6653  "
6654{
6655  if (prepare_move_operands (operands, SFmode))
6656    DONE;
6657  if (TARGET_SHMEDIA)
6658    {
6659      if (TARGET_SHMEDIA_FPU)
6660	emit_insn (gen_movsf_media (operands[0], operands[1]));
6661      else
6662	emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
6663      DONE;
6664    }
6665  if (TARGET_SH2E)
6666    {
6667      emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
6668      DONE;
6669    }
6670}")
6671
6672(define_insn "mov_nop"
6673  [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
6674  "TARGET_SH2E"
6675  ""
6676  [(set_attr "length" "0")
6677   (set_attr "type" "nil")])
6678
6679(define_expand "reload_insf__frn"
6680  [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
6681		   (match_operand:SF 1 "immediate_operand" "FQ"))
6682	      (use (reg:PSI FPSCR_REG))
6683	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6684  "TARGET_SH1"
6685  "")
6686
6687(define_expand "reload_insi__i_fpul"
6688  [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
6689		   (match_operand:SI 1 "immediate_operand" "i"))
6690	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
6691  "TARGET_SH1"
6692  "")
6693
6694(define_expand "ptabs"
6695  [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
6696  "TARGET_SHMEDIA"
6697  "
6698{
6699  if (!TARGET_PT_FIXED)
6700    {
6701      rtx eq = operands[1];
6702
6703      /* ??? For canonical RTL we really should remove any CONST from EQ
6704	 before wrapping it in the AND, and finally wrap the EQ into a
6705	 const if is constant.  However, for reload we must expose the
6706	 input register or symbolic constant, and we can't have
6707	 different insn structures outside of the operands for different
6708	 alternatives of the same pattern.  */
6709      eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
6710		       GEN_INT (3));
6711      operands[1]
6712	= (gen_rtx_IF_THEN_ELSE
6713	    (PDImode,
6714	     eq,
6715	     gen_rtx_MEM (PDImode, operands[1]),
6716	     gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
6717			    PDImode, operands[1])));
6718    }
6719}")
6720
6721;; expanded by ptabs expander.
6722(define_insn "*extendsipdi_media"
6723  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6724	(if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
6725							  "r,Csy")
6726				      (const_int 3))
6727			      (const_int 3))
6728			  (mem:PDI (match_dup 1))
6729			  (sign_extend:PDI (match_dup 1))))]
6730  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6731  "@
6732	ptabs	%1, %0
6733	pt	%1, %0"
6734  [(set_attr "type"   "ptabs_media,pt_media")
6735   (set_attr "length" "4,*")])
6736
6737(define_insn "*truncdipdi_media"
6738  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
6739	(if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
6740							  "r,Csy")
6741				      (const_int 3))
6742			      (const_int 3))
6743			  (mem:PDI (match_dup 1))
6744			  (truncate:PDI (match_dup 1))))]
6745  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
6746  "@
6747	ptabs	%1, %0
6748	pt	%1, %0"
6749  [(set_attr "type"   "ptabs_media,pt_media")
6750   (set_attr "length" "4,*")])
6751
6752(define_insn "*movsi_y"
6753  [(set (match_operand:SI 0 "register_operand" "=y,y")
6754	(match_operand:SI 1 "immediate_operand" "Qi,I08"))
6755   (clobber (match_scratch:SI 2 "=&z,r"))]
6756  "TARGET_SH2E
6757   && (reload_in_progress || reload_completed)"
6758  "#"
6759  [(set_attr "length" "4")
6760   (set_attr "type" "pcload,move")])
6761
6762(define_split
6763  [(set (match_operand:SI 0 "register_operand" "")
6764	(match_operand:SI 1 "immediate_operand" ""))
6765   (clobber (match_operand:SI 2 "register_operand" ""))]
6766  "TARGET_SH1"
6767  [(set (match_dup 2) (match_dup 1))
6768   (set (match_dup 0) (match_dup 2))]
6769  "")
6770
6771(define_split
6772  [(set (match_operand:SI 0 "register_operand" "")
6773	(match_operand:SI 1 "memory_operand" ""))
6774   (clobber (reg:SI R0_REG))]
6775  "TARGET_SH1"
6776  [(set (match_dup 0) (match_dup 1))]
6777  "")
6778
6779;; ------------------------------------------------------------------------
6780;; Define the real conditional branch instructions.
6781;; ------------------------------------------------------------------------
6782
6783(define_insn "branch_true"
6784  [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
6785			   (label_ref (match_operand 0 "" ""))
6786			   (pc)))]
6787  "TARGET_SH1"
6788  "* return output_branch (1, insn, operands);"
6789  [(set_attr "type" "cbranch")])
6790
6791(define_insn "branch_false"
6792  [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
6793			   (label_ref (match_operand 0 "" ""))
6794			   (pc)))]
6795  "TARGET_SH1"
6796  "* return output_branch (0, insn, operands);"
6797  [(set_attr "type" "cbranch")])
6798
6799;; Patterns to prevent reorg from re-combining a condbranch with a branch
6800;; which destination is too far away.
6801;; The const_int_operand is distinct for each branch target; it avoids
6802;; unwanted matches with redundant_insn.
6803(define_insn "block_branch_redirect"
6804  [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
6805  "TARGET_SH1"
6806  ""
6807  [(set_attr "length" "0")])
6808
6809;; This one has the additional purpose to record a possible scratch register
6810;; for the following branch.
6811;; ??? Unfortunately, just setting the scratch register is not good enough,
6812;; because the insn then might be deemed dead and deleted.  And we can't
6813;; make the use in the jump insn explicit because that would disable
6814;; delay slot scheduling from the target.
6815(define_insn "indirect_jump_scratch"
6816  [(set (match_operand:SI 0 "register_operand" "=r")
6817	(unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
6818   (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
6819  "TARGET_SH1"
6820  ""
6821  [(set_attr "length" "0")])
6822
6823;; This one is used to preemt an insn from beyond the bra / braf / jmp
6824;; being pulled into the delay slot of a condbranch that has been made to
6825;; jump around the unconditional jump because it was out of range.
6826(define_insn "stuff_delay_slot"
6827  [(set (pc)
6828	(unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
6829		 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
6830  "TARGET_SH1"
6831  ""
6832  [(set_attr "length" "0")
6833   (set_attr "cond_delay_slot" "yes")])
6834
6835;; Conditional branch insns
6836
6837(define_expand "cbranchint4_media"
6838  [(set (pc)
6839	(if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
6840		       [(match_operand 1 "" "")
6841			(match_operand 2 "" "")])
6842		      (match_operand 3 "" "")
6843		      (pc)))]
6844  "TARGET_SHMEDIA"
6845  "
6846{
6847  enum machine_mode mode = GET_MODE (operands[1]);
6848  if (mode == VOIDmode)
6849    mode = GET_MODE (operands[2]);
6850  if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
6851    {
6852      operands[1] = force_reg (mode, operands[1]);
6853      if (CONSTANT_P (operands[2])
6854          && (! satisfies_constraint_I06 (operands[2])))
6855        operands[2] = force_reg (mode, operands[2]);
6856    }
6857  else
6858    {
6859      if (operands[1] != const0_rtx)
6860        operands[1] = force_reg (mode, operands[1]);
6861      if (operands[2] != const0_rtx)
6862        operands[2] = force_reg (mode, operands[2]);
6863    }
6864  switch (GET_CODE (operands[0]))
6865    {
6866    case LEU:
6867    case LE:
6868    case LTU:
6869    case LT:
6870      operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
6871				    VOIDmode, operands[2], operands[1]);
6872      operands[1] = XEXP (operands[0], 0);
6873      operands[2] = XEXP (operands[0], 1);
6874      break;
6875    default:
6876      operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
6877				    VOIDmode, operands[1], operands[2]);
6878      break;
6879    }
6880  operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
6881}")
6882
6883(define_expand "cbranchfp4_media"
6884  [(set (pc)
6885	(if_then_else (match_operator 0 "sh_float_comparison_operator"
6886		       [(match_operand 1 "" "")
6887			(match_operand 2 "" "")])
6888		      (match_operand 3 "" "")
6889		      (pc)))]
6890  "TARGET_SHMEDIA"
6891  "
6892{
6893  rtx tmp = gen_reg_rtx (SImode);
6894  rtx cmp;
6895  if (GET_CODE (operands[0]) == NE)
6896    cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
6897  else
6898    cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
6899			  operands[1], operands[2]);
6900
6901  emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
6902
6903  if (GET_CODE (cmp) == GET_CODE (operands[0]))
6904    operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
6905  else
6906    operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
6907  operands[1] = tmp;
6908  operands[2] = const0_rtx;
6909  operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
6910}")
6911
6912(define_insn "*beq_media_i"
6913  [(set (pc)
6914	(if_then_else (match_operator 3 "equality_comparison_operator"
6915			[(match_operand:DI 1 "arith_reg_operand" "r,r")
6916			 (match_operand:DI 2 "arith_operand" "r,I06")])
6917		      (match_operand 0 "target_operand" "b,b")
6918		      (pc)))]
6919  "TARGET_SHMEDIA"
6920  "@
6921	b%o3%'	%1, %2, %0%>
6922	b%o3i%'	%1, %2, %0%>"
6923  [(set_attr "type" "cbranch_media")])
6924
6925(define_insn "*beq_media_i32"
6926  [(set (pc)
6927	(if_then_else (match_operator 3 "equality_comparison_operator"
6928			[(match_operand:SI 1 "arith_reg_operand" "r,r")
6929			 (match_operand:SI 2 "arith_operand" "r,I06")])
6930		      (match_operand 0 "target_operand" "b,b")
6931		      (pc)))]
6932  "TARGET_SHMEDIA"
6933  "@
6934	b%o3%'	%1, %2, %0%>
6935	b%o3i%'	%1, %2, %0%>"
6936  [(set_attr "type" "cbranch_media")])
6937
6938(define_insn "*bgt_media_i"
6939  [(set (pc)
6940	(if_then_else (match_operator 3 "greater_comparison_operator"
6941			[(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6942			 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6943		      (match_operand 0 "target_operand" "b")
6944		      (pc)))]
6945  "TARGET_SHMEDIA"
6946  "b%o3%'	%N1, %N2, %0%>"
6947  [(set_attr "type" "cbranch_media")])
6948
6949(define_insn "*bgt_media_i32"
6950  [(set (pc)
6951	(if_then_else (match_operator 3 "greater_comparison_operator"
6952			[(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6953			 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6954		      (match_operand 0 "target_operand" "b")
6955		      (pc)))]
6956  "TARGET_SHMEDIA"
6957  "b%o3%'	%N1, %N2, %0%>"
6958  [(set_attr "type" "cbranch_media")])
6959
6960;; These are only needed to make invert_jump() happy - otherwise, jump
6961;; optimization will be silently disabled.
6962(define_insn "*blt_media_i"
6963  [(set (pc)
6964	(if_then_else (match_operator 3 "less_comparison_operator"
6965			[(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
6966			 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
6967		      (match_operand 0 "target_operand" "b")
6968		      (pc)))]
6969  "TARGET_SHMEDIA"
6970  "b%o3%'	%N2, %N1, %0%>"
6971  [(set_attr "type" "cbranch_media")])
6972
6973(define_insn "*blt_media_i32"
6974  [(set (pc)
6975	(if_then_else (match_operator 3 "less_comparison_operator"
6976			[(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
6977			 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
6978		      (match_operand 0 "target_operand" "b")
6979		      (pc)))]
6980  "TARGET_SHMEDIA"
6981  "b%o3%'	%N2, %N1, %0%>"
6982  [(set_attr "type" "cbranch_media")])
6983
6984;; combiner splitter for test-and-branch on single bit in register.  This
6985;; is endian dependent because the non-paradoxical subreg looks different
6986;; on big endian.
6987(define_split
6988  [(set (pc)
6989	(if_then_else
6990	  (match_operator 3 "equality_comparison_operator"
6991	    [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
6992						      "extend_reg_operand" "")
6993						    0)
6994					 (const_int 1)
6995					 (match_operand 2
6996					  "const_int_operand" "")) 0)
6997	     (const_int 0)])
6998	  (match_operand 0 "target_operand" "")
6999	  (pc)))
7000   (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
7001  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
7002  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
7003   (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
7004
7005  "
7006{
7007  operands[5] = GEN_INT (31 - INTVAL (operands[2]));
7008  operands[6] = (GET_CODE (operands[3]) == EQ
7009		 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
7010		 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
7011}")
7012
7013; operand 0 is the loop count pseudo register
7014; operand 1 is the number of loop iterations or 0 if it is unknown
7015; operand 2 is the maximum number of loop iterations
7016; operand 3 is the number of levels of enclosed loops
7017; operand 4 is the label to jump to at the top of the loop
7018
7019(define_expand "doloop_end"
7020  [(parallel [(set (pc) (if_then_else
7021			  (ne:SI (match_operand:SI 0 "" "")
7022			      (const_int 1))
7023			  (label_ref (match_operand 4 "" ""))
7024			  (pc)))
7025	      (set (match_dup 0)
7026		   (plus:SI (match_dup 0) (const_int -1)))
7027	      (clobber (reg:SI T_REG))])]
7028  "TARGET_SH2"
7029  "
7030{
7031  if (GET_MODE (operands[0]) != SImode)
7032    FAIL;
7033}
7034")
7035
7036(define_insn_and_split "doloop_end_split"
7037  [(set (pc)
7038	(if_then_else (ne:SI (match_operand:SI 0 "arith_reg_dest" "+r")
7039			  (const_int 1))
7040		      (label_ref (match_operand 1 "" ""))
7041		      (pc)))
7042   (set (match_dup 0)
7043	(plus (match_dup 0) (const_int -1)))
7044   (clobber (reg:SI T_REG))]
7045  "TARGET_SH2"
7046  "#"
7047  ""
7048  [(parallel [(set (reg:SI T_REG)
7049		   (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r")
7050			  (const_int 1)))
7051	      (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))])
7052   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
7053			   (label_ref (match_operand 1 "" ""))
7054			   (pc)))]
7055""
7056   [(set_attr "type" "cbranch")])
7057
7058
7059;; ------------------------------------------------------------------------
7060;; Jump and linkage insns
7061;; ------------------------------------------------------------------------
7062
7063(define_insn "jump_compact"
7064  [(set (pc)
7065	(label_ref (match_operand 0 "" "")))]
7066  "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
7067  "*
7068{
7069  /* The length is 16 if the delay slot is unfilled.  */
7070  if (get_attr_length(insn) > 4)
7071    return output_far_jump(insn, operands[0]);
7072  else
7073    return   \"bra	%l0%#\";
7074}"
7075  [(set_attr "type" "jump")
7076   (set_attr "needs_delay_slot" "yes")])
7077
7078;; ??? It would be much saner to explicitly use the scratch register
7079;; in the jump insn, and have indirect_jump_scratch only set it,
7080;; but fill_simple_delay_slots would refuse to do delay slot filling
7081;; from the target then, as it uses simplejump_p.
7082;;(define_insn "jump_compact_far"
7083;;  [(set (pc)
7084;;	(label_ref (match_operand 0 "" "")))
7085;;   (use (match_operand 1 "register_operand" "r")]
7086;;  "TARGET_SH1"
7087;;  "* return output_far_jump(insn, operands[0], operands[1]);"
7088;;  [(set_attr "type" "jump")
7089;;   (set_attr "needs_delay_slot" "yes")])
7090
7091(define_insn "jump_media"
7092  [(set (pc)
7093	(match_operand 0 "target_operand" "b"))]
7094  "TARGET_SHMEDIA"
7095  "blink	%0, r63%>"
7096  [(set_attr "type" "jump_media")])
7097
7098(define_expand "jump"
7099  [(set (pc)
7100	(label_ref (match_operand 0 "" "")))]
7101  ""
7102  "
7103{
7104  if (TARGET_SH1)
7105    emit_jump_insn (gen_jump_compact (operands[0]));
7106  else if (TARGET_SHMEDIA)
7107    {
7108      if (reload_in_progress || reload_completed)
7109	FAIL;
7110      emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
7111							 operands[0])));
7112    }
7113  DONE;
7114}")
7115
7116(define_insn "force_mode_for_call"
7117  [(use (reg:PSI FPSCR_REG))]
7118  "TARGET_SHCOMPACT"
7119  ""
7120  [(set_attr "length" "0")
7121   (set (attr "fp_mode")
7122	(if_then_else (eq_attr "fpu_single" "yes")
7123		      (const_string "single") (const_string "double")))])
7124
7125(define_insn "calli"
7126  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7127	 (match_operand 1 "" ""))
7128   (use (reg:PSI FPSCR_REG))
7129   (clobber (reg:SI PR_REG))]
7130  "TARGET_SH1"
7131  "*
7132   {
7133     if (TARGET_SH2A && (dbr_sequence_length () == 0))
7134	return \"jsr/n\\t@%0\";
7135     else
7136	return \"jsr\\t@%0%#\";
7137   }"
7138
7139  [(set_attr "type" "call")
7140   (set (attr "fp_mode")
7141	(if_then_else (eq_attr "fpu_single" "yes")
7142		      (const_string "single") (const_string "double")))
7143   (set_attr "needs_delay_slot" "yes")
7144   (set_attr "fp_set" "unknown")])
7145
7146;; This is TBR relative jump instruction for SH2A architecture.
7147;; Its use is enabled assigning an attribute "function_vector"
7148;; and the vector number to a function during its declaration.
7149
7150(define_insn "calli_tbr_rel"
7151  [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
7152	 (match_operand 1 "" ""))
7153   (use (reg:PSI FPSCR_REG))
7154   (clobber (reg:SI PR_REG))]
7155  "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
7156  "*
7157{
7158  unsigned HOST_WIDE_INT vect_num;
7159  vect_num = sh2a_get_function_vector_number (operands[0]);
7160  operands[2] = GEN_INT (vect_num * 4);
7161
7162  return \"jsr/n\\t@@(%O2,tbr)\";
7163}"
7164  [(set_attr "type" "call")
7165   (set (attr "fp_mode")
7166	(if_then_else (eq_attr "fpu_single" "yes")
7167		      (const_string "single") (const_string "double")))
7168   (set_attr "needs_delay_slot" "no")
7169   (set_attr "fp_set" "unknown")])
7170
7171;; This is a pc-rel call, using bsrf, for use with PIC.
7172
7173(define_insn "calli_pcrel"
7174  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7175	 (match_operand 1 "" ""))
7176   (use (reg:PSI FPSCR_REG))
7177   (use (reg:SI PIC_REG))
7178   (use (match_operand 2 "" ""))
7179   (clobber (reg:SI PR_REG))]
7180  "TARGET_SH2"
7181  "bsrf	%0\\n%O2:%#"
7182  [(set_attr "type" "call")
7183   (set (attr "fp_mode")
7184	(if_then_else (eq_attr "fpu_single" "yes")
7185		      (const_string "single") (const_string "double")))
7186   (set_attr "needs_delay_slot" "yes")
7187   (set_attr "fp_set" "unknown")])
7188
7189(define_insn_and_split "call_pcrel"
7190  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7191	 (match_operand 1 "" ""))
7192   (use (reg:PSI FPSCR_REG))
7193   (use (reg:SI PIC_REG))
7194   (clobber (reg:SI PR_REG))
7195   (clobber (match_scratch:SI 2 "=r"))]
7196  "TARGET_SH2"
7197  "#"
7198  "reload_completed"
7199  [(const_int 0)]
7200  "
7201{
7202  rtx lab = PATTERN (gen_call_site ());
7203
7204  if (SYMBOL_REF_LOCAL_P (operands[0]))
7205    emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7206  else
7207    emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
7208  emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
7209  DONE;
7210}"
7211  [(set_attr "type" "call")
7212   (set (attr "fp_mode")
7213	(if_then_else (eq_attr "fpu_single" "yes")
7214		      (const_string "single") (const_string "double")))
7215   (set_attr "needs_delay_slot" "yes")
7216   (set_attr "fp_set" "unknown")])
7217
7218(define_insn "call_compact"
7219  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7220	 (match_operand 1 "" ""))
7221   (match_operand 2 "immediate_operand" "n")
7222   (use (reg:SI R0_REG))
7223   (use (reg:SI R1_REG))
7224   (use (reg:PSI FPSCR_REG))
7225   (clobber (reg:SI PR_REG))]
7226  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7227  "jsr	@%0%#"
7228  [(set_attr "type" "call")
7229   (set (attr "fp_mode")
7230	(if_then_else (eq_attr "fpu_single" "yes")
7231		      (const_string "single") (const_string "double")))
7232   (set_attr "needs_delay_slot" "yes")])
7233
7234(define_insn "call_compact_rettramp"
7235  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7236	 (match_operand 1 "" ""))
7237   (match_operand 2 "immediate_operand" "n")
7238   (use (reg:SI R0_REG))
7239   (use (reg:SI R1_REG))
7240   (use (reg:PSI FPSCR_REG))
7241   (clobber (reg:SI R10_REG))
7242   (clobber (reg:SI PR_REG))]
7243  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7244  "jsr	@%0%#"
7245  [(set_attr "type" "call")
7246   (set (attr "fp_mode")
7247	(if_then_else (eq_attr "fpu_single" "yes")
7248		      (const_string "single") (const_string "double")))
7249   (set_attr "needs_delay_slot" "yes")])
7250
7251(define_insn "call_media"
7252  [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
7253	 (match_operand 1 "" ""))
7254   (clobber (reg:DI PR_MEDIA_REG))]
7255  "TARGET_SHMEDIA"
7256  "blink	%0, r18"
7257  [(set_attr "type" "jump_media")])
7258
7259(define_insn "call_valuei"
7260  [(set (match_operand 0 "" "=rf")
7261	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7262	      (match_operand 2 "" "")))
7263   (use (reg:PSI FPSCR_REG))
7264   (clobber (reg:SI PR_REG))]
7265  "TARGET_SH1"
7266  "*
7267   {
7268     if (TARGET_SH2A && (dbr_sequence_length () == 0))
7269	return \"jsr/n\\t@%1\";
7270     else
7271	return \"jsr\\t@%1%#\";
7272   }"
7273  [(set_attr "type" "call")
7274   (set (attr "fp_mode")
7275	(if_then_else (eq_attr "fpu_single" "yes")
7276		      (const_string "single") (const_string "double")))
7277   (set_attr "needs_delay_slot" "yes")
7278   (set_attr "fp_set" "unknown")])
7279
7280;; This is TBR relative jump instruction for SH2A architecture.
7281;; Its use is enabled assigning an attribute "function_vector"
7282;; and the vector number to a function during its declaration.
7283
7284(define_insn "call_valuei_tbr_rel"
7285  [(set (match_operand 0 "" "=rf")
7286	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7287	      (match_operand 2 "" "")))
7288   (use (reg:PSI FPSCR_REG))
7289   (clobber (reg:SI PR_REG))]
7290  "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
7291  "*
7292{
7293  unsigned HOST_WIDE_INT vect_num;
7294  vect_num = sh2a_get_function_vector_number (operands[1]);
7295  operands[3] = GEN_INT (vect_num * 4);
7296
7297  return \"jsr/n\\t@@(%O3,tbr)\";
7298}"
7299  [(set_attr "type" "call")
7300   (set (attr "fp_mode")
7301	(if_then_else (eq_attr "fpu_single" "yes")
7302		      (const_string "single") (const_string "double")))
7303   (set_attr "needs_delay_slot" "no")
7304   (set_attr "fp_set" "unknown")])
7305
7306(define_insn "call_valuei_pcrel"
7307  [(set (match_operand 0 "" "=rf")
7308	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7309	      (match_operand 2 "" "")))
7310   (use (reg:PSI FPSCR_REG))
7311   (use (reg:SI PIC_REG))
7312   (use (match_operand 3 "" ""))
7313   (clobber (reg:SI PR_REG))]
7314  "TARGET_SH2"
7315  "bsrf	%1\\n%O3:%#"
7316  [(set_attr "type" "call")
7317   (set (attr "fp_mode")
7318	(if_then_else (eq_attr "fpu_single" "yes")
7319		      (const_string "single") (const_string "double")))
7320   (set_attr "needs_delay_slot" "yes")
7321   (set_attr "fp_set" "unknown")])
7322
7323(define_insn_and_split "call_value_pcrel"
7324  [(set (match_operand 0 "" "=rf")
7325	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7326	      (match_operand 2 "" "")))
7327   (use (reg:PSI FPSCR_REG))
7328   (use (reg:SI PIC_REG))
7329   (clobber (reg:SI PR_REG))
7330   (clobber (match_scratch:SI 3 "=r"))]
7331  "TARGET_SH2"
7332  "#"
7333  "reload_completed"
7334  [(const_int 0)]
7335  "
7336{
7337  rtx lab = PATTERN (gen_call_site ());
7338
7339  if (SYMBOL_REF_LOCAL_P (operands[1]))
7340    emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7341  else
7342    emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
7343  emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
7344					 operands[2], copy_rtx (lab)));
7345  DONE;
7346}"
7347  [(set_attr "type" "call")
7348   (set (attr "fp_mode")
7349	(if_then_else (eq_attr "fpu_single" "yes")
7350		      (const_string "single") (const_string "double")))
7351   (set_attr "needs_delay_slot" "yes")
7352   (set_attr "fp_set" "unknown")])
7353
7354(define_insn "call_value_compact"
7355  [(set (match_operand 0 "" "=rf")
7356	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7357	      (match_operand 2 "" "")))
7358   (match_operand 3 "immediate_operand" "n")
7359   (use (reg:SI R0_REG))
7360   (use (reg:SI R1_REG))
7361   (use (reg:PSI FPSCR_REG))
7362   (clobber (reg:SI PR_REG))]
7363  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7364  "jsr	@%1%#"
7365  [(set_attr "type" "call")
7366   (set (attr "fp_mode")
7367	(if_then_else (eq_attr "fpu_single" "yes")
7368		      (const_string "single") (const_string "double")))
7369   (set_attr "needs_delay_slot" "yes")])
7370
7371(define_insn "call_value_compact_rettramp"
7372  [(set (match_operand 0 "" "=rf")
7373	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
7374	      (match_operand 2 "" "")))
7375   (match_operand 3 "immediate_operand" "n")
7376   (use (reg:SI R0_REG))
7377   (use (reg:SI R1_REG))
7378   (use (reg:PSI FPSCR_REG))
7379   (clobber (reg:SI R10_REG))
7380   (clobber (reg:SI PR_REG))]
7381  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
7382  "jsr	@%1%#"
7383  [(set_attr "type" "call")
7384   (set (attr "fp_mode")
7385	(if_then_else (eq_attr "fpu_single" "yes")
7386		      (const_string "single") (const_string "double")))
7387   (set_attr "needs_delay_slot" "yes")])
7388
7389(define_insn "call_value_media"
7390  [(set (match_operand 0 "" "=rf")
7391	(call (mem:DI (match_operand 1 "target_reg_operand" "b"))
7392	      (match_operand 2 "" "")))
7393   (clobber (reg:DI PR_MEDIA_REG))]
7394  "TARGET_SHMEDIA"
7395  "blink	%1, r18"
7396  [(set_attr "type" "jump_media")])
7397
7398(define_expand "call"
7399  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7400			    (match_operand 1 "" ""))
7401	      (match_operand 2 "" "")
7402	      (use (reg:PSI FPSCR_REG))
7403	      (clobber (reg:SI PR_REG))])]
7404  ""
7405  "
7406{
7407  if (TARGET_SHMEDIA)
7408    {
7409      operands[0] = shmedia_prepare_call_address (operands[0], 0);
7410      emit_call_insn (gen_call_media (operands[0], operands[1]));
7411      DONE;
7412    }
7413  else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
7414    {
7415      rtx cookie_rtx = operands[2];
7416      long cookie = INTVAL (cookie_rtx);
7417      rtx func = XEXP (operands[0], 0);
7418      rtx r0, r1;
7419
7420      if (flag_pic)
7421	{
7422	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7423	    {
7424	      rtx reg = gen_reg_rtx (Pmode);
7425
7426	      emit_insn (gen_symGOTPLT2reg (reg, func));
7427	      func = reg;
7428	    }
7429	  else
7430	    func = legitimize_pic_address (func, Pmode, 0);
7431	}
7432
7433      r0 = gen_rtx_REG (SImode, R0_REG);
7434      r1 = gen_rtx_REG (SImode, R1_REG);
7435
7436      /* Since such a call function may use all call-clobbered
7437	 registers, we force a mode switch earlier, so that we don't
7438	 run out of registers when adjusting fpscr for the call.  */
7439      emit_insn (gen_force_mode_for_call ());
7440
7441      operands[0]
7442	= function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7443			   SFUNC_GOT);
7444      operands[0] = force_reg (SImode, operands[0]);
7445
7446      emit_move_insn (r0, func);
7447      emit_move_insn (r1, cookie_rtx);
7448
7449      if (cookie & CALL_COOKIE_RET_TRAMP (1))
7450	emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
7451						   operands[2]));
7452      else
7453	emit_call_insn (gen_call_compact (operands[0], operands[1],
7454					  operands[2]));
7455
7456      DONE;
7457    }
7458  else if (TARGET_SHCOMPACT && flag_pic
7459	   && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7460	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7461    {
7462      rtx reg = gen_reg_rtx (Pmode);
7463
7464      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
7465      XEXP (operands[0], 0) = reg;
7466    }
7467  if (!flag_pic && TARGET_SH2A
7468      && MEM_P (operands[0])
7469      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7470    {
7471      if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
7472	{
7473	  emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
7474					     operands[1]));
7475	  DONE;
7476	}
7477    }
7478  if (flag_pic && TARGET_SH2
7479      && MEM_P (operands[0])
7480      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
7481    {
7482      emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
7483      DONE;
7484    }
7485  else
7486  {
7487    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7488    operands[1] = operands[2];
7489  }
7490
7491  emit_call_insn (gen_calli (operands[0], operands[1]));
7492  DONE;
7493}")
7494
7495(define_insn "call_pop_compact"
7496  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7497	 (match_operand 1 "" ""))
7498   (match_operand 2 "immediate_operand" "n")
7499   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7500				 (match_operand 3 "immediate_operand" "n")))
7501   (use (reg:SI R0_REG))
7502   (use (reg:SI R1_REG))
7503   (use (reg:PSI FPSCR_REG))
7504   (clobber (reg:SI PR_REG))]
7505  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7506  "jsr	@%0%#"
7507  [(set_attr "type" "call")
7508   (set (attr "fp_mode")
7509	(if_then_else (eq_attr "fpu_single" "yes")
7510		      (const_string "single") (const_string "double")))
7511   (set_attr "needs_delay_slot" "yes")])
7512
7513(define_insn "call_pop_compact_rettramp"
7514  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
7515	 (match_operand 1 "" ""))
7516   (match_operand 2 "immediate_operand" "n")
7517   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7518				 (match_operand 3 "immediate_operand" "n")))
7519   (use (reg:SI R0_REG))
7520   (use (reg:SI R1_REG))
7521   (use (reg:PSI FPSCR_REG))
7522   (clobber (reg:SI R10_REG))
7523   (clobber (reg:SI PR_REG))]
7524  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
7525  "jsr	@%0%#"
7526  [(set_attr "type" "call")
7527   (set (attr "fp_mode")
7528	(if_then_else (eq_attr "fpu_single" "yes")
7529		      (const_string "single") (const_string "double")))
7530   (set_attr "needs_delay_slot" "yes")])
7531
7532(define_expand "call_pop"
7533  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7534		    (match_operand 1 "" ""))
7535	     (match_operand 2 "" "")
7536	     (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
7537					   (match_operand 3 "" "")))])]
7538  "TARGET_SHCOMPACT"
7539  "
7540{
7541  rtx cookie_rtx;
7542  long cookie;
7543  rtx func;
7544  rtx r0, r1;
7545
7546  gcc_assert (operands[2] && INTVAL (operands[2]));
7547  cookie_rtx = operands[2];
7548  cookie = INTVAL (cookie_rtx);
7549  func = XEXP (operands[0], 0);
7550
7551  if (flag_pic)
7552    {
7553      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7554        {
7555	  rtx reg = gen_reg_rtx (Pmode);
7556	  emit_insn (gen_symGOTPLT2reg (reg, func));
7557	  func = reg;
7558	}
7559      else
7560        func = legitimize_pic_address (func, Pmode, 0);
7561    }
7562
7563  r0 = gen_rtx_REG (SImode, R0_REG);
7564  r1 = gen_rtx_REG (SImode, R1_REG);
7565
7566  /* Since such a call function may use all call-clobbered
7567     registers, we force a mode switch earlier, so that we don't
7568     run out of registers when adjusting fpscr for the call.  */
7569  emit_insn (gen_force_mode_for_call ());
7570
7571  operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7572				 SFUNC_GOT);
7573  operands[0] = force_reg (SImode, operands[0]);
7574
7575  emit_move_insn (r0, func);
7576  emit_move_insn (r1, cookie_rtx);
7577
7578  if (cookie & CALL_COOKIE_RET_TRAMP (1))
7579    emit_call_insn (gen_call_pop_compact_rettramp
7580	   	     (operands[0], operands[1], operands[2], operands[3]));
7581  else
7582    emit_call_insn (gen_call_pop_compact
7583	  	     (operands[0], operands[1], operands[2], operands[3]));
7584
7585  DONE;
7586}")
7587
7588(define_expand "call_value"
7589  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
7590		   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7591				 (match_operand 2 "" "")))
7592	      (match_operand 3 "" "")
7593	      (use (reg:PSI FPSCR_REG))
7594	      (clobber (reg:SI PR_REG))])]
7595  ""
7596  "
7597{
7598  if (TARGET_SHMEDIA)
7599    {
7600      operands[1] = shmedia_prepare_call_address (operands[1], 0);
7601      emit_call_insn (gen_call_value_media (operands[0], operands[1],
7602					    operands[2]));
7603      DONE;
7604    }
7605  else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
7606    {
7607      rtx cookie_rtx = operands[3];
7608      long cookie = INTVAL (cookie_rtx);
7609      rtx func = XEXP (operands[1], 0);
7610      rtx r0, r1;
7611
7612      if (flag_pic)
7613	{
7614	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7615	    {
7616	      rtx reg = gen_reg_rtx (Pmode);
7617
7618	      emit_insn (gen_symGOTPLT2reg (reg, func));
7619	      func = reg;
7620	    }
7621	  else
7622	    func = legitimize_pic_address (func, Pmode, 0);
7623	}
7624
7625      r0 = gen_rtx_REG (SImode, R0_REG);
7626      r1 = gen_rtx_REG (SImode, R1_REG);
7627
7628      /* Since such a call function may use all call-clobbered
7629	 registers, we force a mode switch earlier, so that we don't
7630	 run out of registers when adjusting fpscr for the call.  */
7631      emit_insn (gen_force_mode_for_call ());
7632
7633      operands[1]
7634	= function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7635			   SFUNC_GOT);
7636      operands[1] = force_reg (SImode, operands[1]);
7637
7638      emit_move_insn (r0, func);
7639      emit_move_insn (r1, cookie_rtx);
7640
7641      if (cookie & CALL_COOKIE_RET_TRAMP (1))
7642	emit_call_insn (gen_call_value_compact_rettramp (operands[0],
7643							 operands[1],
7644							 operands[2],
7645							 operands[3]));
7646      else
7647	emit_call_insn (gen_call_value_compact (operands[0], operands[1],
7648						operands[2], operands[3]));
7649
7650      DONE;
7651    }
7652  else if (TARGET_SHCOMPACT && flag_pic
7653	   && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7654	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
7655    {
7656      rtx reg = gen_reg_rtx (Pmode);
7657
7658      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
7659      XEXP (operands[1], 0) = reg;
7660    }
7661  if (!flag_pic && TARGET_SH2A
7662      && MEM_P (operands[1])
7663      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7664    {
7665      if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
7666	{
7667	  emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
7668				 XEXP (operands[1], 0), operands[2]));
7669	  DONE;
7670	}
7671    }
7672  if (flag_pic && TARGET_SH2
7673      && MEM_P (operands[1])
7674      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
7675    {
7676      emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
7677					    operands[2]));
7678      DONE;
7679    }
7680  else
7681    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
7682
7683  emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
7684  DONE;
7685}")
7686
7687(define_insn "sibcalli"
7688  [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
7689	 (match_operand 1 "" ""))
7690   (use (reg:PSI FPSCR_REG))
7691   (return)]
7692  "TARGET_SH1"
7693  "jmp	@%0%#"
7694  [(set_attr "needs_delay_slot" "yes")
7695   (set (attr "fp_mode")
7696	(if_then_else (eq_attr "fpu_single" "yes")
7697		      (const_string "single") (const_string "double")))
7698   (set_attr "type" "jump_ind")])
7699
7700(define_insn "sibcalli_pcrel"
7701  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
7702	 (match_operand 1 "" ""))
7703   (use (match_operand 2 "" ""))
7704   (use (reg:PSI FPSCR_REG))
7705   (return)]
7706  "TARGET_SH2"
7707  "braf	%0\\n%O2:%#"
7708  [(set_attr "needs_delay_slot" "yes")
7709   (set (attr "fp_mode")
7710	(if_then_else (eq_attr "fpu_single" "yes")
7711		      (const_string "single") (const_string "double")))
7712   (set_attr "type" "jump_ind")])
7713
7714;; This uses an unspec to describe that the symbol_ref is very close.
7715(define_insn "sibcalli_thunk"
7716  [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
7717			     UNSPEC_THUNK))
7718	 (match_operand 1 "" ""))
7719   (use (reg:PSI FPSCR_REG))
7720   (return)]
7721  "TARGET_SH1"
7722  "bra	%O0"
7723  [(set_attr "needs_delay_slot" "yes")
7724   (set (attr "fp_mode")
7725	(if_then_else (eq_attr "fpu_single" "yes")
7726		      (const_string "single") (const_string "double")))
7727   (set_attr "type" "jump")
7728   (set_attr "length" "2")])
7729
7730(define_insn_and_split "sibcall_pcrel"
7731  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
7732	 (match_operand 1 "" ""))
7733   (use (reg:PSI FPSCR_REG))
7734   (clobber (match_scratch:SI 2 "=k"))
7735   (return)]
7736  "TARGET_SH2"
7737  "#"
7738  "reload_completed"
7739  [(const_int 0)]
7740  "
7741{
7742  rtx lab = PATTERN (gen_call_site ());
7743  rtx call_insn;
7744
7745  emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
7746  call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
7747						  copy_rtx (lab)));
7748  SIBLING_CALL_P (call_insn) = 1;
7749  DONE;
7750}"
7751  [(set_attr "needs_delay_slot" "yes")
7752   (set (attr "fp_mode")
7753	(if_then_else (eq_attr "fpu_single" "yes")
7754		      (const_string "single") (const_string "double")))
7755   (set_attr "type" "jump_ind")])
7756
7757(define_insn "sibcall_compact"
7758  [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
7759	 (match_operand 1 "" ""))
7760   (return)
7761   (use (match_operand:SI 2 "register_operand" "z,x"))
7762   (use (reg:SI R1_REG))
7763   (use (reg:PSI FPSCR_REG))
7764   ;; We want to make sure the `x' above will only match MACH_REG
7765   ;; because sibcall_epilogue may clobber MACL_REG.
7766   (clobber (reg:SI MACL_REG))]
7767  "TARGET_SHCOMPACT"
7768  "@
7769	jmp	@%0%#
7770	jmp	@%0\\n	sts	%2, r0"
7771  [(set_attr "needs_delay_slot" "yes,no")
7772   (set_attr "length" "2,4")
7773   (set (attr "fp_mode") (const_string "single"))
7774   (set_attr "type" "jump_ind")])
7775
7776(define_insn "sibcall_media"
7777  [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
7778	 (match_operand 1 "" ""))
7779   (use (reg:SI PR_MEDIA_REG))
7780   (return)]
7781  "TARGET_SHMEDIA"
7782  "blink	%0, r63"
7783  [(set_attr "type" "jump_media")])
7784
7785(define_expand "sibcall"
7786  [(parallel
7787    [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
7788	   (match_operand 1 "" ""))
7789     (match_operand 2 "" "")
7790     (use (reg:PSI FPSCR_REG))
7791     (return)])]
7792  ""
7793  "
7794{
7795  if (TARGET_SHMEDIA)
7796    {
7797      operands[0] = shmedia_prepare_call_address (operands[0], 1);
7798      emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
7799      DONE;
7800    }
7801  else if (TARGET_SHCOMPACT && operands[2]
7802	   && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
7803    {
7804      rtx cookie_rtx = operands[2];
7805      long cookie = INTVAL (cookie_rtx);
7806      rtx func = XEXP (operands[0], 0);
7807      rtx mach, r1;
7808
7809      if (flag_pic)
7810	{
7811	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
7812	    {
7813	      rtx reg = gen_reg_rtx (Pmode);
7814
7815	      emit_insn (gen_symGOT2reg (reg, func));
7816	      func = reg;
7817	    }
7818	  else
7819	    func = legitimize_pic_address (func, Pmode, 0);
7820	}
7821
7822      /* FIXME: if we could tell whether all argument registers are
7823	 already taken, we could decide whether to force the use of
7824	 MACH_REG or to stick to R0_REG.  Unfortunately, there's no
7825	 simple way to tell.  We could use the CALL_COOKIE, but we
7826	 can't currently tell a register used for regular argument
7827	 passing from one that is unused.  If we leave it up to reload
7828	 to decide which register to use, it seems to always choose
7829	 R0_REG, which leaves no available registers in SIBCALL_REGS
7830	 to hold the address of the trampoline.  */
7831      mach = gen_rtx_REG (SImode, MACH_REG);
7832      r1 = gen_rtx_REG (SImode, R1_REG);
7833
7834      /* Since such a call function may use all call-clobbered
7835	 registers, we force a mode switch earlier, so that we don't
7836	 run out of registers when adjusting fpscr for the call.  */
7837      emit_insn (gen_force_mode_for_call ());
7838
7839      operands[0]
7840	= function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
7841			   SFUNC_GOT);
7842      operands[0] = force_reg (SImode, operands[0]);
7843
7844      /* We don't need a return trampoline, since the callee will
7845	 return directly to the upper caller.  */
7846      if (cookie & CALL_COOKIE_RET_TRAMP (1))
7847	{
7848	  cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
7849	  cookie_rtx = GEN_INT (cookie);
7850	}
7851
7852      emit_move_insn (mach, func);
7853      emit_move_insn (r1, cookie_rtx);
7854
7855      emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
7856      DONE;
7857    }
7858  else if (TARGET_SHCOMPACT && flag_pic
7859	   && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7860	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7861    {
7862      rtx reg = gen_reg_rtx (Pmode);
7863
7864      emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
7865      XEXP (operands[0], 0) = reg;
7866    }
7867  if (flag_pic && TARGET_SH2
7868      && MEM_P (operands[0])
7869      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7870      /* The PLT needs the PIC register, but the epilogue would have
7871	 to restore it, so we can only use PC-relative PIC calls for
7872	 static functions.  */
7873      && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
7874    {
7875      emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
7876      DONE;
7877    }
7878  else
7879    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
7880
7881  emit_call_insn (gen_sibcalli (operands[0], operands[1]));
7882  DONE;
7883}")
7884
7885(define_insn "sibcall_valuei"
7886  [(set (match_operand 0 "" "=rf")
7887	(call (mem:SI (match_operand:SI 1 "register_operand" "k"))
7888	      (match_operand 2 "" "")))
7889   (use (reg:PSI FPSCR_REG))
7890   (return)]
7891  "TARGET_SH1"
7892  "jmp	@%1%#"
7893  [(set_attr "needs_delay_slot" "yes")
7894   (set (attr "fp_mode")
7895	(if_then_else (eq_attr "fpu_single" "yes")
7896		      (const_string "single") (const_string "double")))
7897   (set_attr "type" "jump_ind")])
7898
7899(define_insn "sibcall_valuei_pcrel"
7900  [(set (match_operand 0 "" "=rf")
7901	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
7902	      (match_operand 2 "" "")))
7903   (use (match_operand 3 "" ""))
7904   (use (reg:PSI FPSCR_REG))
7905   (return)]
7906  "TARGET_SH2"
7907  "braf	%1\\n%O3:%#"
7908  [(set_attr "needs_delay_slot" "yes")
7909   (set (attr "fp_mode")
7910	(if_then_else (eq_attr "fpu_single" "yes")
7911		      (const_string "single") (const_string "double")))
7912   (set_attr "type" "jump_ind")])
7913
7914(define_insn_and_split "sibcall_value_pcrel"
7915  [(set (match_operand 0 "" "=rf")
7916	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
7917	      (match_operand 2 "" "")))
7918   (use (reg:PSI FPSCR_REG))
7919   (clobber (match_scratch:SI 3 "=k"))
7920   (return)]
7921  "TARGET_SH2"
7922  "#"
7923  "reload_completed"
7924  [(const_int 0)]
7925  "
7926{
7927  rtx lab = PATTERN (gen_call_site ());
7928  rtx call_insn;
7929
7930  emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
7931  call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
7932							operands[3],
7933							operands[2],
7934							copy_rtx (lab)));
7935  SIBLING_CALL_P (call_insn) = 1;
7936  DONE;
7937}"
7938  [(set_attr "needs_delay_slot" "yes")
7939   (set (attr "fp_mode")
7940	(if_then_else (eq_attr "fpu_single" "yes")
7941		      (const_string "single") (const_string "double")))
7942   (set_attr "type" "jump_ind")])
7943
7944(define_insn "sibcall_value_compact"
7945  [(set (match_operand 0 "" "=rf,rf")
7946	(call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
7947	      (match_operand 2 "" "")))
7948   (return)
7949   (use (match_operand:SI 3 "register_operand" "z,x"))
7950   (use (reg:SI R1_REG))
7951   (use (reg:PSI FPSCR_REG))
7952   ;; We want to make sure the `x' above will only match MACH_REG
7953   ;; because sibcall_epilogue may clobber MACL_REG.
7954   (clobber (reg:SI MACL_REG))]
7955  "TARGET_SHCOMPACT"
7956  "@
7957	jmp	@%1%#
7958	jmp	@%1\\n	sts	%3, r0"
7959  [(set_attr "needs_delay_slot" "yes,no")
7960   (set_attr "length" "2,4")
7961   (set (attr "fp_mode") (const_string "single"))
7962   (set_attr "type" "jump_ind")])
7963
7964(define_insn "sibcall_value_media"
7965  [(set (match_operand 0 "" "=rf")
7966	(call (mem:DI (match_operand 1 "target_reg_operand" "k"))
7967	      (match_operand 2 "" "")))
7968   (use (reg:SI PR_MEDIA_REG))
7969   (return)]
7970  "TARGET_SHMEDIA"
7971  "blink	%1, r63"
7972  [(set_attr "type" "jump_media")])
7973
7974(define_expand "sibcall_value"
7975  [(parallel
7976    [(set (match_operand 0 "arith_reg_operand" "")
7977	  (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
7978	  	(match_operand 2 "" "")))
7979     (match_operand 3 "" "")
7980     (use (reg:PSI FPSCR_REG))
7981     (return)])]
7982  ""
7983  "
7984{
7985  if (TARGET_SHMEDIA)
7986    {
7987      operands[1] = shmedia_prepare_call_address (operands[1], 1);
7988      emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
7989					       operands[2]));
7990      DONE;
7991    }
7992  else if (TARGET_SHCOMPACT && operands[3]
7993	   && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
7994    {
7995      rtx cookie_rtx = operands[3];
7996      long cookie = INTVAL (cookie_rtx);
7997      rtx func = XEXP (operands[1], 0);
7998      rtx mach, r1;
7999
8000      if (flag_pic)
8001	{
8002	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8003	    {
8004	      rtx reg = gen_reg_rtx (Pmode);
8005
8006	      emit_insn (gen_symGOT2reg (reg, func));
8007	      func = reg;
8008	    }
8009	  else
8010	    func = legitimize_pic_address (func, Pmode, 0);
8011	}
8012
8013      /* FIXME: if we could tell whether all argument registers are
8014	 already taken, we could decide whether to force the use of
8015	 MACH_REG or to stick to R0_REG.  Unfortunately, there's no
8016	 simple way to tell.  We could use the CALL_COOKIE, but we
8017	 can't currently tell a register used for regular argument
8018	 passing from one that is unused.  If we leave it up to reload
8019	 to decide which register to use, it seems to always choose
8020	 R0_REG, which leaves no available registers in SIBCALL_REGS
8021	 to hold the address of the trampoline.  */
8022      mach = gen_rtx_REG (SImode, MACH_REG);
8023      r1 = gen_rtx_REG (SImode, R1_REG);
8024
8025      /* Since such a call function may use all call-clobbered
8026	 registers, we force a mode switch earlier, so that we don't
8027	 run out of registers when adjusting fpscr for the call.  */
8028      emit_insn (gen_force_mode_for_call ());
8029
8030      operands[1]
8031	= function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8032			   SFUNC_GOT);
8033      operands[1] = force_reg (SImode, operands[1]);
8034
8035      /* We don't need a return trampoline, since the callee will
8036	 return directly to the upper caller.  */
8037      if (cookie & CALL_COOKIE_RET_TRAMP (1))
8038	{
8039	  cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
8040	  cookie_rtx = GEN_INT (cookie);
8041	}
8042
8043      emit_move_insn (mach, func);
8044      emit_move_insn (r1, cookie_rtx);
8045
8046      emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
8047						 operands[2], mach));
8048      DONE;
8049    }
8050  else if (TARGET_SHCOMPACT && flag_pic
8051	   && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8052	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8053    {
8054      rtx reg = gen_reg_rtx (Pmode);
8055
8056      emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
8057      XEXP (operands[1], 0) = reg;
8058    }
8059  if (flag_pic && TARGET_SH2
8060      && MEM_P (operands[1])
8061      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8062      /* The PLT needs the PIC register, but the epilogue would have
8063	 to restore it, so we can only use PC-relative PIC calls for
8064	 static functions.  */
8065      && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
8066    {
8067      emit_call_insn (gen_sibcall_value_pcrel (operands[0],
8068					       XEXP (operands[1], 0),
8069					       operands[2]));
8070      DONE;
8071    }
8072  else
8073    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
8074
8075  emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
8076  DONE;
8077}")
8078
8079(define_insn "call_value_pop_compact"
8080  [(set (match_operand 0 "" "=rf")
8081	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8082	      (match_operand 2 "" "")))
8083   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8084				 (match_operand 4 "immediate_operand" "n")))
8085   (match_operand 3 "immediate_operand" "n")
8086   (use (reg:SI R0_REG))
8087   (use (reg:SI R1_REG))
8088   (use (reg:PSI FPSCR_REG))
8089   (clobber (reg:SI PR_REG))]
8090  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8091  "jsr	@%1%#"
8092  [(set_attr "type" "call")
8093   (set (attr "fp_mode")
8094	(if_then_else (eq_attr "fpu_single" "yes")
8095		      (const_string "single") (const_string "double")))
8096   (set_attr "needs_delay_slot" "yes")])
8097
8098(define_insn "call_value_pop_compact_rettramp"
8099  [(set (match_operand 0 "" "=rf")
8100	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8101	      (match_operand 2 "" "")))
8102   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8103				 (match_operand 4 "immediate_operand" "n")))
8104   (match_operand 3 "immediate_operand" "n")
8105   (use (reg:SI R0_REG))
8106   (use (reg:SI R1_REG))
8107   (use (reg:PSI FPSCR_REG))
8108   (clobber (reg:SI R10_REG))
8109   (clobber (reg:SI PR_REG))]
8110  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8111  "jsr	@%1%#"
8112  [(set_attr "type" "call")
8113   (set (attr "fp_mode")
8114	(if_then_else (eq_attr "fpu_single" "yes")
8115		      (const_string "single") (const_string "double")))
8116   (set_attr "needs_delay_slot" "yes")])
8117
8118(define_expand "call_value_pop"
8119  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
8120		   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
8121				 (match_operand 2 "" "")))
8122	      (match_operand 3 "" "")
8123	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8124					    (match_operand 4 "" "")))])]
8125  "TARGET_SHCOMPACT"
8126  "
8127{
8128  rtx cookie_rtx;
8129  long cookie;
8130  rtx func;
8131  rtx r0, r1;
8132
8133  gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
8134  cookie_rtx = operands[3];
8135  cookie = INTVAL (cookie_rtx);
8136  func = XEXP (operands[1], 0);
8137
8138  if (flag_pic)
8139    {
8140      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8141        {
8142          rtx reg = gen_reg_rtx (Pmode);
8143
8144	  emit_insn (gen_symGOTPLT2reg (reg, func));
8145          func = reg;
8146        }
8147      else
8148        func = legitimize_pic_address (func, Pmode, 0);
8149    }
8150
8151  r0 = gen_rtx_REG (SImode, R0_REG);
8152  r1 = gen_rtx_REG (SImode, R1_REG);
8153
8154  /* Since such a call function may use all call-clobbered
8155     registers, we force a mode switch earlier, so that we don't
8156     run out of registers when adjusting fpscr for the call.  */
8157  emit_insn (gen_force_mode_for_call ());
8158
8159  operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
8160				 SFUNC_GOT);
8161  operands[1] = force_reg (SImode, operands[1]);
8162
8163  emit_move_insn (r0, func);
8164  emit_move_insn (r1, cookie_rtx);
8165
8166  if (cookie & CALL_COOKIE_RET_TRAMP (1))
8167    emit_call_insn (gen_call_value_pop_compact_rettramp
8168			(operands[0], operands[1], operands[2],
8169			 operands[3], operands[4]));
8170  else
8171    emit_call_insn (gen_call_value_pop_compact
8172			(operands[0], operands[1], operands[2],
8173			 operands[3], operands[4]));
8174
8175  DONE;
8176}")
8177
8178(define_expand "sibcall_epilogue"
8179  [(return)]
8180  ""
8181  "
8182{
8183  sh_expand_epilogue (1);
8184  if (TARGET_SHCOMPACT)
8185    {
8186      rtx insn, set;
8187
8188      /* If epilogue clobbers r0, preserve it in macl.  */
8189      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
8190	if ((set = single_set (insn))
8191	    && REG_P (SET_DEST (set))
8192	    && REGNO (SET_DEST (set)) == R0_REG)
8193	  {
8194	    rtx r0 = gen_rtx_REG (SImode, R0_REG);
8195	    rtx tmp = gen_rtx_REG (SImode, MACL_REG);
8196
8197	    /* We can't tell at this point whether the sibcall is a
8198	       sibcall_compact and, if it is, whether it uses r0 or
8199	       mach as operand 2, so let the instructions that
8200	       preserve r0 be optimized away if r0 turns out to be
8201	       dead.  */
8202	    emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
8203	    emit_move_insn (r0, tmp);
8204	    break;
8205	  }
8206    }
8207  DONE;
8208}")
8209
8210(define_insn "indirect_jump_compact"
8211  [(set (pc)
8212	(match_operand:SI 0 "arith_reg_operand" "r"))]
8213  "TARGET_SH1"
8214  "jmp	@%0%#"
8215  [(set_attr "needs_delay_slot" "yes")
8216   (set_attr "type" "jump_ind")])
8217
8218(define_expand "indirect_jump"
8219  [(set (pc)
8220	(match_operand 0 "register_operand" ""))]
8221  ""
8222  "
8223{
8224  if (GET_MODE (operands[0]) != Pmode)
8225    operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
8226}")
8227
8228;; The use of operand 1 / 2 helps us distinguish case table jumps
8229;; which can be present in structured code from indirect jumps which can not
8230;; be present in structured code.  This allows -fprofile-arcs to work.
8231
8232;; For SH1 processors.
8233(define_insn "casesi_jump_1"
8234  [(set (pc)
8235	(match_operand:SI 0 "register_operand" "r"))
8236   (use (label_ref (match_operand 1 "" "")))]
8237  "TARGET_SH1"
8238  "jmp  @%0%#"
8239  [(set_attr "needs_delay_slot" "yes")
8240   (set_attr "type" "jump_ind")])
8241
8242;; For all later processors.
8243(define_insn "casesi_jump_2"
8244  [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
8245		      (label_ref (match_operand 1 "" ""))))
8246   (use (label_ref (match_operand 2 "" "")))]
8247  "TARGET_SH2
8248   && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
8249  "braf	%0%#"
8250  [(set_attr "needs_delay_slot" "yes")
8251   (set_attr "type" "jump_ind")])
8252
8253(define_insn "casesi_jump_media"
8254  [(set (pc) (match_operand 0 "target_reg_operand" "b"))
8255   (use (label_ref (match_operand 1 "" "")))]
8256  "TARGET_SHMEDIA"
8257  "blink	%0, r63"
8258  [(set_attr "type" "jump_media")])
8259
8260;; Call subroutine returning any type.
8261;; ??? This probably doesn't work.
8262
8263(define_expand "untyped_call"
8264  [(parallel [(call (match_operand 0 "" "")
8265		    (const_int 0))
8266	      (match_operand 1 "" "")
8267	      (match_operand 2 "" "")])]
8268  "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
8269  "
8270{
8271  int i;
8272
8273  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
8274
8275  for (i = 0; i < XVECLEN (operands[2], 0); i++)
8276    {
8277      rtx set = XVECEXP (operands[2], 0, i);
8278      emit_move_insn (SET_DEST (set), SET_SRC (set));
8279    }
8280
8281  /* The optimizer does not know that the call sets the function value
8282     registers we stored in the result block.  We avoid problems by
8283     claiming that all hard registers are used and clobbered at this
8284     point.  */
8285  emit_insn (gen_blockage ());
8286
8287  DONE;
8288}")
8289
8290;; ------------------------------------------------------------------------
8291;; Misc insns
8292;; ------------------------------------------------------------------------
8293
8294(define_insn "dect"
8295  [(set (reg:SI T_REG)
8296	(eq:SI (match_operand:SI 0 "arith_reg_dest" "+r") (const_int 1)))
8297   (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
8298  "TARGET_SH2"
8299  "dt	%0"
8300  [(set_attr "type" "arith")])
8301
8302(define_insn "nop"
8303  [(const_int 0)]
8304  ""
8305  "nop")
8306
8307;; Load address of a label. This is only generated by the casesi expand,
8308;; and by machine_dependent_reorg (fixing up fp moves).
8309;; This must use unspec, because this only works for labels that are
8310;; within range,
8311
8312(define_insn "mova"
8313  [(set (reg:SI R0_REG)
8314	(unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
8315  "TARGET_SH1"
8316  "mova	%O0,r0"
8317  [(set_attr "in_delay_slot" "no")
8318   (set_attr "type" "arith")])
8319
8320;; machine_dependent_reorg will make this a `mova'.
8321(define_insn "mova_const"
8322  [(set (reg:SI R0_REG)
8323	(unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
8324  "TARGET_SH1"
8325  "#"
8326  [(set_attr "in_delay_slot" "no")
8327   (set_attr "type" "arith")])
8328
8329(define_expand "GOTaddr2picreg"
8330  [(set (reg:SI R0_REG)
8331	(unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
8332		   UNSPEC_MOVA))
8333   (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
8334   (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8335  "" "
8336{
8337  if (TARGET_VXWORKS_RTP)
8338    {
8339      rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
8340      rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
8341      emit_insn (gen_vxworks_picreg (gott_base, gott_index));
8342      DONE;
8343    }
8344
8345  operands[0] = gen_rtx_REG (Pmode, PIC_REG);
8346  operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
8347
8348  if (TARGET_SHMEDIA)
8349    {
8350      rtx tr = gen_rtx_REG (Pmode, TR0_REG);
8351      rtx pic = operands[0];
8352      rtx lab = PATTERN (gen_call_site ());
8353      rtx insn, equiv;
8354
8355      equiv = operands[1];
8356      operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
8357				    UNSPEC_PCREL_SYMOFF);
8358      operands[1] = gen_rtx_CONST (Pmode, operands[1]);
8359
8360      if (Pmode == SImode)
8361	{
8362	  emit_insn (gen_movsi_const (pic, operands[1]));
8363	  emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
8364	}
8365      else
8366	{
8367	  emit_insn (gen_movdi_const (pic, operands[1]));
8368	  emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
8369	}
8370
8371      insn = emit_move_insn (operands[0], tr);
8372
8373      set_unique_reg_note (insn, REG_EQUAL, equiv);
8374
8375      DONE;
8376    }
8377}
8378")
8379
8380;; A helper for GOTaddr2picreg to finish up the initialization of the
8381;; PIC register.
8382
8383(define_expand "vxworks_picreg"
8384  [(set (reg:SI PIC_REG)
8385	(const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
8386   (set (reg:SI R0_REG)
8387	(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
8388   (set (reg:SI PIC_REG)
8389	(mem:SI (reg:SI PIC_REG)))
8390   (set (reg:SI PIC_REG)
8391	(mem:SI (plus:SI (reg:SI PIC_REG)
8392			 (reg:SI R0_REG))))]
8393  "TARGET_VXWORKS_RTP")
8394
8395(define_insn "*ptb"
8396  [(set (match_operand 0 "target_reg_operand" "=b")
8397	(const (unspec [(match_operand 1 "" "Csy")]
8398			     UNSPEC_DATALABEL)))]
8399  "TARGET_SHMEDIA && flag_pic
8400   && satisfies_constraint_Csy (operands[1])"
8401  "ptb/u	datalabel %1, %0"
8402  [(set_attr "type" "ptabs_media")
8403   (set_attr "length" "*")])
8404
8405(define_insn "ptrel_si"
8406  [(set (match_operand:SI 0 "target_reg_operand" "=b")
8407	(plus:SI (match_operand:SI 1 "register_operand" "r")
8408	      (pc)))
8409   (match_operand:SI 2 "" "")]
8410  "TARGET_SHMEDIA"
8411  "%O2: ptrel/u	%1, %0"
8412  [(set_attr "type" "ptabs_media")])
8413
8414(define_insn "ptrel_di"
8415  [(set (match_operand:DI 0 "target_reg_operand" "=b")
8416	(plus:DI (match_operand:DI 1 "register_operand" "r")
8417	      (pc)))
8418   (match_operand:DI 2 "" "")]
8419  "TARGET_SHMEDIA"
8420  "%O2: ptrel/u	%1, %0"
8421  [(set_attr "type" "ptabs_media")])
8422
8423(define_expand "builtin_setjmp_receiver"
8424  [(match_operand 0 "" "")]
8425  "flag_pic"
8426  "
8427{
8428  emit_insn (gen_GOTaddr2picreg ());
8429  DONE;
8430}")
8431
8432(define_expand "call_site"
8433  [(unspec [(match_dup 0)] UNSPEC_CALLER)]
8434  "TARGET_SH1"
8435  "
8436{
8437  static HOST_WIDE_INT i = 0;
8438  operands[0] = GEN_INT (i);
8439  i++;
8440}")
8441
8442;; op0 = op1 + r12 but hide it before reload completed.  See the comment
8443;; in symGOT_load expand.
8444
8445(define_insn_and_split "chk_guard_add"
8446  [(set (match_operand:SI 0 "register_operand" "=&r")
8447	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
8448		    (reg:SI PIC_REG)]
8449		   UNSPEC_CHKADD))]
8450  "TARGET_SH1"
8451  "#"
8452  "TARGET_SH1 && reload_completed"
8453  [(set (match_dup 0) (reg:SI PIC_REG))
8454   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8455  ""
8456  [(set_attr "type" "arith")])
8457
8458(define_expand "sym_label2reg"
8459  [(set (match_operand:SI 0 "" "")
8460	(const:SI (unspec:SI [(match_operand:SI 1 "" "")
8461			      (const (plus:SI (match_operand:SI 2 "" "")
8462					      (const_int 2)))]
8463			     UNSPEC_SYMOFF)))]
8464  "TARGET_SH1" "")
8465
8466(define_expand "symGOT_load"
8467  [(set (match_dup 2) (match_operand 1 "" ""))
8468   (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
8469   (set (match_operand 0 "" "") (mem (match_dup 3)))]
8470  ""
8471  "
8472{
8473  rtx insn, mem;
8474
8475  operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8476  operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
8477
8478  if (TARGET_SHMEDIA)
8479    {
8480      rtx reg = operands[2];
8481
8482      if (Pmode == DImode)
8483	{      
8484	  if (flag_pic > 1)
8485	    emit_insn (gen_movdi_const_32bit (reg, operands[1]));
8486	  else
8487	    emit_insn (gen_movdi_const_16bit (reg, operands[1]));
8488	}
8489      else
8490	{
8491	  if (flag_pic > 1)
8492	    emit_insn (gen_movsi_const (reg, operands[1]));
8493	  else
8494	    emit_insn (gen_movsi_const_16bit (reg, operands[1]));
8495	}
8496    }
8497  else
8498    emit_move_insn (operands[2], operands[1]);
8499
8500  /* When stack protector inserts codes after the result is set to
8501     R0, @(rX, r12) will cause a spill failure for R0.  Use a unspec
8502     insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
8503     when rX is a GOT address for the guard symbol.  Ugly but doesn't
8504     matter because this is a rare situation.  */
8505  if (!TARGET_SHMEDIA
8506      && flag_stack_protect
8507      && GET_CODE (operands[1]) == CONST
8508      && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
8509      && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
8510      && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
8511		 \"__stack_chk_guard\") == 0)
8512    emit_insn (gen_chk_guard_add (operands[3], operands[2]));
8513  else
8514    emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
8515					       gen_rtx_REG (Pmode, PIC_REG)));
8516
8517  /* N.B. This is not constant for a GOTPLT relocation.  */
8518  mem = gen_rtx_MEM (Pmode, operands[3]);
8519  MEM_NOTRAP_P (mem) = 1;
8520  /* ??? Should we have a special alias set for the GOT?  */
8521  insn = emit_move_insn (operands[0], mem);
8522
8523  DONE;
8524}")
8525
8526(define_expand "sym2GOT"
8527  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
8528  ""
8529  "")
8530
8531(define_expand "symGOT2reg"
8532  [(match_operand 0 "" "") (match_operand 1 "" "")]
8533  ""
8534  "
8535{
8536  rtx gotsym, insn;
8537
8538  gotsym = gen_sym2GOT (operands[1]);
8539  PUT_MODE (gotsym, Pmode);
8540  insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
8541
8542  MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
8543
8544  DONE;
8545}")
8546
8547(define_expand "symGOTPLT2reg"
8548  [(match_operand 0 "" "") (match_operand 1 "" "")]
8549  ""
8550  "
8551{
8552  rtx pltsym = gen_rtx_CONST (Pmode,
8553			      gen_rtx_UNSPEC (Pmode,
8554					      gen_rtvec (1, operands[1]),
8555					      UNSPEC_GOTPLT));
8556  emit_insn (gen_symGOT_load (operands[0], pltsym));
8557  DONE;
8558}")
8559
8560(define_expand "sym2GOTOFF"
8561  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
8562  ""
8563  "")
8564
8565(define_expand "symGOTOFF2reg"
8566  [(match_operand 0 "" "") (match_operand 1 "" "")]
8567  ""
8568  "
8569{
8570  rtx gotoffsym, insn;
8571  rtx t = (!can_create_pseudo_p ()
8572	   ? operands[0]
8573	   : gen_reg_rtx (GET_MODE (operands[0])));
8574
8575  gotoffsym = gen_sym2GOTOFF (operands[1]);
8576  PUT_MODE (gotoffsym, Pmode);
8577  emit_move_insn (t, gotoffsym);
8578  insn = emit_move_insn (operands[0],
8579			 gen_rtx_PLUS (Pmode, t,
8580				       gen_rtx_REG (Pmode, PIC_REG)));
8581
8582  set_unique_reg_note (insn, REG_EQUAL, operands[1]);
8583
8584  DONE;
8585}")
8586
8587(define_expand "symPLT_label2reg"
8588  [(set (match_operand:SI 0 "" "")
8589	(const:SI
8590	 (unspec:SI
8591	  [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
8592	   (const:SI (plus:SI (match_operand:SI 2 "" "")
8593			      (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
8594   ;; Even though the PIC register is not really used by the call
8595   ;; sequence in which this is expanded, the PLT code assumes the PIC
8596   ;; register is set, so we must not skip its initialization.  Since
8597   ;; we only use this expand as part of calling sequences, and never
8598   ;; to take the address of a function, this is the best point to
8599   ;; insert the (use).  Using the PLT to take the address of a
8600   ;; function would be wrong, not only because the PLT entry could
8601   ;; then be called from a function that doesn't initialize the PIC
8602   ;; register to the proper GOT, but also because pointers to the
8603   ;; same function might not compare equal, should they be set by
8604   ;; different shared libraries.
8605   (use (reg:SI PIC_REG))]
8606  "TARGET_SH1"
8607  "")
8608
8609(define_expand "sym2PIC"
8610  [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
8611  ""
8612  "")
8613
8614;; TLS code generation.
8615;; ??? this should be a define_insn_and_split
8616;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
8617;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
8618;; for details.
8619
8620(define_insn "tls_global_dynamic"
8621  [(set (match_operand:SI 0 "register_operand" "=&z")
8622	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8623				  UNSPEC_TLSGD))
8624	      (const_int 0)))
8625   (use (reg:PSI FPSCR_REG))
8626   (use (reg:SI PIC_REG))
8627   (clobber (reg:SI PR_REG))
8628   (clobber (scratch:SI))]
8629  "TARGET_SH1"
8630  "*
8631{
8632  return \"\\
8633mov.l\\t1f,r4\\n\\
8634\\tmova\\t2f,r0\\n\\
8635\\tmov.l\\t2f,r1\\n\\
8636\\tadd\\tr0,r1\\n\\
8637\\tjsr\\t@r1\\n\\
8638\\tadd\\tr12,r4\\n\\
8639\\tbra\\t3f\\n\\
8640\\tnop\\n\\
8641\\t.align\\t2\\n\\
86421:\\t.long\\t%a1@TLSGD\\n\\
86432:\\t.long\\t__tls_get_addr@PLT\\n\\
86443:\";
8645}"
8646  [(set_attr "type" "tls_load")
8647   (set_attr "length" "26")])
8648
8649(define_insn "tls_local_dynamic"
8650  [(set (match_operand:SI 0 "register_operand" "=&z")
8651	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
8652				  UNSPEC_TLSLDM))
8653	      (const_int 0)))
8654   (use (reg:PSI FPSCR_REG))
8655   (use (reg:SI PIC_REG))
8656   (clobber (reg:SI PR_REG))
8657   (clobber (scratch:SI))]
8658  "TARGET_SH1"
8659  "*
8660{
8661  return \"\\
8662mov.l\\t1f,r4\\n\\
8663\\tmova\\t2f,r0\\n\\
8664\\tmov.l\\t2f,r1\\n\\
8665\\tadd\\tr0,r1\\n\\
8666\\tjsr\\t@r1\\n\\
8667\\tadd\\tr12,r4\\n\\
8668\\tbra\\t3f\\n\\
8669\\tnop\\n\\
8670\\t.align\\t2\\n\\
86711:\\t.long\\t%a1@TLSLDM\\n\\
86722:\\t.long\\t__tls_get_addr@PLT\\n\\
86733:\";
8674}"
8675  [(set_attr "type" "tls_load")
8676   (set_attr "length" "26")])
8677
8678(define_expand "sym2DTPOFF"
8679  [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
8680  ""
8681  "")
8682
8683(define_expand "symDTPOFF2reg"
8684  [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
8685  ""
8686  "
8687{
8688  rtx dtpoffsym, insn;
8689  rtx t = (!can_create_pseudo_p ()
8690	   ? operands[0]
8691	   : gen_reg_rtx (GET_MODE (operands[0])));
8692
8693  dtpoffsym = gen_sym2DTPOFF (operands[1]);
8694  PUT_MODE (dtpoffsym, Pmode);
8695  emit_move_insn (t, dtpoffsym);
8696  insn = emit_move_insn (operands[0],
8697			 gen_rtx_PLUS (Pmode, t, operands[2]));
8698  DONE;
8699}")
8700
8701(define_expand "sym2GOTTPOFF"
8702  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
8703  ""
8704  "")
8705
8706(define_insn "tls_initial_exec"
8707  [(set (match_operand:SI 0 "register_operand" "=&r")
8708	(unspec:SI [(match_operand:SI 1 "" "")]
8709		    UNSPEC_TLSIE))
8710   (use (reg:SI GBR_REG))
8711   (use (reg:SI PIC_REG))
8712   (clobber (reg:SI R0_REG))]
8713  ""
8714  "*
8715{
8716  return \"\\
8717mov.l\\t1f,r0\\n\\
8718\\tstc\\tgbr,%0\\n\\
8719\\tmov.l\\t@(r0,r12),r0\\n\\
8720\\tbra\\t2f\\n\\
8721\\tadd\\tr0,%0\\n\\
8722\\t.align\\t2\\n\\
87231:\\t.long\\t%a1\\n\\
87242:\";
8725}"
8726  [(set_attr "type" "tls_load")
8727   (set_attr "length" "16")])
8728
8729(define_expand "sym2TPOFF"
8730  [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
8731  ""
8732  "")
8733
8734(define_expand "symTPOFF2reg"
8735  [(match_operand 0 "" "") (match_operand 1 "" "")]
8736  ""
8737  "
8738{
8739  rtx tpoffsym, insn;
8740
8741  tpoffsym = gen_sym2TPOFF (operands[1]);
8742  PUT_MODE (tpoffsym, Pmode);
8743  insn = emit_move_insn (operands[0], tpoffsym);
8744  DONE;
8745}")
8746
8747(define_insn "load_gbr"
8748  [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))
8749   (use (reg:SI GBR_REG))]
8750  ""
8751  "stc	gbr,%0"
8752  [(set_attr "type" "tls_load")])
8753
8754;; case instruction for switch statements.
8755
8756;; Operand 0 is index
8757;; operand 1 is the minimum bound
8758;; operand 2 is the maximum bound - minimum bound + 1
8759;; operand 3 is CODE_LABEL for the table;
8760;; operand 4 is the CODE_LABEL to go to if index out of range.
8761
8762(define_expand "casesi"
8763  [(match_operand:SI 0 "arith_reg_operand" "")
8764   (match_operand:SI 1 "arith_reg_operand" "")
8765   (match_operand:SI 2 "arith_reg_operand" "")
8766   (match_operand 3 "" "") (match_operand 4 "" "")]
8767  ""
8768  "
8769{
8770  rtx reg = gen_reg_rtx (SImode);
8771  rtx reg2 = gen_reg_rtx (SImode);
8772  if (TARGET_SHMEDIA)
8773    {
8774      rtx reg = gen_reg_rtx (DImode);
8775      rtx reg2 = gen_reg_rtx (DImode);
8776      rtx reg3 = gen_reg_rtx (Pmode);
8777      rtx reg4 = gen_reg_rtx (Pmode);
8778      rtx reg5 = gen_reg_rtx (Pmode);
8779      rtx load, test;
8780
8781      operands[0] = convert_modes (DImode, SImode, operands[0], 0);
8782      operands[1] = convert_modes (DImode, SImode, operands[1], 0);
8783      operands[2] = convert_modes (DImode, SImode, operands[2], 1);
8784
8785      test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
8786      emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4]));
8787      emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
8788      test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
8789      emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
8790      emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
8791      emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
8792					       (Pmode, operands[3])));
8793      /* Messy: can we subreg to clean this up? */
8794      if (Pmode == DImode)
8795	load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
8796      else
8797	load = gen_casesi_load_media (reg4,
8798				      gen_rtx_SUBREG (DImode, reg3, 0),
8799				      reg2, operands[3]);
8800      PUT_MODE (SET_SRC (load), Pmode);
8801      emit_insn (load);
8802      /* ??? The following add could be eliminated if we used ptrel.  */
8803      emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
8804      emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
8805      emit_barrier ();
8806      DONE;
8807    }
8808  operands[1] = copy_to_mode_reg (SImode, operands[1]);
8809  operands[2] = copy_to_mode_reg (SImode, operands[2]);
8810  /* If optimizing, casesi_worker depends on the mode of the instruction
8811     before label it 'uses' - operands[3].  */
8812  emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
8813			   reg));
8814  emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
8815  if (TARGET_SH2)
8816    emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
8817  else
8818    emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
8819  /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
8820     operands[3], but to lab.  We will fix this up in
8821     machine_dependent_reorg.  */
8822  emit_barrier ();
8823  DONE;
8824}")
8825
8826(define_expand "casesi_0"
8827  [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
8828   (set (match_dup 4) (minus:SI (match_dup 4)
8829				(match_operand:SI 1 "arith_operand" "")))
8830   (set (reg:SI T_REG)
8831	(gtu:SI (match_dup 4)
8832		(match_operand:SI 2 "arith_reg_operand" "")))
8833   (set (pc)
8834	(if_then_else (ne (reg:SI T_REG)
8835			  (const_int 0))
8836		      (label_ref (match_operand 3 "" ""))
8837		      (pc)))]
8838  "TARGET_SH1"
8839  "")
8840
8841;; ??? reload might clobber r0 if we use it explicitly in the RTL before
8842;; reload; using a R0_REGS pseudo reg is likely to give poor code.
8843;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
8844
8845(define_insn "casesi_worker_0"
8846  [(set (match_operand:SI 0 "register_operand" "=r,r")
8847	(unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
8848		 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8849   (clobber (match_scratch:SI 3 "=X,1"))
8850   (clobber (match_scratch:SI 4 "=&z,z"))]
8851  "TARGET_SH1"
8852  "#")
8853
8854(define_split
8855  [(set (match_operand:SI 0 "register_operand" "")
8856	(unspec:SI [(match_operand:SI 1 "register_operand" "")
8857		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8858   (clobber (match_scratch:SI 3 ""))
8859   (clobber (match_scratch:SI 4 ""))]
8860  "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
8861  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8862   (parallel [(set (match_dup 0)
8863	      (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8864			  (label_ref (match_dup 2))] UNSPEC_CASESI))
8865	      (clobber (match_dup 3))])
8866   (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
8867  "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8868
8869(define_split
8870  [(set (match_operand:SI 0 "register_operand" "")
8871	(unspec:SI [(match_operand:SI 1 "register_operand" "")
8872		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8873   (clobber (match_scratch:SI 3 ""))
8874   (clobber (match_scratch:SI 4 ""))]
8875  "TARGET_SH2 && reload_completed"
8876  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
8877   (parallel [(set (match_dup 0)
8878	      (unspec:SI [(reg:SI R0_REG) (match_dup 1)
8879			  (label_ref (match_dup 2))] UNSPEC_CASESI))
8880	      (clobber (match_dup 3))])]
8881  "if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
8882
8883(define_insn "casesi_worker_1"
8884  [(set (match_operand:SI 0 "register_operand" "=r,r")
8885	(unspec:SI [(reg:SI R0_REG)
8886		    (match_operand:SI 1 "register_operand" "0,r")
8887		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
8888   (clobber (match_scratch:SI 3 "=X,1"))]
8889  "TARGET_SH1"
8890  "*
8891{
8892  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8893
8894  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8895
8896  switch (GET_MODE (diff_vec))
8897    {
8898    case SImode:
8899      return \"shll2	%1\;mov.l	@(r0,%1),%0\";
8900    case HImode:
8901      return \"add	%1,%1\;mov.w	@(r0,%1),%0\";
8902    case QImode:
8903      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8904	return \"mov.b	@(r0,%1),%0\;extu.b	%0,%0\";
8905      return \"mov.b	@(r0,%1),%0\";
8906    default:
8907      gcc_unreachable ();
8908    }
8909}"
8910  [(set_attr "length" "4")])
8911
8912(define_insn "casesi_worker_2"
8913  [(set (match_operand:SI 0 "register_operand" "=r,r")
8914	(unspec:SI [(reg:SI R0_REG)
8915		    (match_operand:SI 1 "register_operand" "0,r")
8916		    (label_ref (match_operand 2 "" ""))
8917		    (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
8918   (clobber (match_operand:SI 4 "" "=X,1"))]
8919  "TARGET_SH2 && reload_completed && flag_pic"
8920  "*
8921{
8922  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8923  const char *load;
8924
8925  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8926
8927  switch (GET_MODE (diff_vec))
8928    {
8929    case SImode:
8930      output_asm_insn (\"shll2    %1\", operands);
8931      load = \"mov.l	@(r0,%1),%0\"; break;
8932    case HImode:
8933      output_asm_insn (\"add	%1,%1\", operands);
8934      load = \"mov.w	@(r0,%1),%0\"; break;
8935    case QImode:
8936      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8937	load = \"mov.b	@(r0,%1),%0\;extu.b	%0,%0\";
8938      else
8939	load = \"mov.b	@(r0,%1),%0\";
8940      break;
8941    default:
8942      gcc_unreachable ();
8943    }
8944  output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
8945  return load;
8946}"
8947  [(set_attr "length" "8")])
8948
8949(define_insn "casesi_shift_media"
8950  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
8951	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
8952		   (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
8953		    UNSPEC_CASESI)))]
8954  "TARGET_SHMEDIA"
8955  "*
8956{
8957  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
8958
8959  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8960
8961  switch (GET_MODE (diff_vec))
8962    {
8963    case SImode:
8964      return \"shlli	%1, 2, %0\";
8965    case HImode:
8966      return \"shlli	%1, 1, %0\";
8967    case QImode:
8968      if (rtx_equal_p (operands[0], operands[1]))
8969	return \"\";
8970      return \"add	%1, r63, %0\";
8971    default:
8972      gcc_unreachable ();
8973    }
8974}"
8975  [(set_attr "type" "arith_media")])
8976
8977(define_insn "casesi_load_media"
8978  [(set (match_operand 0 "any_arith_reg_dest" "=r")
8979	(mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
8980			 (match_operand:DI 2 "arith_reg_operand" "r")
8981			 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
8982  "TARGET_SHMEDIA"
8983  "*
8984{
8985  rtx diff_vec = PATTERN (next_real_insn (operands[3]));
8986
8987  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
8988
8989  switch (GET_MODE (diff_vec))
8990    {
8991    case SImode:
8992      return \"ldx.l	%1, %2, %0\";
8993    case HImode:
8994#if 0
8995      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
8996	return \"ldx.uw	%1, %2, %0\";
8997#endif
8998      return \"ldx.w	%1, %2, %0\";
8999    case QImode:
9000      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
9001	return \"ldx.ub	%1, %2, %0\";
9002      return \"ldx.b	%1, %2, %0\";
9003    default:
9004      gcc_unreachable ();
9005    }
9006}"
9007  [(set_attr "type" "load_media")])
9008
9009(define_expand "return"
9010  [(return)]
9011  "reload_completed && ! sh_need_epilogue ()"
9012  "
9013{
9014  if (TARGET_SHMEDIA)
9015    {
9016      emit_jump_insn (gen_return_media ());
9017      DONE;
9018    }
9019
9020  if (TARGET_SHCOMPACT
9021      && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
9022    {
9023      emit_jump_insn (gen_shcompact_return_tramp ());
9024      DONE;
9025    }
9026}")
9027
9028(define_insn "*return_i"
9029  [(return)]
9030  "TARGET_SH1 && ! (TARGET_SHCOMPACT
9031		    && (crtl->args.info.call_cookie
9032			& CALL_COOKIE_RET_TRAMP (1)))
9033   && reload_completed
9034   && lookup_attribute (\"trap_exit\",
9035			DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
9036  "*
9037  {
9038    if (TARGET_SH2A && (dbr_sequence_length () == 0)
9039			&& !current_function_interrupt)
9040       return \"rts/n\";
9041    else
9042       return \"%@	%#\";
9043  }"
9044  [(set_attr "type" "return")
9045   (set_attr "needs_delay_slot" "yes")])
9046
9047;; trapa has no delay slot.
9048(define_insn "*return_trapa"
9049  [(return)]
9050  "TARGET_SH1 && !TARGET_SHCOMPACT
9051   && reload_completed"
9052  "%@"
9053  [(set_attr "type" "return")])
9054
9055(define_expand "shcompact_return_tramp"
9056  [(return)]
9057  "TARGET_SHCOMPACT
9058   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9059  "
9060{
9061  rtx reg = gen_rtx_REG (Pmode, R0_REG);
9062
9063  function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC);
9064  emit_jump_insn (gen_shcompact_return_tramp_i ());
9065  DONE;
9066}")
9067
9068(define_insn "shcompact_return_tramp_i"
9069  [(parallel [(return) (use (reg:SI R0_REG))])]
9070  "TARGET_SHCOMPACT
9071   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
9072  "jmp	@r0%#"
9073  [(set_attr "type" "jump_ind")
9074   (set_attr "needs_delay_slot" "yes")])
9075
9076(define_insn "return_media_i"
9077  [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
9078  "TARGET_SHMEDIA && reload_completed"
9079  "blink	%0, r63"
9080  [(set_attr "type" "jump_media")])
9081
9082(define_insn "return_media_rte"
9083  [(return)]
9084  "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
9085  "rte"
9086  [(set_attr "type" "jump_media")])
9087
9088(define_expand "return_media"
9089  [(return)]
9090  "TARGET_SHMEDIA && reload_completed"
9091  "
9092{
9093  int tr_regno = sh_media_register_for_return ();
9094  rtx tr;
9095
9096  if (current_function_interrupt)
9097    {
9098      emit_jump_insn (gen_return_media_rte ());
9099      DONE;
9100    }
9101  if (tr_regno < 0)
9102    {
9103      rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
9104
9105      gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
9106      tr_regno = TR0_REG;
9107      tr = gen_rtx_REG (Pmode, tr_regno);
9108      emit_move_insn (tr, r18);
9109    }
9110  else
9111    tr = gen_rtx_REG (Pmode, tr_regno);
9112
9113  emit_jump_insn (gen_return_media_i (tr));
9114  DONE;
9115}")
9116
9117(define_insn "shcompact_preserve_incoming_args"
9118  [(set (match_operand:SI 0 "register_operand" "+r")
9119	(unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
9120  "TARGET_SHCOMPACT"
9121  ""
9122  [(set_attr "length" "0")])
9123
9124(define_insn "shcompact_incoming_args"
9125  [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
9126   (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
9127   (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
9128   (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
9129   (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
9130   (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
9131   (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
9132   (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
9133   (set (mem:BLK (reg:SI MACL_REG))
9134	(unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
9135   (use (reg:SI R0_REG))
9136   (clobber (reg:SI R0_REG))
9137   (clobber (reg:SI MACL_REG))
9138   (clobber (reg:SI MACH_REG))
9139   (clobber (reg:SI PR_REG))]
9140  "TARGET_SHCOMPACT"
9141  "jsr	@r0%#"
9142  [(set_attr "needs_delay_slot" "yes")])
9143
9144(define_insn "shmedia_save_restore_regs_compact"
9145  [(set (reg:SI SP_REG)
9146	(plus:SI (reg:SI SP_REG)
9147		 (match_operand:SI 0 "immediate_operand" "i")))
9148   (use (reg:SI R0_REG))
9149   (clobber (reg:SI PR_REG))]
9150  "TARGET_SHCOMPACT
9151   && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
9152       || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
9153  "jsr @r0%#"
9154  [(set_attr "needs_delay_slot" "yes")])
9155
9156(define_expand "prologue"
9157  [(const_int 0)]
9158  ""
9159  "sh_expand_prologue (); DONE;")
9160
9161(define_expand "epilogue"
9162  [(return)]
9163  ""
9164  "
9165{
9166  sh_expand_epilogue (0);
9167  emit_jump_insn (gen_return ());
9168  DONE;
9169}")
9170
9171(define_expand "eh_return"
9172  [(use (match_operand 0 "register_operand" ""))]
9173  ""
9174{
9175  rtx ra = operands[0];
9176
9177  if (TARGET_SHMEDIA64)
9178    emit_insn (gen_eh_set_ra_di (ra));
9179  else
9180    emit_insn (gen_eh_set_ra_si (ra));
9181
9182  DONE;
9183})
9184
9185;; Clobber the return address on the stack.  We can't expand this
9186;; until we know where it will be put in the stack frame.
9187
9188(define_insn "eh_set_ra_si"
9189  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
9190      UNSPECV_EH_RETURN)
9191   (clobber (match_scratch:SI 1 "=&r"))]
9192  "! TARGET_SHMEDIA64"
9193  "#")
9194
9195(define_insn "eh_set_ra_di"
9196  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
9197      UNSPECV_EH_RETURN)
9198   (clobber (match_scratch:DI 1 "=&r"))]
9199  "TARGET_SHMEDIA64"
9200  "#")
9201
9202(define_split
9203  [(unspec_volatile [(match_operand 0 "register_operand" "")]
9204      UNSPECV_EH_RETURN)
9205   (clobber (match_scratch 1 ""))]
9206  "reload_completed"
9207  [(const_int 0)]
9208  "
9209{
9210  sh_set_return_address (operands[0], operands[1]);
9211  DONE;
9212}")
9213
9214(define_insn "blockage"
9215  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
9216  ""
9217  ""
9218  [(set_attr "length" "0")])
9219
9220;; ------------------------------------------------------------------------
9221;; Scc instructions
9222;; ------------------------------------------------------------------------
9223
9224(define_insn "movt"
9225  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9226	(eq:SI (reg:SI T_REG) (const_int 1)))]
9227  "TARGET_SH1"
9228  "movt	%0"
9229  [(set_attr "type" "arith")])
9230
9231(define_expand "cstore4_media"
9232  [(set (match_operand:SI 0 "register_operand" "=r")
9233	(match_operator:SI 1 "sh_float_comparison_operator"
9234	 [(match_operand 2 "logical_operand" "")
9235	  (match_operand 3 "cmp_operand" "")]))]
9236  "TARGET_SHMEDIA"
9237  "
9238{
9239  enum machine_mode mode = GET_MODE (operands[2]);
9240  enum rtx_code code = GET_CODE (operands[1]);
9241  bool invert, swap;
9242  if (mode == VOIDmode)
9243    mode = GET_MODE (operands[3]);
9244  if (operands[2] == const0_rtx)
9245    {
9246      if (code == EQ || code == NE)
9247	operands[2] = operands[3], operands[3] = const0_rtx;
9248    }
9249  else
9250    operands[2] = force_reg (mode, operands[2]);
9251  if (operands[3] != const0_rtx)
9252    operands[3] = force_reg (mode, operands[3]);
9253
9254  switch (code)
9255    {
9256    case GEU:
9257    case GE:
9258      swap = invert = !FLOAT_MODE_P (mode);
9259      break;
9260
9261    case LEU:
9262    case LE:
9263      swap = FLOAT_MODE_P (mode), invert = !swap;
9264      break;
9265
9266    case LTU:
9267    case LT:
9268      swap = true, invert = false;
9269      break;
9270
9271    case GTU:
9272    case GT:
9273    case EQ:
9274    case UNORDERED:
9275      swap = invert = false;
9276      break;
9277
9278    case NE:
9279      swap = invert = true;
9280      break;
9281
9282    default:
9283      gcc_unreachable ();
9284  }
9285
9286  if (swap)
9287    {
9288      rtx tem = operands[2];
9289      operands[2] = operands[3];
9290      operands[3] = tem;
9291      code = swap_condition (code);
9292    }
9293
9294  if (invert)
9295    {
9296      rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
9297      code = reverse_condition (code);
9298      operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9299      emit_insn (gen_cstore4_media (tem, operands[1],
9300				    operands[2], operands[3]));
9301      code = EQ;
9302      operands[2] = tem;
9303      operands[3] = const0_rtx;
9304    }
9305
9306  operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
9307}")
9308
9309(define_expand "cstoresi4"
9310  [(set (match_operand:SI 0 "register_operand" "=r")
9311	(match_operator:SI 1 "comparison_operator"
9312	 [(match_operand:SI 2 "cmpsi_operand" "")
9313	  (match_operand:SI 3 "arith_operand" "")]))]
9314  "TARGET_SH1 || TARGET_SHMEDIA"
9315  "if (TARGET_SHMEDIA)
9316    {
9317      emit_insn (gen_cstore4_media (operands[0], operands[1],
9318				    operands[2], operands[3]));
9319      DONE;
9320    }
9321
9322   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9323       && sh_expand_t_scc (operands))
9324     DONE;
9325
9326   if (! currently_expanding_to_rtl)
9327     FAIL;
9328   
9329   sh_emit_compare_and_set (operands, SImode);
9330   DONE;
9331")
9332
9333(define_expand "cstoredi4"
9334  [(set (match_operand:SI 0 "register_operand" "=r")
9335	(match_operator:SI 1 "comparison_operator"
9336	 [(match_operand:DI 2 "arith_operand" "")
9337	  (match_operand:DI 3 "arith_operand" "")]))]
9338  "TARGET_SH2 || TARGET_SHMEDIA"
9339  "if (TARGET_SHMEDIA)
9340    {
9341      emit_insn (gen_cstore4_media (operands[0], operands[1],
9342				    operands[2], operands[3]));
9343      DONE;
9344    }
9345
9346   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9347       && sh_expand_t_scc (operands))
9348     DONE;
9349
9350   if (! currently_expanding_to_rtl)
9351     FAIL;
9352   
9353   sh_emit_compare_and_set (operands, DImode);
9354   DONE;
9355")
9356
9357
9358
9359;; sne moves the complement of the T reg to DEST like this:
9360;;      cmp/eq ...
9361;;      mov    #-1,temp
9362;;      negc   temp,dest
9363;;   This is better than xoring compare result with 1 because it does
9364;;   not require r0 and further, the -1 may be CSE-ed or lifted out of a
9365;;   loop.
9366
9367(define_expand "movnegt"
9368  [(set (match_dup 1) (const_int -1))
9369   (parallel [(set (match_operand:SI 0 "" "")
9370		   (neg:SI (plus:SI (reg:SI T_REG)
9371				    (match_dup 1))))
9372	      (set (reg:SI T_REG)
9373		   (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
9374			  (const_int 0)))])]
9375  ""
9376  "
9377{
9378  operands[1] = gen_reg_rtx (SImode);
9379}")
9380
9381
9382;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
9383;; This prevents a regression that occurred when we switched from xor to
9384;; mov/neg for sne.
9385
9386(define_split
9387  [(set (match_operand:SI 0 "arith_reg_dest" "")
9388	(plus:SI (reg:SI T_REG)
9389		 (const_int -1)))]
9390  "TARGET_SH1"
9391  [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
9392   (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
9393  "")
9394
9395(define_expand "cstoresf4"
9396  [(set (match_operand:SI 0 "register_operand" "=r")
9397	(match_operator:SI 1 "sh_float_comparison_operator"
9398	 [(match_operand:SF 2 "arith_operand" "")
9399	  (match_operand:SF 3 "arith_operand" "")]))]
9400  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9401  "if (TARGET_SHMEDIA)
9402     {
9403       emit_insn (gen_cstore4_media (operands[0], operands[1],
9404				     operands[2], operands[3]));
9405       DONE;
9406     }
9407
9408   if (! currently_expanding_to_rtl)
9409     FAIL;
9410   
9411   sh_emit_compare_and_set (operands, SFmode);
9412   DONE;
9413")
9414
9415(define_expand "cstoredf4"
9416  [(set (match_operand:SI 0 "register_operand" "=r")
9417	(match_operator:SI 1 "sh_float_comparison_operator"
9418	 [(match_operand:DF 2 "arith_operand" "")
9419	  (match_operand:DF 3 "arith_operand" "")]))]
9420  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
9421  "if (TARGET_SHMEDIA)
9422     {
9423       emit_insn (gen_cstore4_media (operands[0], operands[1],
9424				     operands[2], operands[3]));
9425       DONE;
9426     }
9427
9428    if (! currently_expanding_to_rtl)
9429      FAIL;
9430   
9431   sh_emit_compare_and_set (operands, DFmode);
9432   DONE;
9433")
9434
9435
9436;; -------------------------------------------------------------------------
9437;; Instructions to cope with inline literal tables
9438;; -------------------------------------------------------------------------
9439
9440; 2 byte integer in line
9441
9442(define_insn "consttable_2"
9443 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9444		    (match_operand 1 "" "")]
9445		   UNSPECV_CONST2)]
9446 ""
9447 "*
9448{
9449  if (operands[1] != const0_rtx)
9450    assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
9451  return \"\";
9452}"
9453 [(set_attr "length" "2")
9454 (set_attr "in_delay_slot" "no")])
9455
9456; 4 byte integer in line
9457
9458(define_insn "consttable_4"
9459 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9460		    (match_operand 1 "" "")]
9461		   UNSPECV_CONST4)]
9462 ""
9463 "*
9464{
9465  if (operands[1] != const0_rtx)
9466    {
9467      assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
9468      mark_symbol_refs_as_used (operands[0]);
9469    }
9470  return \"\";
9471}"
9472 [(set_attr "length" "4")
9473  (set_attr "in_delay_slot" "no")])
9474
9475; 8 byte integer in line
9476
9477(define_insn "consttable_8"
9478 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
9479		    (match_operand 1 "" "")]
9480		   UNSPECV_CONST8)]
9481 ""
9482 "*
9483{
9484  if (operands[1] != const0_rtx)
9485    assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
9486  return \"\";
9487}"
9488 [(set_attr "length" "8")
9489  (set_attr "in_delay_slot" "no")])
9490
9491; 4 byte floating point
9492
9493(define_insn "consttable_sf"
9494 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
9495		    (match_operand 1 "" "")]
9496		   UNSPECV_CONST4)]
9497 ""
9498 "*
9499{
9500  if (operands[1] != const0_rtx)
9501    {
9502      REAL_VALUE_TYPE d;
9503      REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9504      assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
9505    }
9506  return \"\";
9507}"
9508 [(set_attr "length" "4")
9509  (set_attr "in_delay_slot" "no")])
9510
9511; 8 byte floating point
9512
9513(define_insn "consttable_df"
9514 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
9515		    (match_operand 1 "" "")]
9516		   UNSPECV_CONST8)]
9517 ""
9518 "*
9519{
9520  if (operands[1] != const0_rtx)
9521    {
9522      REAL_VALUE_TYPE d;
9523      REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
9524      assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
9525    }
9526  return \"\";
9527}"
9528 [(set_attr "length" "8")
9529  (set_attr "in_delay_slot" "no")])
9530
9531;; Alignment is needed for some constant tables; it may also be added for
9532;; Instructions at the start of loops, or after unconditional branches.
9533;; ??? We would get more accurate lengths if we did instruction
9534;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
9535;; here is too conservative.
9536
9537; align to a two byte boundary
9538
9539(define_expand "align_2"
9540 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
9541 ""
9542 "")
9543
9544; align to a four byte boundary
9545;; align_4 and align_log are instructions for the starts of loops, or
9546;; after unconditional branches, which may take up extra room.
9547
9548(define_expand "align_4"
9549 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
9550 ""
9551 "")
9552
9553; align to a cache line boundary
9554
9555(define_insn "align_log"
9556 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
9557 ""
9558 ""
9559 [(set_attr "length" "0")
9560  (set_attr "in_delay_slot" "no")])
9561
9562; emitted at the end of the literal table, used to emit the
9563; 32bit branch labels if needed.
9564
9565(define_insn "consttable_end"
9566  [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
9567  ""
9568  "* return output_jump_label_table ();"
9569  [(set_attr "in_delay_slot" "no")])
9570
9571; emitted at the end of the window in the literal table.
9572
9573(define_insn "consttable_window_end"
9574  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
9575  ""
9576  ""
9577  [(set_attr "length" "0")
9578   (set_attr "in_delay_slot" "no")])
9579
9580;; -------------------------------------------------------------------------
9581;; Misc
9582;; -------------------------------------------------------------------------
9583
9584;; String/block move insn.
9585
9586(define_expand "movmemsi"
9587  [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
9588		   (mem:BLK (match_operand:BLK 1 "" "")))
9589	      (use (match_operand:SI 2 "nonmemory_operand" ""))
9590	      (use (match_operand:SI 3 "immediate_operand" ""))
9591	      (clobber (reg:SI PR_REG))
9592	      (clobber (reg:SI R4_REG))
9593	      (clobber (reg:SI R5_REG))
9594	      (clobber (reg:SI R0_REG))])]
9595  "TARGET_SH1 && ! TARGET_SH5"
9596  "
9597{
9598  if(expand_block_move (operands))
9599     DONE;
9600  else FAIL;
9601}")
9602
9603(define_insn "block_move_real"
9604  [(parallel [(set (mem:BLK (reg:SI R4_REG))
9605		   (mem:BLK (reg:SI R5_REG)))
9606	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
9607	      (clobber (reg:SI PR_REG))
9608	      (clobber (reg:SI R0_REG))])]
9609  "TARGET_SH1 && ! TARGET_HARD_SH4"
9610  "jsr	@%0%#"
9611  [(set_attr "type" "sfunc")
9612   (set_attr "needs_delay_slot" "yes")])
9613
9614(define_insn "block_lump_real"
9615  [(parallel [(set (mem:BLK (reg:SI R4_REG))
9616		   (mem:BLK (reg:SI R5_REG)))
9617	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
9618	      (use (reg:SI R6_REG))
9619	      (clobber (reg:SI PR_REG))
9620	      (clobber (reg:SI T_REG))
9621	      (clobber (reg:SI R4_REG))
9622	      (clobber (reg:SI R5_REG))
9623	      (clobber (reg:SI R6_REG))
9624	      (clobber (reg:SI R0_REG))])]
9625  "TARGET_SH1 && ! TARGET_HARD_SH4"
9626  "jsr	@%0%#"
9627  [(set_attr "type" "sfunc")
9628   (set_attr "needs_delay_slot" "yes")])
9629
9630(define_insn "block_move_real_i4"
9631  [(parallel [(set (mem:BLK (reg:SI R4_REG))
9632		   (mem:BLK (reg:SI R5_REG)))
9633	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
9634	      (clobber (reg:SI PR_REG))
9635	      (clobber (reg:SI R0_REG))
9636	      (clobber (reg:SI R1_REG))
9637	      (clobber (reg:SI R2_REG))])]
9638  "TARGET_HARD_SH4"
9639  "jsr	@%0%#"
9640  [(set_attr "type" "sfunc")
9641   (set_attr "needs_delay_slot" "yes")])
9642
9643(define_insn "block_lump_real_i4"
9644  [(parallel [(set (mem:BLK (reg:SI R4_REG))
9645		   (mem:BLK (reg:SI R5_REG)))
9646	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
9647	      (use (reg:SI R6_REG))
9648	      (clobber (reg:SI PR_REG))
9649	      (clobber (reg:SI T_REG))
9650	      (clobber (reg:SI R4_REG))
9651	      (clobber (reg:SI R5_REG))
9652	      (clobber (reg:SI R6_REG))
9653	      (clobber (reg:SI R0_REG))
9654	      (clobber (reg:SI R1_REG))
9655	      (clobber (reg:SI R2_REG))
9656	      (clobber (reg:SI R3_REG))])]
9657  "TARGET_HARD_SH4"
9658  "jsr	@%0%#"
9659  [(set_attr "type" "sfunc")
9660   (set_attr "needs_delay_slot" "yes")])
9661
9662;; -------------------------------------------------------------------------
9663;; Floating point instructions.
9664;; -------------------------------------------------------------------------
9665
9666;; ??? All patterns should have a type attribute.
9667
9668(define_expand "movpsi"
9669  [(set (match_operand:PSI 0 "register_operand" "")
9670	(match_operand:PSI 1 "general_movsrc_operand" ""))]
9671  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9672  "")
9673
9674;; The c / m alternative is a fake to guide reload to load directly into
9675;; fpscr, since reload doesn't know how to use post-increment.
9676;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
9677;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
9678;; predicate after reload.
9679;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
9680;; like a mac -> gpr move.
9681(define_insn "fpu_switch"
9682  [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
9683	(match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
9684  "TARGET_SH2E
9685   && (! reload_completed
9686       || true_regnum (operands[0]) != FPSCR_REG
9687       || !MEM_P (operands[1])
9688       || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
9689  "@
9690	! precision stays the same
9691	lds.l	%1,fpscr
9692	mov.l	%1,%0
9693	#
9694	lds	%1,fpscr
9695	mov	%1,%0
9696	mov.l	%1,%0
9697	sts	fpscr,%0
9698	sts.l	fpscr,%0"
9699  [(set_attr "length" "0,2,2,4,2,2,2,2,2")
9700   (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
9701
9702(define_peephole2
9703  [(set (reg:PSI FPSCR_REG)
9704	(mem:PSI (match_operand:SI 0 "register_operand" "")))]
9705  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
9706  [(const_int 0)]
9707{
9708  rtx fpscr, mem, new_insn;
9709
9710  fpscr = SET_DEST (PATTERN (curr_insn));
9711  mem = SET_SRC (PATTERN (curr_insn));
9712  mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9713
9714  new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9715  add_reg_note (new_insn, REG_INC, operands[0]);
9716  DONE;
9717})
9718
9719(define_split
9720  [(set (reg:PSI FPSCR_REG)
9721	(mem:PSI (match_operand:SI 0 "register_operand" "")))]
9722  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
9723   && (flag_peephole2 ? epilogue_completed : reload_completed)"
9724  [(const_int 0)]
9725{
9726  rtx fpscr, mem, new_insn;
9727
9728  fpscr = SET_DEST (PATTERN (curr_insn));
9729  mem = SET_SRC (PATTERN (curr_insn));
9730  mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
9731
9732  new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
9733  add_reg_note (new_insn, REG_INC, operands[0]);
9734
9735  if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
9736    emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
9737  DONE;
9738})
9739
9740;; ??? This uses the fp unit, but has no type indicating that.
9741;; If we did that, this would either give a bogus latency or introduce
9742;; a bogus FIFO constraint.
9743;; Since this insn is currently only used for prologues/epilogues,
9744;; it is probably best to claim no function unit, which matches the
9745;; current setting.
9746(define_insn "toggle_sz"
9747  [(set (reg:PSI FPSCR_REG)
9748	(xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
9749  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
9750  "fschg"
9751  [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
9752
9753;; There's no way we can use it today, since optimize mode switching
9754;; doesn't enable us to know from which mode we're switching to the
9755;; mode it requests, to tell whether we can use a relative mode switch
9756;; (like toggle_pr) or an absolute switch (like loading fpscr from
9757;; memory).
9758(define_insn "toggle_pr"
9759  [(set (reg:PSI FPSCR_REG)
9760	(xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
9761  "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
9762  "fpchg"
9763  [(set_attr "type" "fpscr_toggle")])
9764
9765(define_expand "addsf3"
9766  [(set (match_operand:SF 0 "arith_reg_operand" "")
9767	(plus:SF (match_operand:SF 1 "arith_reg_operand" "")
9768		 (match_operand:SF 2 "arith_reg_operand" "")))]
9769  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9770  "
9771{
9772  if (TARGET_SH2E)
9773    {
9774      expand_sf_binop (&gen_addsf3_i, operands);
9775      DONE;
9776    }
9777}")
9778
9779(define_insn "*addsf3_media"
9780  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9781	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
9782		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
9783  "TARGET_SHMEDIA_FPU"
9784  "fadd.s	%1, %2, %0"
9785  [(set_attr "type" "fparith_media")])
9786
9787(define_insn_and_split "unary_sf_op"
9788  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
9789	(vec_select:V2SF
9790	 (vec_concat:V2SF
9791	  (vec_select:SF
9792	   (match_dup 0)
9793	   (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
9794	  (match_operator:SF 2 "unary_float_operator"
9795	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
9796			    (parallel [(match_operand 4
9797					"const_int_operand" "n")]))]))
9798	 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
9799  "TARGET_SHMEDIA_FPU"
9800  "#"
9801  "TARGET_SHMEDIA_FPU && reload_completed"
9802  [(set (match_dup 5) (match_dup 6))]
9803  "
9804{
9805  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
9806  rtx op1 = gen_rtx_REG (SFmode,
9807			 (true_regnum (operands[1])
9808			  + (INTVAL (operands[4]) ^ endian)));
9809
9810  operands[7] = gen_rtx_REG (SFmode,
9811			     (true_regnum (operands[0])
9812			      + (INTVAL (operands[3]) ^ endian)));
9813  operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
9814}"
9815  [(set_attr "type" "fparith_media")])
9816
9817(define_insn_and_split "binary_sf_op0"
9818  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
9819	(vec_concat:V2SF
9820	  (match_operator:SF 3 "binary_float_operator"
9821	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
9822			    (parallel [(const_int 0)]))
9823	     (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
9824			    (parallel [(const_int 0)]))])
9825	  (vec_select:SF
9826	   (match_dup 0)
9827	   (parallel [(const_int 1)]))))]
9828  "TARGET_SHMEDIA_FPU"
9829  "#"
9830  "&& reload_completed"
9831  [(set (match_dup 4) (match_dup 5))]
9832  "
9833{
9834  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
9835  rtx op1 = gen_rtx_REG (SFmode,
9836			 true_regnum (operands[1]) + endian);
9837  rtx op2 = gen_rtx_REG (SFmode,
9838			 true_regnum (operands[2]) + endian);
9839
9840  operands[4] = gen_rtx_REG (SFmode,
9841			     true_regnum (operands[0]) + endian);
9842  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
9843}"
9844  [(set_attr "type" "fparith_media")])
9845
9846(define_insn_and_split "binary_sf_op1"
9847  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
9848	(vec_concat:V2SF
9849	  (vec_select:SF
9850	   (match_dup 0)
9851	   (parallel [(const_int 0)]))
9852	  (match_operator:SF 3 "binary_float_operator"
9853	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
9854			    (parallel [(const_int 1)]))
9855	     (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
9856			    (parallel [(const_int 1)]))])))]
9857  "TARGET_SHMEDIA_FPU"
9858  "#"
9859  "&& reload_completed"
9860  [(set (match_dup 4) (match_dup 5))]
9861  "
9862{
9863  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
9864  rtx op1 = gen_rtx_REG (SFmode,
9865			 true_regnum (operands[1]) + (1 ^ endian));
9866  rtx op2 = gen_rtx_REG (SFmode,
9867			 true_regnum (operands[2]) + (1 ^ endian));
9868
9869  operands[4] = gen_rtx_REG (SFmode,
9870			     true_regnum (operands[0]) + (1 ^ endian));
9871  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
9872}"
9873  [(set_attr "type" "fparith_media")])
9874
9875(define_insn "addsf3_i"
9876  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9877	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
9878		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
9879   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
9880  "TARGET_SH2E"
9881  "fadd	%2,%0"
9882  [(set_attr "type" "fp")
9883   (set_attr "fp_mode" "single")])
9884
9885(define_expand "subsf3"
9886  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
9887	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
9888		  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
9889  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9890  "
9891{
9892  if (TARGET_SH2E)
9893    {
9894      expand_sf_binop (&gen_subsf3_i, operands);
9895      DONE;
9896    }
9897}")
9898
9899(define_insn "*subsf3_media"
9900  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9901	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
9902		  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
9903  "TARGET_SHMEDIA_FPU"
9904  "fsub.s	%1, %2, %0"
9905  [(set_attr "type" "fparith_media")])
9906
9907(define_insn "subsf3_i"
9908  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9909	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
9910		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
9911   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
9912  "TARGET_SH2E"
9913  "fsub	%2,%0"
9914  [(set_attr "type" "fp")
9915   (set_attr "fp_mode" "single")])
9916
9917(define_expand "mulsf3"
9918  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
9919	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
9920		 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
9921  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9922  "")
9923
9924(define_insn "*mulsf3_media"
9925  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9926	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
9927		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
9928  "TARGET_SHMEDIA_FPU"
9929  "fmul.s	%1, %2, %0"
9930  [(set_attr "type" "fparith_media")])
9931
9932;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
9933;; register in feeding fp instructions.  Thus, in order to generate fmac,
9934;; we start out with a mulsf pattern that does not depend on fpscr.
9935;; This is split after combine to introduce the dependency, in order to
9936;; get mode switching and scheduling right.
9937(define_insn_and_split "mulsf3_ie"
9938  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9939	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
9940		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
9941  "TARGET_SH2E"
9942  "fmul	%2,%0"
9943  "TARGET_SH4 || TARGET_SH2A_SINGLE"
9944  [(const_int 0)]
9945  "
9946{
9947  emit_insn (gen_mulsf3_i4 (operands[0], operands[1], operands[2],
9948	     get_fpscr_rtx ()));
9949  DONE;
9950}"
9951  [(set_attr "type" "fp")])
9952
9953(define_insn "mulsf3_i4"
9954  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9955	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
9956		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
9957   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
9958  "TARGET_SH2E"
9959  "fmul	%2,%0"
9960  [(set_attr "type" "fp")
9961   (set_attr "fp_mode" "single")])
9962
9963(define_insn "mac_media"
9964  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9965	(plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
9966			  (match_operand:SF 2 "fp_arith_reg_operand" "f"))
9967		 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
9968  "TARGET_SHMEDIA_FPU && TARGET_FMAC"
9969  "fmac.s %1, %2, %0"
9970  [(set_attr "type" "fparith_media")])
9971
9972(define_insn "*macsf3"
9973  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9974	(plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
9975			  (match_operand:SF 2 "fp_arith_reg_operand" "f"))
9976		 (match_operand:SF 3 "arith_reg_operand" "0")))
9977   (use (match_operand:PSI 4 "fpscr_operand" "c"))]
9978  "TARGET_SH2E && TARGET_FMAC"
9979  "fmac	fr0,%2,%0"
9980  [(set_attr "type" "fp")
9981   (set_attr "fp_mode" "single")])
9982
9983(define_expand "divsf3"
9984  [(set (match_operand:SF 0 "arith_reg_operand" "")
9985	(div:SF (match_operand:SF 1 "arith_reg_operand" "")
9986		(match_operand:SF 2 "arith_reg_operand" "")))]
9987  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
9988  "
9989{
9990  if (TARGET_SH2E)
9991    {
9992      expand_sf_binop (&gen_divsf3_i, operands);
9993      DONE;
9994    }
9995}")
9996
9997(define_insn "*divsf3_media"
9998  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
9999	(div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
10000		(match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10001  "TARGET_SHMEDIA_FPU"
10002  "fdiv.s	%1, %2, %0"
10003  [(set_attr "type" "fdiv_media")])
10004
10005(define_insn "divsf3_i"
10006  [(set (match_operand:SF 0 "arith_reg_dest" "=f")
10007	(div:SF (match_operand:SF 1 "arith_reg_operand" "0")
10008		 (match_operand:SF 2 "arith_reg_operand" "f")))
10009   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10010  "TARGET_SH2E"
10011  "fdiv	%2,%0"
10012  [(set_attr "type" "fdiv")
10013   (set_attr "fp_mode" "single")])
10014
10015(define_insn "floatdisf2"
10016  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10017	(float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10018  "TARGET_SHMEDIA_FPU"
10019  "float.qs %1, %0"
10020  [(set_attr "type" "fpconv_media")])
10021
10022(define_expand "floatsisf2"
10023  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10024	(float:SF (match_operand:SI 1 "fpul_operand" "")))]
10025  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10026  "
10027{
10028  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10029    {
10030      emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10031      DONE;
10032    }
10033}")
10034
10035(define_insn "*floatsisf2_media"
10036  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10037	(float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10038  "TARGET_SHMEDIA_FPU"
10039  "float.ls	%1, %0"
10040  [(set_attr "type" "fpconv_media")])
10041
10042(define_insn "floatsisf2_i4"
10043  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10044	(float:SF (match_operand:SI 1 "fpul_operand" "y")))
10045   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10046  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10047  "float	%1,%0"
10048  [(set_attr "type" "fp")
10049   (set_attr "fp_mode" "single")])
10050
10051(define_insn "*floatsisf2_ie"
10052  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10053	(float:SF (match_operand:SI 1 "fpul_operand" "y")))]
10054  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10055  "float	%1,%0"
10056  [(set_attr "type" "fp")])
10057
10058(define_insn "fix_truncsfdi2"
10059  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10060	(fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10061  "TARGET_SHMEDIA_FPU"
10062  "ftrc.sq %1, %0"
10063  [(set_attr "type" "fpconv_media")])
10064
10065(define_expand "fix_truncsfsi2"
10066  [(set (match_operand:SI 0 "fpul_operand" "=y")
10067	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10068  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10069  "
10070{
10071  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
10072    {
10073      emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
10074      DONE;
10075    }
10076}")
10077
10078(define_insn "*fix_truncsfsi2_media"
10079  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10080	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10081  "TARGET_SHMEDIA_FPU"
10082  "ftrc.sl	%1, %0"
10083  [(set_attr "type" "fpconv_media")])
10084
10085(define_insn "fix_truncsfsi2_i4"
10086  [(set (match_operand:SI 0 "fpul_operand" "=y")
10087	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10088   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10089  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10090  "ftrc	%1,%0"
10091  [(set_attr "type" "ftrc_s")
10092   (set_attr "fp_mode" "single")])
10093
10094;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
10095;; fix_truncsfsi2_i4.
10096;; (define_insn "fix_truncsfsi2_i4_2"
10097;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10098;;	(fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10099;;   (use (reg:PSI FPSCR_REG))
10100;;   (clobber (reg:SI FPUL_REG))]
10101;;  "TARGET_SH4"
10102;;  "#"
10103;;  [(set_attr "length" "4")
10104;;   (set_attr "fp_mode" "single")])
10105
10106;;(define_split
10107;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10108;;	(fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
10109;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
10110;;   (clobber (reg:SI FPUL_REG))]
10111;;  "TARGET_SH4"
10112;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10113;;	      (use (match_dup 2))])
10114;;   (set (match_dup 0) (reg:SI FPUL_REG))])
10115
10116(define_insn "*fixsfsi"
10117  [(set (match_operand:SI 0 "fpul_operand" "=y")
10118	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10119  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10120  "ftrc	%1,%0"
10121  [(set_attr "type" "fp")])
10122
10123(define_insn "cmpgtsf_t"
10124  [(set (reg:SI T_REG)
10125	(gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10126	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10127  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10128  "fcmp/gt	%1,%0"
10129  [(set_attr "type" "fp_cmp")
10130   (set_attr "fp_mode" "single")])
10131
10132(define_insn "cmpeqsf_t"
10133  [(set (reg:SI T_REG)
10134	(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10135	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10136  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10137  "fcmp/eq	%1,%0"
10138  [(set_attr "type" "fp_cmp")
10139   (set_attr "fp_mode" "single")])
10140
10141(define_insn "ieee_ccmpeqsf_t"
10142  [(set (reg:SI T_REG)
10143	(ior:SI (reg:SI T_REG)
10144		(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10145		       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
10146  "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10147  "* return output_ieee_ccmpeq (insn, operands);"
10148  [(set_attr "length" "4")])
10149
10150
10151(define_insn "cmpgtsf_t_i4"
10152  [(set (reg:SI T_REG)
10153	(gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10154	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10155   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10156  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10157  "fcmp/gt	%1,%0"
10158  [(set_attr "type" "fp_cmp")
10159   (set_attr "fp_mode" "single")])
10160
10161(define_insn "cmpeqsf_t_i4"
10162  [(set (reg:SI T_REG)
10163	(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10164	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
10165   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10166  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
10167  "fcmp/eq	%1,%0"
10168  [(set_attr "type" "fp_cmp")
10169   (set_attr "fp_mode" "single")])
10170
10171(define_insn "*ieee_ccmpeqsf_t_4"
10172  [(set (reg:SI T_REG)
10173	(ior:SI (reg:SI T_REG)
10174		(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
10175		       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
10176   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10177  "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
10178  "* return output_ieee_ccmpeq (insn, operands);"
10179  [(set_attr "length" "4")
10180   (set_attr "fp_mode" "single")])
10181
10182(define_insn "cmpeqsf_media"
10183  [(set (match_operand:SI 0 "register_operand" "=r")
10184	(eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10185	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10186  "TARGET_SHMEDIA_FPU"
10187  "fcmpeq.s	%1, %2, %0"
10188  [(set_attr "type" "fcmp_media")])
10189
10190(define_insn "cmpgtsf_media"
10191  [(set (match_operand:SI 0 "register_operand" "=r")
10192	(gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10193	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10194  "TARGET_SHMEDIA_FPU"
10195  "fcmpgt.s	%1, %2, %0"
10196  [(set_attr "type" "fcmp_media")])
10197
10198(define_insn "cmpgesf_media"
10199  [(set (match_operand:SI 0 "register_operand" "=r")
10200	(ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10201	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10202  "TARGET_SHMEDIA_FPU"
10203  "fcmpge.s	%1, %2, %0"
10204  [(set_attr "type" "fcmp_media")])
10205
10206(define_insn "cmpunsf_media"
10207  [(set (match_operand:SI 0 "register_operand" "=r")
10208	(unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
10209		      (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
10210  "TARGET_SHMEDIA_FPU"
10211  "fcmpun.s	%1, %2, %0"
10212  [(set_attr "type" "fcmp_media")])
10213
10214(define_expand "cbranchsf4"
10215  [(set (pc)
10216	(if_then_else (match_operator 0 "sh_float_comparison_operator"
10217		       [(match_operand:SF 1 "arith_operand" "")
10218			(match_operand:SF 2 "arith_operand" "")])
10219		      (match_operand 3 "" "")
10220		      (pc)))]
10221  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10222  "
10223{
10224  if (TARGET_SHMEDIA)
10225    emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
10226					  operands[3]));
10227  else
10228    sh_emit_compare_and_branch (operands, SFmode);
10229  DONE;
10230}")
10231
10232(define_expand "negsf2"
10233  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10234	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10235  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10236  "
10237{
10238  if (TARGET_SH2E)
10239    {
10240      expand_sf_unop (&gen_negsf2_i, operands);
10241      DONE;
10242    }
10243}")
10244
10245(define_insn "*negsf2_media"
10246  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10247	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10248  "TARGET_SHMEDIA_FPU"
10249  "fneg.s	%1, %0"
10250  [(set_attr "type" "fmove_media")])
10251
10252(define_insn "negsf2_i"
10253  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10254	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10255   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10256  "TARGET_SH2E"
10257  "fneg	%0"
10258  [(set_attr "type" "fmove")
10259   (set_attr "fp_mode" "single")])
10260
10261(define_expand "sqrtsf2"
10262  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10263	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10264  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
10265  "
10266{
10267  if (TARGET_SH3E)
10268    {
10269      expand_sf_unop (&gen_sqrtsf2_i, operands);
10270      DONE;
10271    }
10272}")
10273
10274(define_insn "*sqrtsf2_media"
10275  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10276	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10277  "TARGET_SHMEDIA_FPU"
10278  "fsqrt.s	%1, %0"
10279  [(set_attr "type" "fdiv_media")])
10280
10281(define_insn "sqrtsf2_i"
10282  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10283	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10284   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10285  "TARGET_SH3E"
10286  "fsqrt	%0"
10287  [(set_attr "type" "fdiv")
10288   (set_attr "fp_mode" "single")])
10289
10290(define_insn "rsqrtsf2"
10291  [(set (match_operand:SF 0 "register_operand" "=f")
10292	(div:SF (match_operand:SF 1 "immediate_operand" "i")
10293		(sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
10294   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10295  "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10296   && operands[1] == CONST1_RTX (SFmode)"
10297  "fsrra	%0"
10298  [(set_attr "type" "fsrra")
10299   (set_attr "fp_mode" "single")])
10300
10301(define_insn "fsca"
10302  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
10303	(vec_concat:V2SF
10304	 (unspec:SF [(mult:SF
10305		      (float:SF (match_operand:SI 1 "fpul_operand" "y"))
10306		      (match_operand:SF 2 "immediate_operand" "i"))
10307		    ] UNSPEC_FSINA)
10308	 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
10309		    ] UNSPEC_FCOSA)))
10310   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10311  "TARGET_SH4A_FP && flag_unsafe_math_optimizations
10312   && operands[2] == sh_fsca_int2sf ()"
10313  "fsca	fpul,%d0"
10314  [(set_attr "type" "fsca")
10315   (set_attr "fp_mode" "single")])
10316
10317(define_expand "sinsf2"
10318  [(set (match_operand:SF 0 "nonimmediate_operand" "")
10319	(unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10320		   UNSPEC_FSINA))]
10321  "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10322  "
10323{
10324  rtx scaled = gen_reg_rtx (SFmode);
10325  rtx truncated = gen_reg_rtx (SImode);
10326  rtx fsca = gen_reg_rtx (V2SFmode);
10327  rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10328
10329  emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10330  emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10331  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10332			  get_fpscr_rtx ()));
10333  emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
10334  DONE;
10335}")
10336
10337(define_expand "cossf2"
10338  [(set (match_operand:SF 0 "nonimmediate_operand" "")
10339	(unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "")]
10340		   UNSPEC_FCOSA))]
10341  "TARGET_SH4A_FP && flag_unsafe_math_optimizations"
10342  "
10343{
10344  rtx scaled = gen_reg_rtx (SFmode);
10345  rtx truncated = gen_reg_rtx (SImode);
10346  rtx fsca = gen_reg_rtx (V2SFmode);
10347  rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
10348
10349  emit_sf_insn (gen_mulsf3 (scaled, operands[1], scale_reg));
10350  emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
10351  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10352			  get_fpscr_rtx ()));
10353  emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
10354  DONE;
10355}")
10356
10357(define_expand "sindf2"
10358  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10359	(unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10360		   UNSPEC_FSINA))]
10361  "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10362  "
10363{
10364  rtx scaled = gen_reg_rtx (DFmode);
10365  rtx truncated = gen_reg_rtx (SImode);
10366  rtx fsca = gen_reg_rtx (V2SFmode);
10367  rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10368  rtx sfresult = gen_reg_rtx (SFmode);
10369
10370  emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10371  emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10372  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10373			  get_fpscr_rtx ()));
10374  emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 0));
10375  emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10376  DONE;
10377}")
10378
10379(define_expand "cosdf2"
10380  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10381	(unspec:DF [(match_operand:DF 1 "fp_arith_reg_operand" "")]
10382		   UNSPEC_FCOSA))]
10383  "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE && flag_unsafe_math_optimizations"
10384  "
10385{
10386  rtx scaled = gen_reg_rtx (DFmode);
10387  rtx truncated = gen_reg_rtx (SImode);
10388  rtx fsca = gen_reg_rtx (V2SFmode);
10389  rtx scale_reg = force_reg (DFmode, sh_fsca_df2int ());
10390  rtx sfresult = gen_reg_rtx (SFmode);
10391
10392  emit_df_insn (gen_muldf3 (scaled, operands[1], scale_reg));
10393  emit_df_insn (gen_fix_truncdfsi2 (truncated, scaled));
10394  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
10395			  get_fpscr_rtx ()));
10396  emit_move_insn (sfresult, gen_rtx_SUBREG (SFmode, fsca, 4));
10397  emit_df_insn (gen_extendsfdf2 (operands[0], sfresult));
10398  DONE;
10399}")
10400
10401(define_expand "abssf2"
10402  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
10403	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
10404  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
10405  "
10406{
10407  if (TARGET_SH2E)
10408    {
10409      expand_sf_unop (&gen_abssf2_i, operands);
10410      DONE;
10411    }
10412}")
10413
10414(define_insn "*abssf2_media"
10415  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10416	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10417  "TARGET_SHMEDIA_FPU"
10418  "fabs.s	%1, %0"
10419  [(set_attr "type" "fmove_media")])
10420
10421(define_insn "abssf2_i"
10422  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10423	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
10424   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10425  "TARGET_SH2E"
10426  "fabs	%0"
10427  [(set_attr "type" "fmove")
10428   (set_attr "fp_mode" "single")])
10429
10430(define_expand "adddf3"
10431  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10432	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10433		 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10434  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10435  "
10436{
10437  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10438    {
10439      expand_df_binop (&gen_adddf3_i, operands);
10440      DONE;
10441    }
10442}")
10443
10444(define_insn "*adddf3_media"
10445  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10446	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10447		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10448  "TARGET_SHMEDIA_FPU"
10449  "fadd.d	%1, %2, %0"
10450  [(set_attr "type" "dfparith_media")])
10451
10452(define_insn "adddf3_i"
10453  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10454	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10455		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10456   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10457  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10458  "fadd	%2,%0"
10459  [(set_attr "type" "dfp_arith")
10460   (set_attr "fp_mode" "double")])
10461
10462(define_expand "subdf3"
10463  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10464	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10465		  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10466  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10467  "
10468{
10469  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10470    {
10471      expand_df_binop (&gen_subdf3_i, operands);
10472      DONE;
10473    }
10474}")
10475
10476(define_insn "*subdf3_media"
10477  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10478	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10479		  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10480  "TARGET_SHMEDIA_FPU"
10481  "fsub.d	%1, %2, %0"
10482  [(set_attr "type" "dfparith_media")])
10483
10484(define_insn "subdf3_i"
10485  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10486	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10487		  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10488   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10489  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10490  "fsub	%2,%0"
10491  [(set_attr "type" "dfp_arith")
10492   (set_attr "fp_mode" "double")])
10493
10494(define_expand "muldf3"
10495  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10496	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10497		 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
10498  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10499  "
10500{
10501  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10502    {
10503      expand_df_binop (&gen_muldf3_i, operands);
10504      DONE;
10505    }
10506}")
10507
10508(define_insn "*muldf3_media"
10509  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10510	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
10511		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10512  "TARGET_SHMEDIA_FPU"
10513  "fmul.d	%1, %2, %0"
10514  [(set_attr "type" "dfmul_media")])
10515
10516(define_insn "muldf3_i"
10517  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10518	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
10519		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
10520   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10521  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10522  "fmul	%2,%0"
10523  [(set_attr "type" "dfp_mul")
10524   (set_attr "fp_mode" "double")])
10525
10526(define_expand "divdf3"
10527  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10528	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
10529		(match_operand:DF 2 "fp_arith_reg_operand" "")))]
10530  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10531  "
10532{
10533  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10534    {
10535      expand_df_binop (&gen_divdf3_i, operands);
10536      DONE;
10537    }
10538}")
10539
10540(define_insn "*divdf3_media"
10541  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10542	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
10543		(match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10544  "TARGET_SHMEDIA_FPU"
10545  "fdiv.d	%1, %2, %0"
10546  [(set_attr "type" "dfdiv_media")])
10547
10548(define_insn "divdf3_i"
10549  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10550	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
10551		(match_operand:DF 2 "fp_arith_reg_operand" "f")))
10552   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
10553  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10554  "fdiv	%2,%0"
10555  [(set_attr "type" "dfdiv")
10556   (set_attr "fp_mode" "double")])
10557
10558(define_insn "floatdidf2"
10559  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10560	(float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
10561  "TARGET_SHMEDIA_FPU"
10562  "float.qd	%1, %0"
10563  [(set_attr "type" "dfpconv_media")])
10564
10565(define_expand "floatsidf2"
10566  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10567	(float:DF (match_operand:SI 1 "fpul_operand" "")))]
10568  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10569  "
10570{
10571  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10572    {
10573      emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
10574				      get_fpscr_rtx ()));
10575      DONE;
10576    }
10577}")
10578
10579(define_insn "*floatsidf2_media"
10580  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10581	(float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
10582  "TARGET_SHMEDIA_FPU"
10583  "float.ld	%1, %0"
10584  [(set_attr "type" "dfpconv_media")])
10585
10586(define_insn "floatsidf2_i"
10587  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10588	(float:DF (match_operand:SI 1 "fpul_operand" "y")))
10589   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10590  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10591  "float	%1,%0"
10592  [(set_attr "type" "dfp_conv")
10593   (set_attr "fp_mode" "double")])
10594
10595(define_insn "fix_truncdfdi2"
10596  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
10597	(fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10598  "TARGET_SHMEDIA_FPU"
10599  "ftrc.dq	%1, %0"
10600  [(set_attr "type" "dfpconv_media")])
10601
10602(define_expand "fix_truncdfsi2"
10603  [(set (match_operand:SI 0 "fpul_operand" "")
10604	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
10605  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10606  "
10607{
10608  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10609    {
10610      emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
10611					  get_fpscr_rtx ()));
10612      DONE;
10613    }
10614}")
10615
10616(define_insn "*fix_truncdfsi2_media"
10617  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
10618	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10619  "TARGET_SHMEDIA_FPU"
10620  "ftrc.dl	%1, %0"
10621  [(set_attr "type" "dfpconv_media")])
10622
10623(define_insn "fix_truncdfsi2_i"
10624  [(set (match_operand:SI 0 "fpul_operand" "=y")
10625	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
10626   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10627  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10628  "ftrc	%1,%0"
10629  [(set_attr "type" "dfp_conv")
10630   (set_attr "dfp_comp" "no")
10631   (set_attr "fp_mode" "double")])
10632
10633;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
10634;; fix_truncdfsi2_i.
10635;; (define_insn "fix_truncdfsi2_i4"
10636;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10637;; 	(fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10638;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10639;;    (clobber (reg:SI FPUL_REG))]
10640;;   "TARGET_SH4"
10641;;   "#"
10642;;   [(set_attr "length" "4")
10643;;    (set_attr "fp_mode" "double")])
10644;;
10645;; (define_split
10646;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
10647;; 	(fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
10648;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
10649;;    (clobber (reg:SI FPUL_REG))]
10650;;   "TARGET_SH4"
10651;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
10652;; 	      (use (match_dup 2))])
10653;;    (set (match_dup 0) (reg:SI FPUL_REG))])
10654
10655(define_insn "cmpgtdf_t"
10656  [(set (reg:SI T_REG)
10657	(gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
10658	       (match_operand:DF 1 "arith_reg_operand" "f")))
10659   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10660  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10661  "fcmp/gt	%1,%0"
10662  [(set_attr "type" "dfp_cmp")
10663   (set_attr "fp_mode" "double")])
10664
10665(define_insn "cmpeqdf_t"
10666  [(set (reg:SI T_REG)
10667	(eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10668	       (match_operand:DF 1 "arith_reg_operand" "f")))
10669   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10670  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10671  "fcmp/eq	%1,%0"
10672  [(set_attr "type" "dfp_cmp")
10673   (set_attr "fp_mode" "double")])
10674
10675(define_insn "*ieee_ccmpeqdf_t"
10676  [(set (reg:SI T_REG)
10677	(ior:SI (reg:SI T_REG)
10678		(eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
10679		       (match_operand:DF 1 "arith_reg_operand" "f"))))
10680   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10681  "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10682  "* return output_ieee_ccmpeq (insn, operands);"
10683  [(set_attr "length" "4")
10684   (set_attr "fp_mode" "double")])
10685
10686(define_insn "cmpeqdf_media"
10687  [(set (match_operand:SI 0 "register_operand" "=r")
10688	(eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10689	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10690  "TARGET_SHMEDIA_FPU"
10691  "fcmpeq.d	%1,%2,%0"
10692  [(set_attr "type" "fcmp_media")])
10693
10694(define_insn "cmpgtdf_media"
10695  [(set (match_operand:SI 0 "register_operand" "=r")
10696	(gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10697	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10698  "TARGET_SHMEDIA_FPU"
10699  "fcmpgt.d	%1,%2,%0"
10700  [(set_attr "type" "fcmp_media")])
10701
10702(define_insn "cmpgedf_media"
10703  [(set (match_operand:SI 0 "register_operand" "=r")
10704	(ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10705	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10706  "TARGET_SHMEDIA_FPU"
10707  "fcmpge.d	%1,%2,%0"
10708  [(set_attr "type" "fcmp_media")])
10709
10710(define_insn "cmpundf_media"
10711  [(set (match_operand:SI 0 "register_operand" "=r")
10712	(unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
10713		      (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
10714  "TARGET_SHMEDIA_FPU"
10715  "fcmpun.d	%1,%2,%0"
10716  [(set_attr "type" "fcmp_media")])
10717
10718(define_expand "cbranchdf4"
10719  [(set (pc)
10720	(if_then_else (match_operator 0 "sh_float_comparison_operator"
10721		       [(match_operand:DF 1 "arith_operand" "")
10722			(match_operand:DF 2 "arith_operand" "")])
10723		      (match_operand 3 "" "")
10724		      (pc)))]
10725  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10726  "
10727{
10728  if (TARGET_SHMEDIA)
10729    emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
10730					  operands[3]));
10731  else
10732    sh_emit_compare_and_branch (operands, DFmode);
10733  DONE;
10734}")
10735
10736
10737(define_expand "negdf2"
10738  [(set (match_operand:DF 0 "arith_reg_operand" "")
10739	(neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10740  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10741  "
10742{
10743  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10744    {
10745      expand_df_unop (&gen_negdf2_i, operands);
10746      DONE;
10747    }
10748}")
10749
10750(define_insn "*negdf2_media"
10751  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10752	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10753  "TARGET_SHMEDIA_FPU"
10754  "fneg.d	%1, %0"
10755  [(set_attr "type" "fmove_media")])
10756
10757(define_insn "negdf2_i"
10758  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10759	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10760   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10761  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10762  "fneg	%0"
10763  [(set_attr "type" "fmove")
10764   (set_attr "fp_mode" "double")])
10765
10766(define_expand "sqrtdf2"
10767  [(set (match_operand:DF 0 "arith_reg_operand" "")
10768	(sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10769  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10770  "
10771{
10772  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10773    {
10774      expand_df_unop (&gen_sqrtdf2_i, operands);
10775      DONE;
10776    }
10777}")
10778
10779(define_insn "*sqrtdf2_media"
10780  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10781	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10782  "TARGET_SHMEDIA_FPU"
10783  "fsqrt.d	%1, %0"
10784  [(set_attr "type" "dfdiv_media")])
10785
10786(define_insn "sqrtdf2_i"
10787  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10788	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10789   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10790  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10791  "fsqrt	%0"
10792  [(set_attr "type" "dfdiv")
10793   (set_attr "fp_mode" "double")])
10794
10795(define_expand "absdf2"
10796  [(set (match_operand:DF 0 "arith_reg_operand" "")
10797	(abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
10798  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10799  "
10800{
10801  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10802    {
10803      expand_df_unop (&gen_absdf2_i, operands);
10804      DONE;
10805    }
10806}")
10807
10808(define_insn "*absdf2_media"
10809  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10810	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10811  "TARGET_SHMEDIA_FPU"
10812  "fabs.d	%1, %0"
10813  [(set_attr "type" "fmove_media")])
10814
10815(define_insn "absdf2_i"
10816  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10817	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
10818   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10819  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10820  "fabs	%0"
10821  [(set_attr "type" "fmove")
10822   (set_attr "fp_mode" "double")])
10823
10824(define_expand "extendsfdf2"
10825  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
10826	(float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
10827  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10828  "
10829{
10830  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10831    {
10832      emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
10833					get_fpscr_rtx ()));
10834      DONE;
10835    }
10836}")
10837
10838(define_insn "*extendsfdf2_media"
10839  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10840	(float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
10841  "TARGET_SHMEDIA_FPU"
10842  "fcnv.sd	%1, %0"
10843  [(set_attr "type" "dfpconv_media")])
10844
10845(define_insn "extendsfdf2_i4"
10846  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
10847	(float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
10848   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10849  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10850  "fcnvsd  %1,%0"
10851  [(set_attr "type" "fp")
10852   (set_attr "fp_mode" "double")])
10853
10854(define_expand "truncdfsf2"
10855  [(set (match_operand:SF 0 "fpul_operand" "")
10856	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
10857  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
10858  "
10859{
10860  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
10861    {
10862      emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
10863				       get_fpscr_rtx ()));
10864      DONE;
10865    }
10866}")
10867
10868(define_insn "*truncdfsf2_media"
10869  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
10870	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
10871  "TARGET_SHMEDIA_FPU"
10872  "fcnv.ds	%1, %0"
10873  [(set_attr "type" "dfpconv_media")])
10874
10875(define_insn "truncdfsf2_i4"
10876  [(set (match_operand:SF 0 "fpul_operand" "=y")
10877	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
10878   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
10879  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
10880  "fcnvds  %1,%0"
10881  [(set_attr "type" "fp")
10882   (set_attr "fp_mode" "double")])
10883
10884;; Bit field extract patterns.  These give better code for packed bitfields,
10885;; because they allow auto-increment addresses to be generated.
10886
10887(define_expand "insv"
10888  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
10889			 (match_operand:SI 1 "immediate_operand" "")
10890			 (match_operand:SI 2 "immediate_operand" ""))
10891	(match_operand:SI 3 "general_operand" ""))]
10892  "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
10893  "
10894{
10895  rtx addr_target, orig_address, shift_reg, qi_val;
10896  HOST_WIDE_INT bitsize, size, v = 0;
10897  rtx x = operands[3];
10898
10899  if (TARGET_SH2A && TARGET_BITOPS
10900      && (satisfies_constraint_Sbw (operands[0])
10901	  || satisfies_constraint_Sbv (operands[0]))
10902      && satisfies_constraint_M (operands[1])
10903      && satisfies_constraint_K03 (operands[2]))
10904    {
10905      if (satisfies_constraint_N (operands[3]))
10906	{
10907	  emit_insn (gen_bclr_m2a (operands[0], operands[2]));
10908	  DONE;
10909	}
10910      else if (satisfies_constraint_M (operands[3]))
10911	{
10912	  emit_insn (gen_bset_m2a (operands[0], operands[2]));
10913	  DONE;
10914	}
10915      else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
10916		&& satisfies_constraint_M (operands[1]))
10917	{
10918	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
10919	  DONE;
10920	}
10921      else if (REG_P (operands[3])
10922	       && satisfies_constraint_M (operands[1]))
10923	{
10924	  emit_insn (gen_bld_reg (operands[3], const0_rtx));
10925	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
10926	  DONE;
10927	}
10928    }
10929  /* ??? expmed doesn't care for non-register predicates.  */
10930  if (! memory_operand (operands[0], VOIDmode)
10931      || ! immediate_operand (operands[1], VOIDmode)
10932      || ! immediate_operand (operands[2], VOIDmode)
10933      || ! general_operand (x, VOIDmode))
10934    FAIL;
10935  /* If this isn't a 16 / 24 / 32 bit field, or if
10936     it doesn't start on a byte boundary, then fail.  */
10937  bitsize = INTVAL (operands[1]);
10938  if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
10939      || (INTVAL (operands[2]) % 8) != 0)
10940    FAIL;
10941
10942  size = bitsize / 8;
10943  orig_address = XEXP (operands[0], 0);
10944  shift_reg = gen_reg_rtx (SImode);
10945  if (CONST_INT_P (x))
10946    {
10947      v = INTVAL (x);
10948      qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
10949    }
10950  else
10951    {
10952      emit_insn (gen_movsi (shift_reg, operands[3]));
10953      qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
10954    }
10955  addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
10956
10957  operands[0] = replace_equiv_address (operands[0], addr_target);
10958  emit_insn (gen_movqi (operands[0], qi_val));
10959
10960  while (size -= 1)
10961    {
10962      if (CONST_INT_P (x))
10963	qi_val
10964	  = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
10965      else
10966	{
10967	  emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
10968	  qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
10969	}
10970      emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
10971      emit_insn (gen_movqi (operands[0], qi_val));
10972    }
10973
10974  DONE;
10975}")
10976
10977(define_insn "movua"
10978  [(set (match_operand:SI 0 "register_operand" "=z")
10979	(unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
10980		   UNSPEC_MOVUA))]
10981  "TARGET_SH4A_ARCH"
10982  "movua.l	%1,%0"
10983  [(set_attr "type" "movua")])
10984
10985;; We shouldn't need this, but cse replaces increments with references
10986;; to other regs before flow has a chance to create post_inc
10987;; addressing modes, and only postreload's cse_move2add brings the
10988;; increments back to a usable form.
10989(define_peephole2
10990  [(set (match_operand:SI 0 "register_operand" "")
10991	(sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
10992			 (const_int 32) (const_int 0)))
10993   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
10994  "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
10995  [(set (match_operand:SI 0 "register_operand" "")
10996	(sign_extract:SI (mem:SI (post_inc:SI
10997				  (match_operand:SI 1 "register_operand" "")))
10998			 (const_int 32) (const_int 0)))]
10999  "")
11000
11001(define_expand "extv"
11002  [(set (match_operand:SI 0 "register_operand" "")
11003	(sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11004			 (match_operand 2 "const_int_operand" "")
11005			 (match_operand 3 "const_int_operand" "")))]
11006  "TARGET_SH4A_ARCH || TARGET_SH2A"
11007{
11008  if (TARGET_SH2A && TARGET_BITOPS
11009      && (satisfies_constraint_Sbw (operands[1])
11010	  || satisfies_constraint_Sbv (operands[1]))
11011      && satisfies_constraint_M (operands[2])
11012      && satisfies_constraint_K03 (operands[3]))
11013   {
11014      emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
11015      if (REGNO (operands[0]) != T_REG)
11016	emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11017      DONE;
11018   }
11019  if (TARGET_SH4A_ARCH
11020      && INTVAL (operands[2]) == 32
11021      && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11022      && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11023    {
11024      rtx src = adjust_address (operands[1], BLKmode, 0);
11025      set_mem_size (src, GEN_INT (4));
11026      emit_insn (gen_movua (operands[0], src));
11027      DONE;
11028    }
11029
11030  FAIL;
11031})
11032
11033(define_expand "extzv"
11034  [(set (match_operand:SI 0 "register_operand" "")
11035	(zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
11036			 (match_operand 2 "const_int_operand" "")
11037			 (match_operand 3 "const_int_operand" "")))]
11038  "TARGET_SH4A_ARCH || TARGET_SH2A"
11039{
11040  if (TARGET_SH2A && TARGET_BITOPS
11041      && (satisfies_constraint_Sbw (operands[1])
11042	  || satisfies_constraint_Sbv (operands[1]))
11043      && satisfies_constraint_M (operands[2])
11044      && satisfies_constraint_K03 (operands[3]))
11045    {
11046      emit_insn (gen_bld_m2a (operands[1], operands[3]));
11047      if (REGNO (operands[0]) != T_REG)
11048	emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
11049      DONE;
11050    }
11051  if (TARGET_SH4A_ARCH
11052      && INTVAL (operands[2]) == 32
11053      && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
11054      && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
11055    {
11056      rtx src = adjust_address (operands[1], BLKmode, 0);
11057      set_mem_size (src, GEN_INT (4));
11058      emit_insn (gen_movua (operands[0], src));
11059      DONE;
11060    }
11061
11062  FAIL;
11063})
11064
11065;; SH2A instructions for bitwise operations.
11066
11067;; Clear a bit in a memory location.
11068(define_insn "bclr_m2a"
11069  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11070	(and:QI
11071	    (not:QI (ashift:QI (const_int 1)
11072			(match_operand:QI 1 "const_int_operand" "K03,K03")))
11073	    (match_dup 0)))]
11074  "TARGET_SH2A && TARGET_BITOPS"
11075  "@
11076	bclr.b\\t%1,%0
11077	bclr.b\\t%1,@(0,%t0)"
11078[(set_attr "length" "4,4")])
11079
11080(define_insn "bclrmem_m2a"
11081  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11082        (and:QI (match_dup 0)
11083                (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
11084  "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
11085  "@
11086        bclr.b\\t%W1,%0
11087        bclr.b\\t%W1,@(0,%t0)"
11088  [(set_attr "length" "4,4")])
11089
11090;; Set a bit in a memory location.
11091(define_insn "bset_m2a"
11092  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11093	(ior:QI
11094	    (ashift:QI (const_int 1)
11095		       (match_operand:QI 1 "const_int_operand" "K03,K03"))
11096	    (match_dup 0)))]
11097  "TARGET_SH2A && TARGET_BITOPS"
11098  "@
11099	bset.b\\t%1,%0
11100	bset.b\\t%1,@(0,%t0)"
11101  [(set_attr "length" "4,4")])
11102
11103(define_insn "bsetmem_m2a"
11104  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
11105	(ior:QI (match_dup 0)
11106		(match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
11107  "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
11108  "@
11109        bset.b\\t%V1,%0
11110        bset.b\\t%V1,@(0,%t0)"
11111  [(set_attr "length" "4,4")])
11112
11113;;; Transfer the contents of the T bit to a specified bit of memory.
11114(define_insn "bst_m2a"
11115  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
11116	(if_then_else (eq (reg:SI T_REG) (const_int 0))
11117	    (and:QI
11118		(not:QI (ashift:QI (const_int 1)
11119			(match_operand:QI 1 "const_int_operand" "K03,K03")))
11120		(match_dup 0))
11121	    (ior:QI
11122		(ashift:QI (const_int 1) (match_dup 1))
11123		(match_dup 0))))]
11124  "TARGET_SH2A && TARGET_BITOPS"
11125  "@
11126	bst.b\\t%1,%0
11127	bst.b\\t%1,@(0,%t0)"
11128  [(set_attr "length" "4")])
11129
11130;; Store a specified bit of memory in the T bit.
11131(define_insn "bld_m2a"
11132  [(set (reg:SI T_REG)
11133	(zero_extract:SI
11134	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
11135	    (const_int 1)
11136	    (match_operand 1 "const_int_operand" "K03,K03")))]
11137  "TARGET_SH2A && TARGET_BITOPS"
11138  "@
11139	bld.b\\t%1,%0
11140	bld.b\\t%1,@(0,%t0)"
11141  [(set_attr "length" "4,4")])
11142
11143;; Store a specified bit of memory in the T bit.
11144(define_insn "bldsign_m2a"
11145  [(set (reg:SI T_REG)
11146	(sign_extract:SI
11147	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11148	    (const_int 1)
11149	    (match_operand 1 "const_int_operand" "K03,K03")))]
11150  "TARGET_SH2A && TARGET_BITOPS"
11151  "@
11152	bld.b\\t%1,%0
11153	bld.b\\t%1,@(0,%t0)"
11154  [(set_attr "length" "4,4")])
11155
11156;; Store a specified bit of the LSB 8 bits of a register in the T bit.
11157(define_insn "bld_reg"
11158  [(set (reg:SI T_REG)
11159	(zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
11160			 (const_int 1)
11161			 (match_operand 1 "const_int_operand" "K03")))]
11162  "TARGET_SH2A"
11163  "bld\\t%1,%0")
11164
11165(define_insn "*bld_regqi"
11166  [(set (reg:SI T_REG)
11167	(zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
11168			 (const_int 1)
11169			 (match_operand 1 "const_int_operand" "K03")))]
11170  "TARGET_SH2A"
11171  "bld\\t%1,%0")
11172
11173;; Take logical and of a specified bit of memory with the T bit and
11174;; store its result in the T bit.
11175(define_insn "band_m2a"
11176  [(set (reg:SI T_REG)
11177	(and:SI (reg:SI T_REG)
11178		(zero_extract:SI
11179		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11180		    (const_int 1)
11181		    (match_operand 1 "const_int_operand" "K03,K03"))))]
11182  "TARGET_SH2A && TARGET_BITOPS"
11183  "@
11184	band.b\\t%1,%0
11185	band.b\\t%1,@(0,%t0)"
11186  [(set_attr "length" "4,4")])
11187
11188(define_insn "bandreg_m2a"
11189  [(set (match_operand:SI 0 "register_operand" "=r,r")
11190	(and:SI (zero_extract:SI
11191		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11192		    (const_int 1)
11193		    (match_operand 2 "const_int_operand" "K03,K03"))
11194        	(match_operand:SI 3 "register_operand" "r,r")))]
11195  "TARGET_SH2A && TARGET_BITOPS"
11196  "@
11197	band.b\\t%2,%1\;movt\\t%0
11198	band.b\\t%2,@(0,%t1)\;movt\\t%0"
11199  [(set_attr "length" "6,6")])
11200
11201;; Take logical or of a specified bit of memory with the T bit and
11202;; store its result in the T bit.
11203(define_insn "bor_m2a"
11204  [(set (reg:SI T_REG)
11205	(ior:SI (reg:SI T_REG)
11206		(zero_extract:SI
11207		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11208		    (const_int 1)
11209		    (match_operand 1 "const_int_operand" "K03,K03"))))]
11210  "TARGET_SH2A && TARGET_BITOPS"
11211  "@
11212	bor.b\\t%1,%0
11213	bor.b\\t%1,@(0,%t0)"
11214  [(set_attr "length" "4,4")])
11215
11216(define_insn "borreg_m2a"
11217  [(set (match_operand:SI 0 "register_operand" "=r,r")
11218	(ior:SI (zero_extract:SI
11219		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11220		    (const_int 1)
11221		    (match_operand 2 "const_int_operand" "K03,K03"))
11222		(match_operand:SI 3 "register_operand" "=r,r")))]
11223  "TARGET_SH2A && TARGET_BITOPS"
11224  "@
11225	bor.b\\t%2,%1\;movt\\t%0
11226	bor.b\\t%2,@(0,%t1)\;movt\\t%0"
11227  [(set_attr "length" "6,6")])
11228
11229;; Take exclusive or of a specified bit of memory with the T bit and
11230;; store its result in the T bit.
11231(define_insn "bxor_m2a"
11232  [(set (reg:SI T_REG)
11233	(xor:SI (reg:SI T_REG)
11234		(zero_extract:SI
11235		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
11236		    (const_int 1)
11237		    (match_operand 1 "const_int_operand" "K03,K03"))))]
11238  "TARGET_SH2A && TARGET_BITOPS"
11239  "@
11240	bxor.b\\t%1,%0
11241	bxor.b\\t%1,@(0,%t0)"
11242  [(set_attr "length" "4,4")])
11243
11244(define_insn "bxorreg_m2a"
11245  [(set (match_operand:SI 0 "register_operand" "=r,r")
11246	(xor:SI (zero_extract:SI
11247		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
11248		    (const_int 1)
11249		    (match_operand 2 "const_int_operand" "K03,K03"))
11250		(match_operand:SI 3 "register_operand" "=r,r")))]
11251  "TARGET_SH2A && TARGET_BITOPS"
11252  "@
11253	bxor.b\\t%2,%1\;movt\\t%0
11254	bxor.b\\t%2,@(0,%t1)\;movt\\t%0"
11255  [(set_attr "length" "6,6")])
11256
11257
11258;; -------------------------------------------------------------------------
11259;; Peepholes
11260;; -------------------------------------------------------------------------
11261;; This matches cases where the bit in a memory location is set.
11262(define_peephole2
11263  [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11264	(sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11265   (set (match_dup 0)
11266	(ior:SI (match_dup 0)
11267	(match_operand:SI 2 "const_int_operand" "Pso,Pso")))
11268   (set (match_dup 1)
11269	(match_operand 3 "arith_reg_operand" "r,r"))]
11270  "TARGET_SH2A && TARGET_BITOPS
11271   && satisfies_constraint_Pso (operands[2])
11272   && REGNO (operands[0]) == REGNO (operands[3])"
11273  [(set (match_dup 1)
11274        (ior:QI (match_dup 1)
11275                (match_dup 2)))]
11276  "")
11277
11278;; This matches cases where the bit in a memory location is cleared.
11279(define_peephole2
11280  [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
11281	(sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
11282   (set (match_dup 0)
11283	(and:SI (match_dup 0)
11284	(match_operand:SI 2 "const_int_operand" "Psz,Psz")))
11285   (set (match_dup 1)
11286	(match_operand 3 "arith_reg_operand" "r,r"))]
11287  "TARGET_SH2A && TARGET_BITOPS
11288   && satisfies_constraint_Psz (operands[2])
11289   && REGNO (operands[0]) == REGNO (operands[3])"
11290  [(set (match_dup 1)
11291        (and:QI (match_dup 1)
11292                (match_dup 2)))]
11293  "")
11294
11295;; This matches cases where a stack pointer increment at the start of the
11296;; epilogue combines with a stack slot read loading the return value.
11297
11298(define_peephole
11299  [(set (match_operand:SI 0 "arith_reg_operand" "")
11300	(mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
11301   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
11302  "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
11303  "mov.l	@%1+,%0")
11304
11305;; See the comment on the dt combiner pattern above.
11306
11307(define_peephole
11308  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
11309	(plus:SI (match_dup 0)
11310		 (const_int -1)))
11311   (set (reg:SI T_REG)
11312	(eq:SI (match_dup 0)
11313	       (const_int 0)))]
11314  "TARGET_SH2"
11315  "dt	%0")
11316
11317;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
11318;; to `mov #k,r0; mov.l @(r0,r15),rn'.  These sequences are generated by
11319;; reload when the constant is too large for a reg+offset address.
11320
11321;; ??? We would get much better code if this was done in reload.  This would
11322;; require modifying find_reloads_address to recognize that if the constant
11323;; is out-of-range for an immediate add, then we get better code by reloading
11324;; the constant into a register than by reloading the sum into a register,
11325;; since the former is one instruction shorter if the address does not need
11326;; to be offsettable.  Unfortunately this does not work, because there is
11327;; only one register, r0, that can be used as an index register.  This register
11328;; is also the function return value register.  So, if we try to force reload
11329;; to use double-reg addresses, then we end up with some instructions that
11330;; need to use r0 twice.  The only way to fix this is to change the calling
11331;; convention so that r0 is not used to return values.
11332
11333(define_peephole
11334  [(set (match_operand:SI 0 "register_operand" "=r")
11335	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11336   (set (mem:SI (match_dup 0))
11337	(match_operand:SI 2 "general_movsrc_operand" ""))]
11338  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11339  "mov.l	%2,@(%0,%1)")
11340
11341(define_peephole
11342  [(set (match_operand:SI 0 "register_operand" "=r")
11343	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11344   (set (match_operand:SI 2 "general_movdst_operand" "")
11345	(mem:SI (match_dup 0)))]
11346  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11347  "mov.l	@(%0,%1),%2")
11348
11349(define_peephole
11350  [(set (match_operand:SI 0 "register_operand" "=r")
11351	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11352   (set (mem:HI (match_dup 0))
11353	(match_operand:HI 2 "general_movsrc_operand" ""))]
11354  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11355  "mov.w	%2,@(%0,%1)")
11356
11357(define_peephole
11358  [(set (match_operand:SI 0 "register_operand" "=r")
11359	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11360   (set (match_operand:HI 2 "general_movdst_operand" "")
11361	(mem:HI (match_dup 0)))]
11362  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11363  "mov.w	@(%0,%1),%2")
11364
11365(define_peephole
11366  [(set (match_operand:SI 0 "register_operand" "=r")
11367	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11368   (set (mem:QI (match_dup 0))
11369	(match_operand:QI 2 "general_movsrc_operand" ""))]
11370  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11371  "mov.b	%2,@(%0,%1)")
11372
11373(define_peephole
11374  [(set (match_operand:SI 0 "register_operand" "=r")
11375	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11376   (set (match_operand:QI 2 "general_movdst_operand" "")
11377	(mem:QI (match_dup 0)))]
11378  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
11379  "mov.b	@(%0,%1),%2")
11380
11381(define_peephole
11382  [(set (match_operand:SI 0 "register_operand" "=r")
11383	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11384   (set (mem:SF (match_dup 0))
11385	(match_operand:SF 2 "general_movsrc_operand" ""))]
11386  "TARGET_SH1 && REGNO (operands[0]) == 0
11387   && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11388       || (GET_CODE (operands[2]) == SUBREG
11389	   && REGNO (SUBREG_REG (operands[2])) < 16))
11390   && reg_unused_after (operands[0], insn)"
11391  "mov.l	%2,@(%0,%1)")
11392
11393(define_peephole
11394  [(set (match_operand:SI 0 "register_operand" "=r")
11395	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11396   (set (match_operand:SF 2 "general_movdst_operand" "")
11397
11398	(mem:SF (match_dup 0)))]
11399  "TARGET_SH1 && REGNO (operands[0]) == 0
11400   && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
11401       || (GET_CODE (operands[2]) == SUBREG
11402	   && REGNO (SUBREG_REG (operands[2])) < 16))
11403   && reg_unused_after (operands[0], insn)"
11404  "mov.l	@(%0,%1),%2")
11405
11406(define_peephole
11407  [(set (match_operand:SI 0 "register_operand" "=r")
11408	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11409   (set (mem:SF (match_dup 0))
11410	(match_operand:SF 2 "general_movsrc_operand" ""))]
11411  "TARGET_SH2E && REGNO (operands[0]) == 0
11412   && ((REG_P (operands[2])
11413        && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11414       || (GET_CODE (operands[2]) == SUBREG
11415	   && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11416   && reg_unused_after (operands[0], insn)"
11417  "fmov{.s|}	%2,@(%0,%1)")
11418
11419(define_peephole
11420  [(set (match_operand:SI 0 "register_operand" "=r")
11421	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
11422   (set (match_operand:SF 2 "general_movdst_operand" "")
11423
11424	(mem:SF (match_dup 0)))]
11425  "TARGET_SH2E && REGNO (operands[0]) == 0
11426   && ((REG_P (operands[2])
11427	&& FP_OR_XD_REGISTER_P (REGNO (operands[2])))
11428       || (GET_CODE (operands[2]) == SUBREG
11429	   && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
11430   && reg_unused_after (operands[0], insn)"
11431  "fmov{.s|}	@(%0,%1),%2")
11432
11433;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
11434(define_insn "sp_switch_1"
11435  [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
11436  "TARGET_SH1"
11437  "*
11438{
11439  output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", operands);
11440  output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", operands);
11441  return \"mov r0,r15\";
11442}"
11443  [(set_attr "length" "10")])
11444
11445;; Switch back to the original stack for interrupt functions with the
11446;; sp_switch attribute.  */
11447(define_insn "sp_switch_2"
11448  [(const_int 2)]
11449  "TARGET_SH1"
11450  "mov.l @r15+,r15\;mov.l @r15+,r0"
11451  [(set_attr "length" "4")])
11452
11453;; Integer vector moves
11454
11455(define_expand "movv8qi"
11456  [(set (match_operand:V8QI 0 "general_movdst_operand" "")
11457	(match_operand:V8QI 1 "general_movsrc_operand" ""))]
11458  "TARGET_SHMEDIA"
11459  "{ if (prepare_move_operands (operands, V8QImode)) DONE; }")
11460
11461(define_insn "movv8qi_i"
11462  [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
11463	(match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11464  "TARGET_SHMEDIA
11465   && (register_operand (operands[0], V8QImode)
11466       || sh_register_operand (operands[1], V8QImode))"
11467  "@
11468	add	%1, r63, %0
11469	movi	%1, %0
11470	#
11471	ld%M1.q	%m1, %0
11472	st%M0.q	%m0, %N1"
11473  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11474   (set_attr "length" "4,4,16,4,4")])
11475
11476(define_split
11477  [(set (match_operand:V8QI 0 "arith_reg_dest" "")
11478	(subreg:V8QI (const_int 0) 0))]
11479  "TARGET_SHMEDIA"
11480  [(set (match_dup 0)
11481	(const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
11482			    (const_int 0) (const_int 0) (const_int 0)
11483			    (const_int 0) (const_int 0)]))])
11484
11485(define_split
11486  [(set (match_operand 0 "arith_reg_dest" "")
11487	(match_operand 1 "sh_rep_vec" ""))]
11488  "TARGET_SHMEDIA && reload_completed
11489   && GET_MODE (operands[0]) == GET_MODE (operands[1])
11490   && sh_vector_mode_supported_p (GET_MODE (operands[0]))
11491   && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
11492   && (XVECEXP (operands[1], 0, 0) != const0_rtx
11493       || XVECEXP (operands[1], 0, 1) != const0_rtx)
11494   && (XVECEXP (operands[1], 0, 0) != constm1_rtx
11495       || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
11496  [(set (match_dup 0) (match_dup 1))
11497   (match_dup 2)]
11498  "
11499{
11500  int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
11501  rtx elt1 = XVECEXP (operands[1], 0, 1);
11502
11503  if (unit_size > 2)
11504    operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
11505  else
11506    {
11507      if (unit_size < 2)
11508	operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
11509      operands[2] = gen_mperm_w0 (operands[0], operands[0]);
11510    }
11511  operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
11512  operands[1] = XVECEXP (operands[1], 0, 0);
11513  if (unit_size < 2)
11514    {
11515      if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
11516	operands[1]
11517	  = GEN_INT (TARGET_LITTLE_ENDIAN
11518		     ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
11519		     : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
11520      else
11521	{
11522	  operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
11523	  operands[1]
11524	    = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
11525	}
11526    }
11527}")
11528
11529(define_split
11530  [(set (match_operand 0 "arith_reg_dest" "")
11531	(match_operand 1 "sh_const_vec" ""))]
11532  "TARGET_SHMEDIA && reload_completed
11533   && GET_MODE (operands[0]) == GET_MODE (operands[1])
11534   && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
11535  [(set (match_dup 0) (match_dup 1))]
11536  "
11537{
11538  rtx v = operands[1];
11539  enum machine_mode new_mode
11540    = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
11541
11542  operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
11543  operands[1]
11544    = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
11545}")
11546
11547(define_expand "movv2hi"
11548  [(set (match_operand:V2HI 0 "general_movdst_operand" "")
11549	(match_operand:V2HI 1 "general_movsrc_operand" ""))]
11550  "TARGET_SHMEDIA"
11551  "{ if (prepare_move_operands (operands, V2HImode)) DONE; }")
11552
11553(define_insn "movv2hi_i"
11554  [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11555	(match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11556  "TARGET_SHMEDIA
11557   && (register_operand (operands[0], V2HImode)
11558       || sh_register_operand (operands[1], V2HImode))"
11559  "@
11560	add.l	%1, r63, %0
11561	movi	%1, %0
11562	#
11563	ld%M1.l	%m1, %0
11564	st%M0.l	%m0, %N1"
11565  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11566   (set_attr "length" "4,4,16,4,4")
11567   (set (attr "highpart")
11568	(cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
11569	       (const_string "user")]
11570	      (const_string "ignore")))])
11571
11572(define_expand "movv4hi"
11573  [(set (match_operand:V4HI 0 "general_movdst_operand" "")
11574	(match_operand:V4HI 1 "general_movsrc_operand" ""))]
11575  "TARGET_SHMEDIA"
11576  "{ if (prepare_move_operands (operands, V4HImode)) DONE; }")
11577
11578(define_insn "movv4hi_i"
11579  [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
11580	(match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11581  "TARGET_SHMEDIA
11582   && (register_operand (operands[0], V4HImode)
11583       || sh_register_operand (operands[1], V4HImode))"
11584  "@
11585	add	%1, r63, %0
11586	movi	%1, %0
11587	#
11588	ld%M1.q	%m1, %0
11589	st%M0.q	%m0, %N1"
11590  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11591   (set_attr "length" "4,4,16,4,4")
11592   (set_attr "highpart" "depend")])
11593
11594(define_expand "movv2si"
11595  [(set (match_operand:V2SI 0 "general_movdst_operand" "")
11596	(match_operand:V2SI 1 "general_movsrc_operand" ""))]
11597  "TARGET_SHMEDIA"
11598  "{ if (prepare_move_operands (operands, V2SImode)) DONE; }")
11599
11600(define_insn "movv2si_i"
11601  [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
11602	(match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
11603  "TARGET_SHMEDIA
11604   && (register_operand (operands[0], V2SImode)
11605       || sh_register_operand (operands[1], V2SImode))"
11606  "@
11607	add	%1, r63, %0
11608	#
11609	#
11610	ld%M1.q	%m1, %0
11611	st%M0.q	%m0, %N1"
11612  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
11613   (set_attr "length" "4,4,16,4,4")
11614   (set_attr "highpart" "depend")])
11615
11616;; Multimedia Intrinsics
11617
11618(define_insn "absv2si2"
11619  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11620	(abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
11621  "TARGET_SHMEDIA"
11622  "mabs.l	%1, %0"
11623  [(set_attr "type" "mcmp_media")
11624   (set_attr "highpart" "depend")])
11625
11626(define_insn "absv4hi2"
11627  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11628	(abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
11629  "TARGET_SHMEDIA"
11630  "mabs.w	%1, %0"
11631  [(set_attr "type" "mcmp_media")
11632   (set_attr "highpart" "depend")])
11633
11634(define_insn "addv2si3"
11635  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11636	(plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11637		   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11638  "TARGET_SHMEDIA"
11639  "madd.l	%1, %2, %0"
11640  [(set_attr "type" "arith_media")
11641   (set_attr "highpart" "depend")])
11642
11643(define_insn "addv4hi3"
11644  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11645	(plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11646		   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11647  "TARGET_SHMEDIA"
11648  "madd.w	%1, %2, %0"
11649  [(set_attr "type" "arith_media")
11650   (set_attr "highpart" "depend")])
11651
11652(define_insn_and_split "addv2hi3"
11653  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
11654	(plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
11655		   (match_operand:V2HI 2 "extend_reg_operand" "r")))]
11656  "TARGET_SHMEDIA"
11657  "#"
11658  "TARGET_SHMEDIA"
11659  [(const_int 0)]
11660  "
11661{
11662  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
11663  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
11664  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
11665  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
11666  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
11667
11668  emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
11669  emit_insn (gen_truncdisi2 (si_dst, di_dst));
11670  DONE;
11671}"
11672  [(set_attr "highpart" "must_split")])
11673
11674(define_insn "ssaddv2si3"
11675  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11676	(ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
11677		      (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11678  "TARGET_SHMEDIA"
11679  "madds.l	%1, %2, %0"
11680  [(set_attr "type" "mcmp_media")
11681   (set_attr "highpart" "depend")])
11682
11683(define_insn "usaddv8qi3"
11684  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11685	(us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
11686		      (match_operand:V8QI 2 "arith_reg_operand" "r")))]
11687  "TARGET_SHMEDIA"
11688  "madds.ub	%1, %2, %0"
11689  [(set_attr "type" "mcmp_media")
11690   (set_attr "highpart" "depend")])
11691
11692(define_insn "ssaddv4hi3"
11693  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11694	(ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
11695		      (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11696  "TARGET_SHMEDIA"
11697  "madds.w	%1, %2, %0"
11698  [(set_attr "type" "mcmp_media")
11699   (set_attr "highpart" "depend")])
11700
11701(define_insn "negcmpeqv8qi"
11702  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11703	(neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11704			   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11705  "TARGET_SHMEDIA"
11706  "mcmpeq.b	%N1, %N2, %0"
11707  [(set_attr "type" "mcmp_media")
11708   (set_attr "highpart" "depend")])
11709
11710(define_insn "negcmpeqv2si"
11711  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11712	(neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11713			   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11714  "TARGET_SHMEDIA"
11715  "mcmpeq.l	%N1, %N2, %0"
11716  [(set_attr "type" "mcmp_media")
11717   (set_attr "highpart" "depend")])
11718
11719(define_insn "negcmpeqv4hi"
11720  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11721	(neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11722			   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11723  "TARGET_SHMEDIA"
11724  "mcmpeq.w	%N1, %N2, %0"
11725  [(set_attr "type" "mcmp_media")
11726   (set_attr "highpart" "depend")])
11727
11728(define_insn "negcmpgtuv8qi"
11729  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11730	(neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
11731			    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
11732  "TARGET_SHMEDIA"
11733  "mcmpgt.ub	%N1, %N2, %0"
11734  [(set_attr "type" "mcmp_media")
11735   (set_attr "highpart" "depend")])
11736
11737(define_insn "negcmpgtv2si"
11738  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11739	(neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
11740			   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11741  "TARGET_SHMEDIA"
11742  "mcmpgt.l	%N1, %N2, %0"
11743  [(set_attr "type" "mcmp_media")
11744   (set_attr "highpart" "depend")])
11745
11746(define_insn "negcmpgtv4hi"
11747  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11748	(neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
11749			   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11750  "TARGET_SHMEDIA"
11751  "mcmpgt.w	%N1, %N2, %0"
11752  [(set_attr "type" "mcmp_media")
11753   (set_attr "highpart" "depend")])
11754
11755(define_insn "mcmv"
11756  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11757	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11758			(match_operand:DI 2 "arith_reg_operand" "r"))
11759		(and:DI (match_operand:DI 3 "arith_reg_operand" "0")
11760			(not:DI (match_dup 2)))))]
11761  "TARGET_SHMEDIA"
11762  "mcmv	%N1, %2, %0"
11763  [(set_attr "type" "arith_media")
11764   (set_attr "highpart" "depend")])
11765
11766(define_insn "mcnvs_lw"
11767  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11768	(vec_concat:V4HI
11769	 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
11770	 (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
11771  "TARGET_SHMEDIA"
11772  "mcnvs.lw	%N1, %N2, %0"
11773  [(set_attr "type" "mcmp_media")])
11774
11775(define_insn "mcnvs_wb"
11776  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11777	(vec_concat:V8QI
11778	 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11779	 (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11780  "TARGET_SHMEDIA"
11781  "mcnvs.wb	%N1, %N2, %0"
11782  [(set_attr "type" "mcmp_media")])
11783
11784(define_insn "mcnvs_wub"
11785  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
11786	(vec_concat:V8QI
11787	 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
11788	 (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
11789  "TARGET_SHMEDIA"
11790  "mcnvs.wub	%N1, %N2, %0"
11791  [(set_attr "type" "mcmp_media")])
11792
11793(define_insn "mextr_rl"
11794  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11795	(ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11796			     (match_operand:HI 3 "mextr_bit_offset" "i"))
11797	       (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11798			  (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11799  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11800  "*
11801{
11802  static char templ[21];
11803
11804  sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\",
11805	   (int) INTVAL (operands[3]) >> 3);
11806  return templ;
11807}"
11808  [(set_attr "type" "arith_media")])
11809
11810(define_insn "*mextr_lr"
11811  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11812	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11813			   (match_operand:HI 3 "mextr_bit_offset" "i"))
11814	       (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
11815			    (match_operand:HI 4 "mextr_bit_offset" "i"))))]
11816  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
11817  "*
11818{
11819  static char templ[21];
11820
11821  sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\",
11822	   (int) INTVAL (operands[4]) >> 3);
11823  return templ;
11824}"
11825  [(set_attr "type" "arith_media")])
11826
11827; mextrN can be modelled with vec_select / vec_concat, but the selection
11828; vector then varies depending on endianness.
11829(define_expand "mextr1"
11830  [(match_operand:DI 0 "arith_reg_dest" "")
11831   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11832   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11833  "TARGET_SHMEDIA"
11834  "
11835{
11836  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11837			   GEN_INT (1 * 8), GEN_INT (7 * 8)));
11838  DONE;
11839}")
11840
11841(define_expand "mextr2"
11842  [(match_operand:DI 0 "arith_reg_dest" "")
11843   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11844   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11845  "TARGET_SHMEDIA"
11846  "
11847{
11848  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11849			   GEN_INT (2 * 8), GEN_INT (6 * 8)));
11850  DONE;
11851}")
11852
11853(define_expand "mextr3"
11854  [(match_operand:DI 0 "arith_reg_dest" "")
11855   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11856   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11857  "TARGET_SHMEDIA"
11858  "
11859{
11860  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11861			   GEN_INT (3 * 8), GEN_INT (5 * 8)));
11862  DONE;
11863}")
11864
11865(define_expand "mextr4"
11866  [(match_operand:DI 0 "arith_reg_dest" "")
11867   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11868   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11869  "TARGET_SHMEDIA"
11870  "
11871{
11872  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11873			   GEN_INT (4 * 8), GEN_INT (4 * 8)));
11874  DONE;
11875}")
11876
11877(define_expand "mextr5"
11878  [(match_operand:DI 0 "arith_reg_dest" "")
11879   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11880   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11881  "TARGET_SHMEDIA"
11882  "
11883{
11884  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11885			   GEN_INT (5 * 8), GEN_INT (3 * 8)));
11886  DONE;
11887}")
11888
11889(define_expand "mextr6"
11890  [(match_operand:DI 0 "arith_reg_dest" "")
11891   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11892   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11893  "TARGET_SHMEDIA"
11894  "
11895{
11896  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11897			   GEN_INT (6 * 8), GEN_INT (2 * 8)));
11898  DONE;
11899}")
11900
11901(define_expand "mextr7"
11902  [(match_operand:DI 0 "arith_reg_dest" "")
11903   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
11904   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
11905  "TARGET_SHMEDIA"
11906  "
11907{
11908  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
11909			   GEN_INT (7 * 8), GEN_INT (1 * 8)));
11910  DONE;
11911}")
11912
11913(define_expand "mmacfx_wl"
11914  [(match_operand:V2SI 0 "arith_reg_dest" "")
11915   (match_operand:V2HI 1 "extend_reg_operand" "")
11916   (match_operand:V2HI 2 "extend_reg_operand" "")
11917   (match_operand:V2SI 3 "arith_reg_operand" "")]
11918  "TARGET_SHMEDIA"
11919  "
11920{
11921  emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
11922			      operands[1], operands[2]));
11923  DONE;
11924}")
11925
11926;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
11927;; is depend
11928(define_insn "mmacfx_wl_i"
11929  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11930	(ss_plus:V2SI
11931	 (match_operand:V2SI 1 "arith_reg_operand" "0")
11932	 (ss_truncate:V2SI
11933	  (ashift:V2DI
11934	   (sign_extend:V2DI
11935	    (mult:V2SI
11936	     (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
11937	     (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
11938	   (const_int 1)))))]
11939  "TARGET_SHMEDIA"
11940  "mmacfx.wl	%2, %3, %0"
11941  [(set_attr "type" "mac_media")
11942   (set_attr "highpart" "depend")])
11943
11944(define_expand "mmacnfx_wl"
11945  [(match_operand:V2SI 0 "arith_reg_dest" "")
11946   (match_operand:V2HI 1 "extend_reg_operand" "")
11947   (match_operand:V2HI 2 "extend_reg_operand" "")
11948   (match_operand:V2SI 3 "arith_reg_operand" "")]
11949  "TARGET_SHMEDIA"
11950  "
11951{
11952  emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
11953			       operands[1], operands[2]));
11954  DONE;
11955}")
11956
11957(define_insn "mmacnfx_wl_i"
11958  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11959	(ss_minus:V2SI
11960	 (match_operand:V2SI 1 "arith_reg_operand" "0")
11961	 (ss_truncate:V2SI
11962	  (ashift:V2DI
11963	   (sign_extend:V2DI
11964	    (mult:V2SI
11965	     (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
11966	     (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
11967	   (const_int 1)))))]
11968  "TARGET_SHMEDIA"
11969  "mmacnfx.wl	%2, %3, %0"
11970  [(set_attr "type" "mac_media")
11971   (set_attr "highpart" "depend")])
11972
11973(define_insn "mulv2si3"
11974  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11975	(mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
11976		   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
11977  "TARGET_SHMEDIA"
11978  "mmul.l	%1, %2, %0"
11979  [(set_attr "type" "d2mpy_media")
11980   (set_attr "highpart" "depend")])
11981
11982(define_insn "mulv4hi3"
11983  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
11984	(mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
11985		   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
11986  "TARGET_SHMEDIA"
11987  "mmul.w	%1, %2, %0"
11988  [(set_attr "type" "dmpy_media")
11989   (set_attr "highpart" "depend")])
11990
11991(define_insn "mmulfx_l"
11992  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
11993	(ss_truncate:V2SI
11994	 (ashiftrt:V2DI
11995	  (mult:V2DI
11996	   (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
11997	   (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
11998	  (const_int 31))))]
11999  "TARGET_SHMEDIA"
12000  "mmulfx.l	%1, %2, %0"
12001  [(set_attr "type" "d2mpy_media")
12002   (set_attr "highpart" "depend")])
12003
12004(define_insn "mmulfx_w"
12005  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12006	(ss_truncate:V4HI
12007	 (ashiftrt:V4SI
12008	  (mult:V4SI
12009	   (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12010	   (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12011	  (const_int 15))))]
12012  "TARGET_SHMEDIA"
12013  "mmulfx.w	%1, %2, %0"
12014  [(set_attr "type" "dmpy_media")
12015   (set_attr "highpart" "depend")])
12016
12017(define_insn "mmulfxrp_w"
12018  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12019	(ss_truncate:V4HI
12020	 (ashiftrt:V4SI
12021	  (plus:V4SI
12022	   (mult:V4SI
12023	    (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12024	    (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12025	   (const_int 16384))
12026	  (const_int 15))))]
12027  "TARGET_SHMEDIA"
12028  "mmulfxrp.w	%1, %2, %0"
12029  [(set_attr "type" "dmpy_media")
12030   (set_attr "highpart" "depend")])
12031
12032
12033(define_expand "mmulhi_wl"
12034  [(match_operand:V2SI 0 "arith_reg_dest" "")
12035   (match_operand:V4HI 1 "arith_reg_operand" "")
12036   (match_operand:V4HI 2 "arith_reg_operand" "")]
12037  "TARGET_SHMEDIA"
12038  "
12039{
12040  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
12041	     (operands[0], operands[1], operands[2]));
12042  DONE;
12043}")
12044
12045(define_expand "mmullo_wl"
12046  [(match_operand:V2SI 0 "arith_reg_dest" "")
12047   (match_operand:V4HI 1 "arith_reg_operand" "")
12048   (match_operand:V4HI 2 "arith_reg_operand" "")]
12049  "TARGET_SHMEDIA"
12050  "
12051{
12052  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
12053	     (operands[0], operands[1], operands[2]));
12054  DONE;
12055}")
12056
12057(define_insn "mmul23_wl"
12058  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12059	(vec_select:V2SI
12060	 (mult:V4SI
12061	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12062	  (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12063	 (parallel [(const_int 2) (const_int 3)])))]
12064  "TARGET_SHMEDIA"
12065  "* return (TARGET_LITTLE_ENDIAN
12066	     ? \"mmulhi.wl	%1, %2, %0\"
12067	     : \"mmullo.wl	%1, %2, %0\");"
12068  [(set_attr "type" "dmpy_media")
12069   (set (attr "highpart")
12070	(cond [(eq_attr "endian" "big") (const_string "ignore")]
12071	 (const_string "user")))])
12072
12073(define_insn "mmul01_wl"
12074  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12075	(vec_select:V2SI
12076	 (mult:V4SI
12077	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12078	  (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
12079	 (parallel [(const_int 0) (const_int 1)])))]
12080  "TARGET_SHMEDIA"
12081  "* return (TARGET_LITTLE_ENDIAN
12082	     ? \"mmullo.wl	%1, %2, %0\"
12083	     : \"mmulhi.wl	%1, %2, %0\");"
12084  [(set_attr "type" "dmpy_media")
12085   (set (attr "highpart")
12086	(cond [(eq_attr "endian" "little") (const_string "ignore")]
12087	 (const_string "user")))])
12088
12089
12090(define_expand "mmulsum_wq"
12091  [(match_operand:DI 0 "arith_reg_dest" "")
12092   (match_operand:V4HI 1 "arith_reg_operand" "")
12093   (match_operand:V4HI 2 "arith_reg_operand" "")
12094   (match_operand:DI 3 "arith_reg_operand" "")]
12095  "TARGET_SHMEDIA"
12096  "
12097{
12098  emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
12099			       operands[1], operands[2]));
12100  DONE;
12101}")
12102
12103(define_insn "mmulsum_wq_i"
12104  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12105	(plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
12106	 (plus:DI
12107	  (plus:DI
12108	   (vec_select:DI
12109	    (mult:V4DI
12110	     (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
12111	     (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
12112	    (parallel [(const_int 0)]))
12113	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12114				     (sign_extend:V4DI (match_dup 3)))
12115			  (parallel [(const_int 1)])))
12116	  (plus:DI
12117	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12118				     (sign_extend:V4DI (match_dup 3)))
12119			  (parallel [(const_int 2)]))
12120	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
12121				     (sign_extend:V4DI (match_dup 3)))
12122			  (parallel [(const_int 3)]))))))]
12123  "TARGET_SHMEDIA"
12124  "mmulsum.wq	%2, %3, %0"
12125  [(set_attr "type" "mac_media")])
12126
12127(define_expand "mperm_w"
12128  [(match_operand:V4HI 0 "arith_reg_dest" "=r")
12129   (match_operand:V4HI 1 "arith_reg_operand" "r")
12130   (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
12131  "TARGET_SHMEDIA"
12132  "
12133{
12134  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
12135	     (operands[0], operands[1], operands[2]));
12136  DONE;
12137}")
12138
12139; This use of vec_select isn't exactly correct according to rtl.texi
12140; (because not constant), but it seems a straightforward extension.
12141(define_insn "mperm_w_little"
12142  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12143	(vec_select:V4HI
12144	 (match_operand:V4HI 1 "arith_reg_operand" "r")
12145	 (parallel
12146	  [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
12147			    (const_int 2) (const_int 0))
12148	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
12149	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
12150	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
12151  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
12152  "mperm.w	%1, %N2, %0"
12153  [(set_attr "type" "arith_media")])
12154
12155(define_insn "mperm_w_big"
12156  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12157	(vec_select:V4HI
12158	 (match_operand:V4HI 1 "arith_reg_operand" "r")
12159	 (parallel
12160	  [(zero_extract:QI (not:QI (match_operand:QI 2
12161				     "extend_reg_or_0_operand" "rZ"))
12162			    (const_int 2) (const_int 0))
12163	   (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
12164	   (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
12165	   (zero_extract:QI (not:QI (match_dup 2))
12166			    (const_int 2) (const_int 6))])))]
12167  "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
12168  "mperm.w	%1, %N2, %0"
12169  [(set_attr "type" "arith_media")])
12170
12171(define_insn "mperm_w0"
12172  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12173	(vec_duplicate:V4HI (truncate:HI (match_operand 1
12174					  "trunc_hi_operand" "r"))))]
12175  "TARGET_SHMEDIA"
12176  "mperm.w	%1, r63, %0"
12177  [(set_attr "type" "arith_media")
12178   (set_attr "highpart" "ignore")])
12179
12180(define_expand "msad_ubq"
12181  [(match_operand:DI 0 "arith_reg_dest" "")
12182   (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
12183   (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
12184   (match_operand:DI 3 "arith_reg_operand" "")]
12185  "TARGET_SHMEDIA"
12186  "
12187{
12188  emit_insn (gen_msad_ubq_i (operands[0], operands[3],
12189			     operands[1], operands[2]));
12190  DONE;
12191}")
12192
12193(define_insn "msad_ubq_i"
12194  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12195	(plus:DI
12196	 (plus:DI
12197	  (plus:DI
12198	   (plus:DI
12199	    (match_operand:DI 1 "arith_reg_operand" "0")
12200	    (abs:DI (vec_select:DI
12201		     (minus:V8DI
12202		      (zero_extend:V8DI
12203		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12204		      (zero_extend:V8DI
12205		       (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
12206		     (parallel [(const_int 0)]))))
12207	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12208					      (zero_extend:V8DI (match_dup 3)))
12209				  (parallel [(const_int 1)]))))
12210	  (plus:DI
12211	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12212					      (zero_extend:V8DI (match_dup 3)))
12213				  (parallel [(const_int 2)])))
12214	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12215					      (zero_extend:V8DI (match_dup 3)))
12216				  (parallel [(const_int 3)])))))
12217	 (plus:DI
12218	  (plus:DI
12219	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12220					      (zero_extend:V8DI (match_dup 3)))
12221				  (parallel [(const_int 4)])))
12222	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12223					      (zero_extend:V8DI (match_dup 3)))
12224				  (parallel [(const_int 5)]))))
12225	  (plus:DI
12226	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12227					      (zero_extend:V8DI (match_dup 3)))
12228				  (parallel [(const_int 6)])))
12229	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
12230					      (zero_extend:V8DI (match_dup 3)))
12231				  (parallel [(const_int 7)])))))))]
12232  "TARGET_SHMEDIA"
12233  "msad.ubq	%N2, %N3, %0"
12234  [(set_attr "type" "mac_media")])
12235
12236(define_insn "mshalds_l"
12237  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12238	(ss_truncate:V2SI
12239	 (ashift:V2DI
12240	  (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
12241	  (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12242		  (const_int 31)))))]
12243  "TARGET_SHMEDIA"
12244  "mshalds.l	%1, %2, %0"
12245  [(set_attr "type" "mcmp_media")
12246   (set_attr "highpart" "depend")])
12247
12248(define_insn "mshalds_w"
12249  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12250	(ss_truncate:V4HI
12251	 (ashift:V4SI
12252	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
12253	  (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
12254		  (const_int 15)))))]
12255  "TARGET_SHMEDIA"
12256  "mshalds.w	%1, %2, %0"
12257  [(set_attr "type" "mcmp_media")
12258   (set_attr "highpart" "depend")])
12259
12260(define_insn "ashrv2si3"
12261  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12262	(ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12263		       (match_operand:DI 2 "arith_reg_operand" "r")))]
12264  "TARGET_SHMEDIA"
12265  "mshard.l	%1, %2, %0"
12266  [(set_attr "type" "arith_media")
12267   (set_attr "highpart" "depend")])
12268
12269(define_insn "ashrv4hi3"
12270  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12271	(ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12272		       (match_operand:DI 2 "arith_reg_operand" "r")))]
12273  "TARGET_SHMEDIA"
12274  "mshard.w	%1, %2, %0"
12275  [(set_attr "type" "arith_media")
12276   (set_attr "highpart" "depend")])
12277
12278(define_insn "mshards_q"
12279  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
12280	(ss_truncate:HI
12281	 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
12282		      (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
12283  "TARGET_SHMEDIA"
12284  "mshards.q	%1, %N2, %0"
12285  [(set_attr "type" "mcmp_media")])
12286
12287(define_expand "mshfhi_b"
12288  [(match_operand:V8QI 0 "arith_reg_dest" "")
12289   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12290   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12291  "TARGET_SHMEDIA"
12292  "
12293{
12294  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
12295	     (operands[0], operands[1], operands[2]));
12296  DONE;
12297}")
12298
12299(define_expand "mshflo_b"
12300  [(match_operand:V8QI 0 "arith_reg_dest" "")
12301   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12302   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
12303  "TARGET_SHMEDIA"
12304  "
12305{
12306  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
12307	     (operands[0], operands[1], operands[2]));
12308  DONE;
12309}")
12310
12311(define_insn "mshf4_b"
12312  [(set
12313    (match_operand:V8QI 0 "arith_reg_dest" "=r")
12314    (vec_select:V8QI
12315     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12316		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12317     (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
12318		(const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
12319  "TARGET_SHMEDIA"
12320  "* return (TARGET_LITTLE_ENDIAN
12321	     ? \"mshfhi.b	%N1, %N2, %0\"
12322	     : \"mshflo.b	%N1, %N2, %0\");"
12323  [(set_attr "type" "arith_media")
12324   (set (attr "highpart")
12325	(cond [(eq_attr "endian" "big") (const_string "ignore")]
12326	 (const_string "user")))])
12327
12328(define_insn "mshf0_b"
12329  [(set
12330    (match_operand:V8QI 0 "arith_reg_dest" "=r")
12331    (vec_select:V8QI
12332     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12333		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
12334     (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
12335		(const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
12336  "TARGET_SHMEDIA"
12337  "* return (TARGET_LITTLE_ENDIAN
12338	     ? \"mshflo.b	%N1, %N2, %0\"
12339	     : \"mshfhi.b	%N1, %N2, %0\");"
12340  [(set_attr "type" "arith_media")
12341   (set (attr "highpart")
12342	(cond [(eq_attr "endian" "little") (const_string "ignore")]
12343	 (const_string "user")))])
12344
12345(define_expand "mshfhi_l"
12346  [(match_operand:V2SI 0 "arith_reg_dest" "")
12347   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12348   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12349  "TARGET_SHMEDIA"
12350  "
12351{
12352  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
12353	     (operands[0], operands[1], operands[2]));
12354  DONE;
12355}")
12356
12357(define_expand "mshflo_l"
12358  [(match_operand:V2SI 0 "arith_reg_dest" "")
12359   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12360   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
12361  "TARGET_SHMEDIA"
12362  "
12363{
12364  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
12365	     (operands[0], operands[1], operands[2]));
12366  DONE;
12367}")
12368
12369(define_insn "mshf4_l"
12370  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12371	(vec_select:V2SI
12372	 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12373			  (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12374	 (parallel [(const_int 1) (const_int 3)])))]
12375  "TARGET_SHMEDIA"
12376  "* return (TARGET_LITTLE_ENDIAN
12377	     ? \"mshfhi.l	%N1, %N2, %0\"
12378	     : \"mshflo.l	%N1, %N2, %0\");"
12379  [(set_attr "type" "arith_media")
12380   (set (attr "highpart")
12381	(cond [(eq_attr "endian" "big") (const_string "ignore")]
12382	 (const_string "user")))])
12383
12384(define_insn "mshf0_l"
12385  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12386	(vec_select:V2SI
12387	 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12388			  (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
12389	 (parallel [(const_int 0) (const_int 2)])))]
12390  "TARGET_SHMEDIA"
12391  "* return (TARGET_LITTLE_ENDIAN
12392	     ? \"mshflo.l	%N1, %N2, %0\"
12393	     : \"mshfhi.l	%N1, %N2, %0\");"
12394  [(set_attr "type" "arith_media")
12395   (set (attr "highpart")
12396	(cond [(eq_attr "endian" "little") (const_string "ignore")]
12397	 (const_string "user")))])
12398
12399(define_expand "mshfhi_w"
12400  [(match_operand:V4HI 0 "arith_reg_dest" "")
12401   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12402   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12403  "TARGET_SHMEDIA"
12404  "
12405{
12406  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
12407	     (operands[0], operands[1], operands[2]));
12408  DONE;
12409}")
12410
12411(define_expand "mshflo_w"
12412  [(match_operand:V4HI 0 "arith_reg_dest" "")
12413   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12414   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
12415  "TARGET_SHMEDIA"
12416  "
12417{
12418  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
12419	     (operands[0], operands[1], operands[2]));
12420  DONE;
12421}")
12422
12423(define_insn "mshf4_w"
12424  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12425	(vec_select:V4HI
12426	 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12427			  (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12428	 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
12429  "TARGET_SHMEDIA"
12430  "* return (TARGET_LITTLE_ENDIAN
12431	     ? \"mshfhi.w	%N1, %N2, %0\"
12432	     : \"mshflo.w	%N1, %N2, %0\");"
12433  [(set_attr "type" "arith_media")
12434   (set (attr "highpart")
12435	(cond [(eq_attr "endian" "big") (const_string "ignore")]
12436	 (const_string "user")))])
12437
12438(define_insn "mshf0_w"
12439  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12440	(vec_select:V4HI
12441	 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12442			  (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
12443	 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
12444  "TARGET_SHMEDIA"
12445  "* return (TARGET_LITTLE_ENDIAN
12446	     ? \"mshflo.w	%N1, %N2, %0\"
12447	     : \"mshfhi.w	%N1, %N2, %0\");"
12448  [(set_attr "type" "arith_media")
12449   (set (attr "highpart")
12450	(cond [(eq_attr "endian" "little") (const_string "ignore")]
12451	 (const_string "user")))])
12452
12453(define_insn "mshflo_w_x"
12454  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12455	(vec_select:V4HI
12456	 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
12457			  (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
12458	 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
12459  "TARGET_SHMEDIA"
12460  "mshflo.w	%N1, %N2, %0"
12461  [(set_attr "type" "arith_media")
12462   (set_attr "highpart" "ignore")])
12463
12464/* These are useful to expand ANDs and as combiner patterns.  */
12465(define_insn_and_split "mshfhi_l_di"
12466  [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
12467	(ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
12468                             (const_int 32))
12469		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
12470			(const_int -4294967296))))]
12471  "TARGET_SHMEDIA"
12472  "@
12473	mshfhi.l	%N1, %N2, %0
12474	#"
12475  "TARGET_SHMEDIA && reload_completed
12476   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12477  [(set (match_dup 3) (match_dup 4))
12478   (set (match_dup 5) (match_dup 6))]
12479  "
12480{
12481  operands[3] = gen_lowpart (SImode, operands[0]);
12482  operands[4] = gen_highpart (SImode, operands[1]);
12483  operands[5] = gen_highpart (SImode, operands[0]);
12484  operands[6] = gen_highpart (SImode, operands[2]);
12485}"
12486  [(set_attr "type" "arith_media")])
12487
12488(define_insn "*mshfhi_l_di_rev"
12489  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12490	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12491			(const_int -4294967296))
12492		(lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12493                             (const_int 32))))]
12494  "TARGET_SHMEDIA"
12495  "mshfhi.l	%N2, %N1, %0"
12496  [(set_attr "type" "arith_media")])
12497
12498(define_split
12499  [(set (match_operand:DI 0 "arith_reg_dest" "")
12500	(ior:DI (zero_extend:DI (match_operand:SI 1
12501					      "extend_reg_or_0_operand" ""))
12502		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
12503			(const_int -4294967296))))
12504   (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
12505  "TARGET_SHMEDIA"
12506  [(const_int 0)]
12507  "
12508{
12509  emit_insn (gen_ashldi3_media (operands[3],
12510				simplify_gen_subreg (DImode, operands[1],
12511						     SImode, 0),
12512				GEN_INT (32)));
12513  emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
12514  DONE;
12515}")
12516
12517(define_insn "mshflo_l_di"
12518  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12519	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12520			(const_int 4294967295))
12521		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12522                           (const_int 32))))]
12523
12524  "TARGET_SHMEDIA"
12525  "mshflo.l	%N1, %N2, %0"
12526  [(set_attr "type" "arith_media")
12527   (set_attr "highpart" "ignore")])
12528
12529(define_insn "*mshflo_l_di_rev"
12530  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12531	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12532                           (const_int 32))
12533		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12534			(const_int 4294967295))))]
12535
12536  "TARGET_SHMEDIA"
12537  "mshflo.l	%N2, %N1, %0"
12538  [(set_attr "type" "arith_media")
12539   (set_attr "highpart" "ignore")])
12540
12541;; Combiner pattern for trampoline initialization.
12542(define_insn_and_split "*double_shori"
12543  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12544	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
12545                           (const_int 32))
12546		(match_operand:DI 2 "const_int_operand" "n")))]
12547  "TARGET_SHMEDIA
12548   && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
12549  "#"
12550  "rtx_equal_p (operands[0], operands[1])"
12551  [(const_int 0)]
12552  "
12553{
12554  HOST_WIDE_INT v = INTVAL (operands[2]);
12555
12556  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
12557  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
12558  DONE;
12559}"
12560  [(set_attr "highpart" "ignore")])
12561
12562
12563(define_insn "*mshflo_l_di_x"
12564  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12565	(ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
12566				 "rZ"))
12567		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
12568                           (const_int 32))))]
12569
12570  "TARGET_SHMEDIA"
12571  "mshflo.l	%N1, %N2, %0"
12572  [(set_attr "type" "arith_media")
12573   (set_attr "highpart" "ignore")])
12574
12575(define_insn_and_split "concat_v2sf"
12576  [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
12577;;	(vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
12578	(vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
12579			 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
12580
12581  "TARGET_SHMEDIA"
12582  "@
12583	mshflo.l	%N1, %N2, %0
12584	#
12585	#"
12586  "TARGET_SHMEDIA && reload_completed
12587   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
12588  [(set (match_dup 3) (match_dup 1))
12589   (set (match_dup 4) (match_dup 2))]
12590  "
12591{
12592  operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
12593  operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
12594}"
12595  [(set_attr "type" "arith_media")
12596   (set_attr "highpart" "ignore")])
12597
12598(define_insn "*mshflo_l_di_x_rev"
12599  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12600	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
12601                           (const_int 32))
12602		(zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
12603
12604  "TARGET_SHMEDIA"
12605  "mshflo.l	%N2, %N1, %0"
12606  [(set_attr "type" "arith_media")
12607   (set_attr "highpart" "ignore")])
12608
12609(define_insn "ashlv2si3"
12610  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12611	(ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12612		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12613  "TARGET_SHMEDIA"
12614  "mshlld.l	%1, %2, %0"
12615  [(set_attr "type" "arith_media")
12616   (set_attr "highpart" "depend")])
12617
12618(define_split
12619  [(set (match_operand 0 "any_register_operand" "")
12620	(match_operator 3 "shift_operator"
12621	  [(match_operand 1 "any_register_operand" "")
12622	   (match_operand 2 "shift_count_reg_operand" "")]))]
12623  "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
12624  [(set (match_dup 0) (match_dup 3))]
12625  "
12626{
12627  rtx count = operands[2];
12628  enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
12629
12630  while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
12631	 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
12632	 || GET_CODE (count) == TRUNCATE)
12633    count = XEXP (count, 0);
12634  inner_mode = GET_MODE (count);
12635  count = simplify_gen_subreg (outer_mode, count, inner_mode,
12636			       subreg_lowpart_offset (outer_mode, inner_mode));
12637  operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
12638				operands[1], count);
12639}")
12640
12641(define_insn "ashlv4hi3"
12642  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12643	(ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12644		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12645  "TARGET_SHMEDIA"
12646  "mshlld.w	%1, %2, %0"
12647  [(set_attr "type" "arith_media")
12648   (set_attr "highpart" "depend")])
12649
12650(define_insn "lshrv2si3"
12651  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12652	(lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
12653		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12654  "TARGET_SHMEDIA"
12655  "mshlrd.l	%1, %2, %0"
12656  [(set_attr "type" "arith_media")
12657   (set_attr "highpart" "depend")])
12658
12659(define_insn "lshrv4hi3"
12660  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12661	(lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
12662		       (match_operand:DI 2 "shift_count_reg_operand" "r")))]
12663  "TARGET_SHMEDIA"
12664  "mshlrd.w	%1, %2, %0"
12665  [(set_attr "type" "arith_media")
12666   (set_attr "highpart" "depend")])
12667
12668(define_insn "subv2si3"
12669  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12670	(minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12671		    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12672  "TARGET_SHMEDIA"
12673  "msub.l	%N1, %2, %0"
12674  [(set_attr "type" "arith_media")
12675   (set_attr "highpart" "depend")])
12676
12677(define_insn "subv4hi3"
12678  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12679	(minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12680		    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12681  "TARGET_SHMEDIA"
12682  "msub.w	%N1, %2, %0"
12683  [(set_attr "type" "arith_media")
12684   (set_attr "highpart" "depend")])
12685
12686(define_insn_and_split "subv2hi3"
12687  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
12688	(minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
12689		   (match_operand:V2HI 2 "arith_reg_operand" "r")))]
12690  "TARGET_SHMEDIA"
12691  "#"
12692  "TARGET_SHMEDIA"
12693  [(const_int 0)]
12694  "
12695{
12696  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
12697  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
12698  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
12699  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
12700  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
12701
12702  emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
12703  emit_insn (gen_truncdisi2 (si_dst, di_dst));
12704  DONE;
12705}"
12706  [(set_attr "highpart" "must_split")])
12707
12708(define_insn "sssubv2si3"
12709  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
12710	(ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
12711		       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
12712  "TARGET_SHMEDIA"
12713  "msubs.l	%N1, %2, %0"
12714  [(set_attr "type" "mcmp_media")
12715   (set_attr "highpart" "depend")])
12716
12717(define_insn "ussubv8qi3"
12718  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
12719	(us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
12720		       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
12721  "TARGET_SHMEDIA"
12722  "msubs.ub	%N1, %2, %0"
12723  [(set_attr "type" "mcmp_media")
12724   (set_attr "highpart" "depend")])
12725
12726(define_insn "sssubv4hi3"
12727  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
12728	(ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
12729		       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
12730  "TARGET_SHMEDIA"
12731  "msubs.w	%N1, %2, %0"
12732  [(set_attr "type" "mcmp_media")
12733   (set_attr "highpart" "depend")])
12734
12735;; Floating Point Intrinsics
12736
12737(define_insn "fcosa_s"
12738  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12739	(unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12740		   UNSPEC_FCOSA))]
12741  "TARGET_SHMEDIA"
12742  "fcosa.s	%1, %0"
12743  [(set_attr "type" "atrans_media")])
12744
12745(define_insn "fsina_s"
12746  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12747	(unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
12748		   UNSPEC_FSINA))]
12749  "TARGET_SHMEDIA"
12750  "fsina.s	%1, %0"
12751  [(set_attr "type" "atrans_media")])
12752
12753(define_insn "fipr"
12754  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12755	(plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
12756						    "fp_arith_reg_operand" "f")
12757						   (match_operand:V4SF 2
12758						    "fp_arith_reg_operand" "f"))
12759					 (parallel [(const_int 0)]))
12760			  (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12761					 (parallel [(const_int 1)])))
12762		 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12763					 (parallel [(const_int 2)]))
12764			  (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
12765					 (parallel [(const_int 3)])))))]
12766  "TARGET_SHMEDIA"
12767  "fipr.s	%1, %2, %0"
12768  [(set_attr "type" "fparith_media")])
12769
12770(define_insn "fsrra_s"
12771  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12772	(unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
12773		   UNSPEC_FSRRA))]
12774  "TARGET_SHMEDIA"
12775  "fsrra.s	%1, %0"
12776  [(set_attr "type" "atrans_media")])
12777
12778(define_insn "ftrv"
12779  [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
12780	(plus:V4SF
12781	 (plus:V4SF
12782	  (mult:V4SF
12783	   (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
12784			    (parallel [(const_int 0) (const_int 5)
12785				       (const_int 10) (const_int 15)]))
12786	   (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
12787	  (mult:V4SF
12788	   (vec_select:V4SF (match_dup 1)
12789			    (parallel [(const_int 4) (const_int 9)
12790				       (const_int 14) (const_int 3)]))
12791	   (vec_select:V4SF (match_dup 2)
12792			    (parallel [(const_int 1) (const_int 2)
12793				       (const_int 3) (const_int 0)]))))
12794	 (plus:V4SF
12795	  (mult:V4SF
12796	   (vec_select:V4SF (match_dup 1)
12797			    (parallel [(const_int 8) (const_int 13)
12798				       (const_int 2) (const_int 7)]))
12799	   (vec_select:V4SF (match_dup 2)
12800			    (parallel [(const_int 2) (const_int 3)
12801				       (const_int 0) (const_int 1)])))
12802	  (mult:V4SF
12803	   (vec_select:V4SF (match_dup 1)
12804			    (parallel [(const_int 12) (const_int 1)
12805				       (const_int 6) (const_int 11)]))
12806	   (vec_select:V4SF (match_dup 2)
12807			    (parallel [(const_int 3) (const_int 0)
12808				       (const_int 1) (const_int 2)]))))))]
12809  "TARGET_SHMEDIA"
12810  "ftrv.s %1, %2, %0"
12811  [(set_attr "type" "fparith_media")])
12812
12813(define_insn "ldhi_l"
12814  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12815	(zero_extract:SI
12816	 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12817				  (const_int 3))
12818			  (const_int -3)))
12819	 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
12820	 (const_int 0)))]
12821  "TARGET_SHMEDIA32"
12822  "ldhi.l	%U1, %0"
12823  [(set_attr "type" "load_media")])
12824
12825(define_insn "ldhi_q"
12826  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12827	(zero_extract:DI
12828	 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
12829				  (const_int 7))
12830			  (const_int -7)))
12831	 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
12832	 (const_int 0)))]
12833  "TARGET_SHMEDIA32"
12834  "ldhi.q	%U1, %0"
12835  [(set_attr "type" "load_media")])
12836
12837(define_insn_and_split "*ldhi_q_comb0"
12838  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12839	(zero_extract:DI
12840	 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12841					    "register_operand" "r")
12842					   (match_operand:SI 2
12843					    "ua_offset" "I06"))
12844				  (const_int 7))
12845			  (const_int -7)))
12846	 (plus:SI (and:SI (match_dup 1) (const_int 7))
12847		  (const_int 1))
12848	 (const_int 0)))]
12849  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12850  "#"
12851  ""
12852  [(pc)]
12853  "emit_insn (gen_ldhi_q (operands[0],
12854			  gen_rtx_PLUS (SImode, operands[1], operands[2])));
12855   DONE;")
12856
12857
12858(define_insn_and_split "*ldhi_q_comb1"
12859  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12860	(zero_extract:DI
12861	 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
12862					    "register_operand" "r")
12863					   (match_operand:SI 2
12864					    "ua_offset" "I06"))
12865				  (const_int 7))
12866			  (const_int -7)))
12867	 (plus:SI (and:SI (plus:SI (match_dup 1)  (match_operand:SI 3
12868						   "ua_offset" "I06"))
12869			  (const_int 7))
12870		  (const_int 1))
12871	 (const_int 0)))]
12872  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12873   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12874  "#"
12875  ""
12876  [(pc)]
12877  "emit_insn (gen_ldhi_q (operands[0],
12878			  gen_rtx_PLUS (SImode, operands[1], operands[2])));
12879   DONE;")
12880
12881
12882(define_insn "ldlo_l"
12883  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12884	(zero_extract:SI
12885	 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12886			 (const_int -4)))
12887	 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
12888	 (and:SI (match_dup 1) (const_int 3))))]
12889  "TARGET_SHMEDIA32"
12890  "ldlo.l	%U1, %0"
12891  [(set_attr "type" "load_media")])
12892
12893(define_insn "ldlo_q"
12894  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12895	(zero_extract:DI
12896	 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
12897			 (const_int -8)))
12898	 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12899	 (and:SI (match_dup 1) (const_int 7))))]
12900  "TARGET_SHMEDIA32"
12901  "ldlo.q	%U1, %0"
12902  [(set_attr "type" "load_media")])
12903
12904(define_insn_and_split "*ldlo_q_comb0"
12905  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12906	(zero_extract:DI
12907	 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12908				  (match_operand:SI 2 "ua_offset" "I06"))
12909			 (const_int -8)))
12910	 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
12911	 (and:SI (match_dup 1) (const_int 7))))]
12912  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
12913  "#"
12914  ""
12915  [(pc)]
12916  "emit_insn (gen_ldlo_q (operands[0],
12917			  gen_rtx_PLUS (SImode, operands[1], operands[2])));
12918   DONE;")
12919
12920(define_insn_and_split "*ldlo_q_comb1"
12921  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
12922	(zero_extract:DI
12923	 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
12924				  (match_operand:SI 2 "ua_offset" "I06"))
12925			 (const_int -8)))
12926	 (minus:SI (const_int 8)
12927		   (and:SI (plus:SI (match_dup 1)
12928				    (match_operand:SI 3 "ua_offset" "I06"))
12929			   (const_int 7)))
12930	 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
12931  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
12932   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
12933  "#"
12934  ""
12935  [(pc)]
12936  "emit_insn (gen_ldlo_q (operands[0],
12937			  gen_rtx_PLUS (SImode, operands[1], operands[2])));
12938   DONE;")
12939
12940(define_insn "sthi_l"
12941  [(set (zero_extract:SI
12942	 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
12943				  (const_int 3))
12944			  (const_int -3)))
12945	 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
12946	 (const_int 0))
12947	(match_operand:SI 1 "arith_reg_operand" "r"))]
12948  "TARGET_SHMEDIA32"
12949  "sthi.l	%U0, %1"
12950  [(set_attr "type" "ustore_media")])
12951
12952;; All unaligned stores are considered to be 'narrow' because they typically
12953;; operate on less that a quadword, and when they operate on a full quadword,
12954;; the vanilla store high / store low sequence will cause a stall if not
12955;; scheduled apart.
12956(define_insn "sthi_q"
12957  [(set (zero_extract:DI
12958	 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
12959				  (const_int 7))
12960			  (const_int -7)))
12961	 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
12962	 (const_int 0))
12963	(match_operand:DI 1 "arith_reg_operand" "r"))]
12964  "TARGET_SHMEDIA32"
12965  "sthi.q	%U0, %1"
12966  [(set_attr "type" "ustore_media")])
12967
12968(define_insn_and_split "*sthi_q_comb0"
12969  [(set (zero_extract:DI
12970	 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
12971					    "register_operand" "r")
12972					   (match_operand:SI 1 "ua_offset"
12973					    "I06"))
12974				  (const_int 7))
12975			  (const_int -7)))
12976	 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
12977	 (const_int 0))
12978	(match_operand:DI 2 "arith_reg_operand" "r"))]
12979  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
12980  "#"
12981  ""
12982  [(pc)]
12983  "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
12984			  operands[2]));
12985   DONE;")
12986
12987(define_insn_and_split "*sthi_q_comb1"
12988  [(set (zero_extract:DI
12989	 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
12990					    "register_operand" "r")
12991					   (match_operand:SI 1 "ua_offset"
12992					    "I06"))
12993				  (const_int 7))
12994			  (const_int -7)))
12995	 (plus:SI (and:SI (plus:SI (match_dup 0)
12996				   (match_operand:SI 2 "ua_offset" "I06"))
12997			  (const_int 7))
12998		  (const_int 1))
12999	 (const_int 0))
13000	(match_operand:DI 3 "arith_reg_operand" "r"))]
13001  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
13002   && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13003  "#"
13004  ""
13005  [(pc)]
13006  "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13007			  operands[3]));
13008   DONE;")
13009
13010;; This is highpart user because the address is used as full 64 bit.
13011(define_insn "stlo_l"
13012  [(set (zero_extract:SI
13013	 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13014			 (const_int -4)))
13015	 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
13016	 (and:SI (match_dup 0) (const_int 3)))
13017	(match_operand:SI 1 "arith_reg_operand" "r"))]
13018  "TARGET_SHMEDIA32"
13019  "stlo.l	%U0, %1"
13020  [(set_attr "type" "ustore_media")])
13021
13022(define_insn "stlo_q"
13023  [(set (zero_extract:DI
13024	 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
13025			 (const_int -8)))
13026	 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13027	 (and:SI (match_dup 0) (const_int 7)))
13028	(match_operand:DI 1 "arith_reg_operand" "r"))]
13029  "TARGET_SHMEDIA32"
13030  "stlo.q	%U0, %1"
13031  [(set_attr "type" "ustore_media")])
13032
13033(define_insn_and_split "*stlo_q_comb0"
13034  [(set (zero_extract:DI
13035	 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13036				  (match_operand:SI 1 "ua_offset" "I06"))
13037			 (const_int -8)))
13038	 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
13039	 (and:SI (match_dup 0) (const_int 7)))
13040	(match_operand:DI 2 "arith_reg_operand" "r"))]
13041  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
13042  "#"
13043  ""
13044  [(pc)]
13045  "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13046			  operands[2]));
13047   DONE;")
13048
13049(define_insn_and_split "*stlo_q_comb1"
13050  [(set (zero_extract:DI
13051	 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
13052				  (match_operand:SI 1 "ua_offset" "I06"))
13053			 (const_int -8)))
13054	 (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
13055						  (match_operand:SI 2
13056						   "ua_offset" "I06"))
13057					 (const_int 7)))
13058	 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
13059	(match_operand:DI 3 "arith_reg_operand" "r"))]
13060  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
13061  "#"
13062  ""
13063  [(pc)]
13064  "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
13065			  operands[3]));
13066   DONE;")
13067
13068(define_insn "ldhi_l64"
13069  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13070	(zero_extract:SI
13071	 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13072				  (const_int 3))
13073			  (const_int -3)))
13074	 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
13075	 (const_int 0)))]
13076  "TARGET_SHMEDIA64"
13077  "ldhi.l	%U1, %0"
13078  [(set_attr "type" "load_media")])
13079
13080(define_insn "ldhi_q64"
13081  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13082	(zero_extract:DI
13083	 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
13084				  (const_int 7))
13085			  (const_int -7)))
13086	 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
13087	 (const_int 0)))]
13088  "TARGET_SHMEDIA64"
13089  "ldhi.q	%U1, %0"
13090  [(set_attr "type" "load_media")])
13091
13092(define_insn "ldlo_l64"
13093  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13094	(zero_extract:SI
13095	 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13096			 (const_int -4)))
13097	 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
13098	 (and:DI (match_dup 1) (const_int 3))))]
13099  "TARGET_SHMEDIA64"
13100  "ldlo.l	%U1, %0"
13101  [(set_attr "type" "load_media")])
13102
13103(define_insn "ldlo_q64"
13104  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13105	(zero_extract:DI
13106	 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
13107			 (const_int -8)))
13108	 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
13109	 (and:DI (match_dup 1) (const_int 7))))]
13110  "TARGET_SHMEDIA64"
13111  "ldlo.q	%U1, %0"
13112  [(set_attr "type" "load_media")])
13113
13114(define_insn "sthi_l64"
13115  [(set (zero_extract:SI
13116	 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13117				  (const_int 3))
13118			  (const_int -3)))
13119	 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
13120	 (const_int 0))
13121	(match_operand:SI 1 "arith_reg_operand" "r"))]
13122  "TARGET_SHMEDIA64"
13123  "sthi.l	%U0, %1"
13124  [(set_attr "type" "ustore_media")])
13125
13126(define_insn "sthi_q64"
13127  [(set (zero_extract:DI
13128	 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
13129				  (const_int 7))
13130			  (const_int -7)))
13131	 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
13132	 (const_int 0))
13133	(match_operand:DI 1 "arith_reg_operand" "r"))]
13134  "TARGET_SHMEDIA64"
13135  "sthi.q	%U0, %1"
13136  [(set_attr "type" "ustore_media")])
13137
13138(define_insn "stlo_l64"
13139  [(set (zero_extract:SI
13140	 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13141			 (const_int -4)))
13142	 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
13143	 (and:DI (match_dup 0) (const_int 3)))
13144	(match_operand:SI 1 "arith_reg_operand" "r"))]
13145  "TARGET_SHMEDIA64"
13146  "stlo.l	%U0, %1"
13147  [(set_attr "type" "ustore_media")])
13148
13149(define_insn "stlo_q64"
13150  [(set (zero_extract:DI
13151	 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
13152			 (const_int -8)))
13153	 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
13154	 (and:DI (match_dup 0) (const_int 7)))
13155	(match_operand:DI 1 "arith_reg_operand" "r"))]
13156  "TARGET_SHMEDIA64"
13157  "stlo.q	%U0, %1"
13158  [(set_attr "type" "ustore_media")])
13159
13160(define_insn "nsb"
13161  [(set (match_operand:QI 0 "arith_reg_dest" "=r")
13162	(unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13163		   UNSPEC_NSB))]
13164  "TARGET_SHMEDIA"
13165  "nsb	%1, %0"
13166  [(set_attr "type" "arith_media")])
13167
13168(define_insn "nsbsi"
13169  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
13170	(zero_extend:SI
13171	 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13172		    UNSPEC_NSB)))]
13173  "TARGET_SHMEDIA"
13174  "nsb	%1, %0"
13175  [(set_attr "type" "arith_media")])
13176
13177(define_insn "nsbdi"
13178  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13179	(zero_extend:DI
13180	 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
13181		    UNSPEC_NSB)))]
13182  "TARGET_SHMEDIA"
13183  "nsb	%1, %0"
13184  [(set_attr "type" "arith_media")])
13185
13186(define_expand "ffsdi2"
13187  [(set (match_operand:DI 0 "arith_reg_dest" "")
13188	(ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
13189  "TARGET_SHMEDIA"
13190  "
13191{
13192  rtx scratch = gen_reg_rtx (DImode);
13193  rtx last;
13194
13195  emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
13196  emit_insn (gen_xordi3 (scratch, operands[1], scratch));
13197  emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
13198  emit_insn (gen_nsbdi (scratch, scratch));
13199  emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
13200  emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
13201  last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
13202  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
13203
13204  DONE;
13205}")
13206
13207(define_expand "ffssi2"
13208  [(set (match_operand:SI 0 "arith_reg_dest" "")
13209	(ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
13210  "TARGET_SHMEDIA"
13211  "
13212{
13213  rtx scratch = gen_reg_rtx (SImode);
13214  rtx discratch = gen_reg_rtx (DImode);
13215  rtx last;
13216
13217  emit_insn (gen_adddi3 (discratch,
13218			 simplify_gen_subreg (DImode, operands[1], SImode, 0),
13219			 constm1_rtx));
13220  emit_insn (gen_andcdi3 (discratch,
13221			  simplify_gen_subreg (DImode, operands[1], SImode, 0),
13222			  discratch));
13223  emit_insn (gen_nsbsi (scratch, discratch));
13224  last = emit_insn (gen_subsi3 (operands[0],
13225				force_reg (SImode, GEN_INT (63)), scratch));
13226  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
13227
13228  DONE;
13229}")
13230
13231(define_insn "byterev"
13232  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13233	(vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
13234			 (parallel [(const_int 7) (const_int 6) (const_int 5)
13235				    (const_int 4) (const_int 3) (const_int 2)
13236				    (const_int 1) (const_int 0)])))]
13237  "TARGET_SHMEDIA"
13238  "byterev	%1, %0"
13239  [(set_attr "type" "arith_media")])
13240
13241(define_insn "*prefetch_media"
13242  [(prefetch (match_operand:QI 0 "address_operand" "p")
13243             (match_operand:SI 1 "const_int_operand" "n")
13244             (match_operand:SI 2 "const_int_operand" "n"))]
13245  "TARGET_SHMEDIA"
13246  "*
13247{
13248  operands[0] = gen_rtx_MEM (QImode, operands[0]);
13249  output_asm_insn (\"ld%M0.b    %m0,r63\", operands);
13250  return \"\";
13251}"
13252  [(set_attr "type" "other")])
13253
13254(define_insn "*prefetch_i4"
13255  [(prefetch (match_operand:SI 0 "register_operand" "r")
13256             (match_operand:SI 1 "const_int_operand" "n")
13257             (match_operand:SI 2 "const_int_operand" "n"))]
13258  "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && !TARGET_VXWORKS_RTP"
13259  "*
13260{
13261  return \"pref @%0\";
13262}"
13263  [(set_attr "type" "other")])
13264
13265;; In user mode, the "pref" instruction will raise a RADDERR exception
13266;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
13267;; implementation of __builtin_prefetch for VxWorks RTPs.
13268(define_expand "prefetch"
13269  [(prefetch (match_operand 0 "address_operand" "p")
13270             (match_operand:SI 1 "const_int_operand" "n")
13271             (match_operand:SI 2 "const_int_operand" "n"))]
13272  "TARGET_SH2A || ((TARGET_HARD_SH4 || TARGET_SH5)
13273   && (TARGET_SHMEDIA || !TARGET_VXWORKS_RTP))"
13274  "
13275{
13276  if (GET_MODE (operands[0]) != Pmode
13277      || !CONST_INT_P (operands[1])
13278      || !CONST_INT_P (operands[2]))
13279    FAIL;
13280  if (! TARGET_SHMEDIA)
13281    operands[0] = force_reg (Pmode, operands[0]);
13282}")
13283
13284(define_insn "prefetch_m2a"
13285  [(prefetch (match_operand:SI 0 "register_operand" "r")
13286	     (match_operand:SI 1 "const_int_operand" "n")
13287	     (match_operand:SI 2 "const_int_operand" "n"))]
13288  "TARGET_SH2A"
13289  "pref\\t@%0"
13290  [(set_attr "type" "other")])
13291
13292(define_insn "alloco_i"
13293  [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
13294	(unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
13295  "TARGET_SHMEDIA32"
13296  "*
13297{
13298  rtx xops[2];
13299
13300  if (GET_CODE (operands[0]) == PLUS)
13301    {
13302      xops[0] = XEXP (operands[0], 0);
13303      xops[1] = XEXP (operands[0], 1);
13304    }
13305  else
13306    {
13307      xops[0] = operands[0];
13308      xops[1] = const0_rtx;
13309    }
13310  output_asm_insn (\"alloco   %0, %1\", xops);
13311  return \"\";
13312}"
13313  [(set_attr "type" "other")])
13314
13315(define_split
13316  [(set (match_operand 0 "any_register_operand" "")
13317	(match_operand 1 "" ""))]
13318  "TARGET_SHMEDIA && reload_completed"
13319  [(set (match_dup 0) (match_dup 1))]
13320  "
13321{
13322  int n_changes = 0;
13323
13324  for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
13325  if (!n_changes)
13326    FAIL;
13327}")
13328
13329; Stack Protector Patterns
13330
13331(define_expand "stack_protect_set"
13332  [(set (match_operand 0 "memory_operand" "")
13333	(match_operand 1 "memory_operand" ""))]
13334  ""
13335{
13336  if (TARGET_SHMEDIA)
13337    {
13338      if (TARGET_SHMEDIA64)
13339	emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
13340      else
13341	emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
13342    }
13343  else
13344    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
13345
13346  DONE;
13347})
13348
13349(define_insn "stack_protect_set_si"
13350  [(set (match_operand:SI 0 "memory_operand" "=m")
13351        (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13352   (set (match_scratch:SI 2 "=&r") (const_int 0))]
13353  "!TARGET_SHMEDIA"
13354  "mov.l\t%1, %2\;mov.l\t%2, %0\;mov\t#0, %2"
13355  [(set_attr "type" "other")
13356   (set_attr "length" "6")])
13357
13358(define_insn "stack_protect_set_si_media"
13359  [(set (match_operand:SI 0 "memory_operand" "=m")
13360        (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13361   (set (match_scratch:SI 2 "=&r") (const_int 0))]
13362  "TARGET_SHMEDIA"
13363  "ld%M1.l\t%m1, %2\;st%M0.l\t%m0, %2\;movi\t0, %2"
13364  [(set_attr "type" "other")
13365   (set_attr "length" "12")])
13366
13367(define_insn "stack_protect_set_di_media"
13368  [(set (match_operand:DI 0 "memory_operand" "=m")
13369        (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
13370   (set (match_scratch:DI 2 "=&r") (const_int 0))]
13371  "TARGET_SHMEDIA64"
13372  "ld%M1.q\t%m1, %2\;st%M0.q\t%m0, %2\;movi\t0, %2"
13373  [(set_attr "type" "other")
13374   (set_attr "length" "12")])
13375
13376(define_expand "stack_protect_test"
13377  [(match_operand 0 "memory_operand" "")
13378   (match_operand 1 "memory_operand" "")
13379   (match_operand 2 "" "")]
13380  ""
13381{
13382  if (TARGET_SHMEDIA)
13383    {
13384      rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
13385      rtx test;
13386
13387      test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
13388      if (TARGET_SHMEDIA64)
13389	{
13390	  emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
13391						      operands[1]));
13392          emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
13393	}
13394      else
13395	{
13396	  emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
13397						      operands[1]));
13398          emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
13399	}
13400    }
13401  else
13402    {
13403      emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
13404      emit_jump_insn (gen_branch_true (operands[2]));
13405    }
13406
13407  DONE;
13408})
13409
13410(define_insn "stack_protect_test_si"
13411  [(set (reg:SI T_REG)
13412        (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
13413		    (match_operand:SI 1 "memory_operand" "m")]
13414		   UNSPEC_SP_TEST))
13415  (set (match_scratch:SI 2 "=&r") (const_int 0))
13416  (set (match_scratch:SI 3 "=&r") (const_int 0))]
13417  "!TARGET_SHMEDIA"
13418  "mov.l\t%0, %2\;mov.l\t%1, %3\;cmp/eq\t%2, %3\;mov\t#0, %2\;mov\t#0, %3"
13419  [(set_attr "type" "other")
13420   (set_attr "length" "10")])
13421
13422(define_insn "stack_protect_test_si_media"
13423  [(set (match_operand:SI 0 "register_operand" "=&r")
13424        (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
13425		    (match_operand:SI 2 "memory_operand" "m")]
13426		   UNSPEC_SP_TEST))
13427  (set (match_scratch:SI 3 "=&r") (const_int 0))]
13428  "TARGET_SHMEDIA"
13429  "ld%M1.l\t%m1, %0\;ld%M2.l\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13430  [(set_attr "type" "other")
13431   (set_attr "length" "16")])
13432
13433(define_insn "stack_protect_test_di_media"
13434  [(set (match_operand:DI 0 "register_operand" "=&r")
13435        (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
13436		    (match_operand:DI 2 "memory_operand" "m")]
13437		   UNSPEC_SP_TEST))
13438  (set (match_scratch:DI 3 "=&r") (const_int 0))]
13439  "TARGET_SHMEDIA64"
13440  "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
13441  [(set_attr "type" "other")
13442   (set_attr "length" "16")])
13443