sh.md revision 1.1.1.2
1;;- Machine description for Renesas / SuperH SH.
2;;  Copyright (C) 1993-2013 Free Software Foundation, Inc.
3;;  Contributed by Steve Chamberlain (sac@cygnus.com).
4;;  Improved by Jim Wilson (wilson@cygnus.com).
5
6;; This file is part of GCC.
7
8;; GCC is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation; either version 3, or (at your option)
11;; any later version.
12
13;; GCC is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with GCC; see the file COPYING3.  If not see
20;; <http://www.gnu.org/licenses/>.
21
22
23;; ??? Should prepend a * to all pattern names which are not used.
24;; This will make the compiler smaller, and rebuilds after changes faster.
25
26;; ??? Should be enhanced to include support for many more GNU superoptimizer
27;; sequences.  Especially the sequences for arithmetic right shifts.
28
29;; ??? Should check all DImode patterns for consistency and usefulness.
30
31;; ??? The MAC.W and MAC.L instructions are not supported.  There is no
32;; way to generate them.
33
34;; ??? The cmp/str instruction is not supported.  Perhaps it can be used
35;; for a str* inline function.
36
37;; BSR is not generated by the compiler proper, but when relaxing, it
38;; generates .uses pseudo-ops that allow linker relaxation to create
39;; BSR.  This is actually implemented in bfd/{coff,elf32}-sh.c
40
41;; Special constraints for SH machine description:
42;;
43;;    t -- T
44;;    x -- mac
45;;    l -- pr
46;;    z -- r0
47;;
48;; Special formats used for outputting SH instructions:
49;;
50;;   %.  --  print a .s if insn needs delay slot
51;;   %@  --  print rte/rts if is/isn't an interrupt function
52;;   %#  --  output a nop if there is nothing to put in the delay slot
53;;   %O  --  print a constant without the #
54;;   %R  --  print the lsw reg of a double
55;;   %S  --  print the msw reg of a double
56;;   %T  --  print next word of a double REG or MEM
57;;
58;; Special predicates:
59;;
60;;  arith_operand          -- operand is valid source for arithmetic op
61;;  arith_reg_operand      -- operand is valid register for arithmetic op
62;;  general_movdst_operand -- operand is valid move destination
63;;  general_movsrc_operand -- operand is valid move source
64;;  logical_operand        -- operand is valid source for logical op
65
66;; -------------------------------------------------------------------------
67;; Constants
68;; -------------------------------------------------------------------------
69
70(define_constants [
71  (AP_REG	145)
72  (PR_REG	146)
73  (T_REG	147)
74  (GBR_REG	144)
75  (MACH_REG	148)
76  (MACL_REG	149)
77  (FPUL_REG	150)
78  (RAP_REG	152)
79
80  (FPSCR_REG	151)
81
82  (PIC_REG	12)
83  (FP_REG	14)
84  (SP_REG	15)
85
86  (PR_MEDIA_REG	18)
87  (T_MEDIA_REG	19)
88
89  (R0_REG	0)
90  (R1_REG	1)
91  (R2_REG	2)
92  (R3_REG	3)
93  (R4_REG	4)
94  (R5_REG	5)
95  (R6_REG	6)
96  (R7_REG	7)
97  (R8_REG	8)
98  (R9_REG	9)
99  (R10_REG	10)
100  (R20_REG	20)
101  (R21_REG	21)
102  (R22_REG	22)
103  (R23_REG	23)
104
105  (DR0_REG	64)
106  (DR2_REG	66)
107  (DR4_REG	68)
108  (FR23_REG	87)
109
110  (TR0_REG	128)
111  (TR1_REG	129)
112  (TR2_REG	130)
113
114  (XD0_REG	136)
115
116  ;; These are used with unspec.
117  (UNSPEC_COMPACT_ARGS	0)
118  (UNSPEC_MOVA		1)
119  (UNSPEC_CASESI	2)
120  (UNSPEC_DATALABEL	3)
121  (UNSPEC_BBR		4)
122  (UNSPEC_SFUNC		5)
123  (UNSPEC_PIC		6)
124  (UNSPEC_GOT		7)
125  (UNSPEC_GOTOFF	8)
126  (UNSPEC_PLT		9)
127  (UNSPEC_CALLER	10)
128  (UNSPEC_GOTPLT	11)
129  (UNSPEC_ICACHE	12)
130  (UNSPEC_INIT_TRAMP	13)
131  (UNSPEC_FCOSA		14)
132  (UNSPEC_FSRRA		15)
133  (UNSPEC_FSINA		16)
134  (UNSPEC_NSB		17)
135  (UNSPEC_ALLOCO	18)
136  (UNSPEC_TLSGD		20)
137  (UNSPEC_TLSLDM	21)
138  (UNSPEC_TLSIE		22)
139  (UNSPEC_DTPOFF	23)
140  (UNSPEC_GOTTPOFF	24)
141  (UNSPEC_TPOFF		25)
142  (UNSPEC_RA		26)
143  (UNSPEC_DIV_INV_M0	30)
144  (UNSPEC_DIV_INV_M1	31)
145  (UNSPEC_DIV_INV_M2	32)
146  (UNSPEC_DIV_INV_M3	33)
147  (UNSPEC_DIV_INV20	34)
148  (UNSPEC_DIV_INV_TABLE	37)
149  (UNSPEC_ASHIFTRT	35)
150  (UNSPEC_THUNK		36)
151  (UNSPEC_CHKADD	38)
152  (UNSPEC_SP_SET	40)
153  (UNSPEC_SP_TEST	41)
154  (UNSPEC_MOVUA		42)
155
156  ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
157  ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
158  (UNSPEC_EXTRACT_S16	43)
159  (UNSPEC_EXTRACT_U16	44)
160
161  ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
162  (UNSPEC_SYMOFF	45)
163
164  ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
165  (UNSPEC_PCREL_SYMOFF	46)
166
167  ;; These are used with unspec_volatile.
168  (UNSPECV_BLOCKAGE	0)
169  (UNSPECV_ALIGN	1)
170  (UNSPECV_CONST2	2)
171  (UNSPECV_CONST4	4)
172  (UNSPECV_CONST8	6)
173  (UNSPECV_WINDOW_END	10)
174  (UNSPECV_CONST_END	11)
175  (UNSPECV_EH_RETURN	12)
176  (UNSPECV_GBR		13)
177  (UNSPECV_SP_SWITCH_B  14)
178  (UNSPECV_SP_SWITCH_E  15)
179])
180
181;; -------------------------------------------------------------------------
182;; Attributes
183;; -------------------------------------------------------------------------
184
185;; Target CPU.
186
187(define_attr "cpu"
188 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
189  (const (symbol_ref "sh_cpu_attr")))
190
191(define_attr "endian" "big,little"
192 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
193		      (const_string "little") (const_string "big"))))
194
195;; Indicate if the default fpu mode is single precision.
196(define_attr "fpu_single" "yes,no"
197  (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
198		       (const_string "yes") (const_string "no"))))
199
200(define_attr "fmovd" "yes,no"
201  (const (if_then_else (symbol_ref "TARGET_FMOVD")
202		       (const_string "yes") (const_string "no"))))
203;; pipeline model
204(define_attr "pipe_model" "sh1,sh4,sh5media"
205  (const
206   (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
207          (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
208         (const_string "sh1"))))
209
210;; cbranch	conditional branch instructions
211;; jump		unconditional jumps
212;; arith	ordinary arithmetic
213;; arith3	a compound insn that behaves similarly to a sequence of
214;;		three insns of type arith
215;; arith3b	like above, but might end with a redirected branch
216;; load		from memory
217;; load_si	Likewise, SImode variant for general register.
218;; fload	Likewise, but load to fp register.
219;; store	to memory
220;; fstore	floating point register to memory
221;; move		general purpose register to register
222;; movi8	8-bit immediate to general purpose register
223;; mt_group	other sh4 mt instructions
224;; fmove	register to register, floating point
225;; smpy		word precision integer multiply
226;; dmpy		longword or doublelongword precision integer multiply
227;; return	rts
228;; pload	load of pr reg, which can't be put into delay slot of rts
229;; prset	copy register to pr reg, ditto
230;; pstore	store of pr reg, which can't be put into delay slot of jsr
231;; prget	copy pr to register, ditto
232;; pcload	pc relative load of constant value
233;; pcfload	Likewise, but load to fp register.
234;; pcload_si	Likewise, SImode variant for general register.
235;; rte		return from exception
236;; sfunc	special function call with known used registers
237;; call		function call
238;; fp		floating point
239;; fpscr_toggle	toggle a bit in the fpscr
240;; fdiv		floating point divide (or square root)
241;; gp_fpul	move from general purpose register to fpul
242;; fpul_gp	move from fpul to general purpose register
243;; mac_gp	move from mac[lh] to general purpose register
244;; gp_mac	move from general purpose register to mac[lh]
245;; mac_mem	move from mac[lh] to memory
246;; mem_mac	move from memory to mac[lh]
247;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
248;; ftrc_s	fix_truncsfsi2_i4
249;; dfdiv	double precision floating point divide (or square root)
250;; cwb		ic_invalidate_line_i
251;; movua	SH4a unaligned load
252;; fsrra	square root reciprocal approximate
253;; fsca		sine and cosine approximate
254;; tls_load     load TLS related address
255;; arith_media	SHmedia arithmetic, logical, and shift instructions
256;; cbranch_media SHmedia conditional branch instructions
257;; cmp_media	SHmedia compare instructions
258;; dfdiv_media	SHmedia double precision divide and square root
259;; dfmul_media	SHmedia double precision multiply instruction
260;; dfparith_media SHmedia double precision floating point arithmetic
261;; dfpconv_media SHmedia double precision floating point conversions
262;; dmpy_media	SHmedia longword multiply
263;; fcmp_media	SHmedia floating point compare instructions
264;; fdiv_media	SHmedia single precision divide and square root
265;; fload_media	SHmedia floating point register load instructions
266;; fmove_media	SHmedia floating point register moves (inc. fabs and fneg)
267;; fparith_media SHmedia single precision floating point arithmetic
268;; fpconv_media	SHmedia single precision floating point conversions
269;; fstore_media	SHmedia floating point register store instructions
270;; gettr_media	SHmedia gettr instruction
271;; invalidate_line_media SHmedia invalidate_line sequence
272;; jump_media	SHmedia unconditional branch instructions
273;; load_media	SHmedia general register load instructions
274;; pt_media	SHmedia pt instruction (expanded by assembler)
275;; ptabs_media	SHmedia ptabs instruction
276;; store_media	SHmedia general register store instructions
277;; mcmp_media	SHmedia multimedia compare, absolute, saturating ops
278;; mac_media	SHmedia mac-style fixed point operations
279;; d2mpy_media	SHmedia: two 32-bit integer multiplies
280;; atrans_media	SHmedia approximate transcendental functions
281;; ustore_media	SHmedia unaligned stores
282;; nil		no-op move, will be deleted.
283
284(define_attr "type"
285 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,
286  fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,
287  prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,
288  dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,
289  gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,
290  arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,
291  dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,
292  fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,
293  jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,
294  d2mpy_media,atrans_media,ustore_media,nil,other"
295  (const_string "other"))
296
297;; We define a new attribute namely "insn_class".We use
298;; this for the DFA based pipeline description.
299;;
300;; mt_group      SH4 "mt" group instructions.
301;;
302;; ex_group      SH4 "ex" group instructions.
303;;
304;; ls_group      SH4 "ls" group instructions.
305;;
306(define_attr "insn_class"
307  "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
308  (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
309	 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
310	 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,
311			  store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
312	 (eq_attr "type" "cbranch,jump") (const_string "br_group")
313	 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
314	   (const_string "fe_group")
315	 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,
316			  prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,
317			  gp_mac,mac_mem,mem_mac") (const_string "co_group")]
318	(const_string "none")))
319
320;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
321;; so these do not belong in an insn group, although they are modeled
322;; with their own define_insn_reservations.
323
324;; Indicate what precision must be selected in fpscr for this insn, if any.
325(define_attr "fp_mode" "single,double,none" (const_string "none"))
326
327;; Indicate if the fpu mode is set by this instruction
328;; "unknown" must have the value as "none" in fp_mode, and means
329;; that the instruction/abi has left the processor in an unknown
330;; state.
331;; "none" means that nothing has changed and no mode is set.
332;; This attribute is only used for the Renesas ABI.
333(define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
334
335; If a conditional branch destination is within -252..258 bytes away
336; from the instruction it can be 2 bytes long.  Something in the
337; range -4090..4100 bytes can be 6 bytes long.  All other conditional
338; branches are initially assumed to be 16 bytes long.
339; In machine_dependent_reorg, we split all branches that are longer than
340; 2 bytes.
341
342;; The maximum range used for SImode constant pool entries is 1018.  A final
343;; instruction can add 8 bytes while only being 4 bytes in size, thus we
344;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
345;; instruction around the pool table, 2 bytes of alignment before the table,
346;; and 30 bytes of alignment after the table.  That gives a maximum total
347;; pool size of 1058 bytes.
348;; Worst case code/pool content size ratio is 1:2 (using asms).
349;; Thus, in the worst case, there is one instruction in front of a maximum
350;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
351;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
352;; If we have a forward branch, the initial table will be put after the
353;; unconditional branch.
354;;
355;; ??? We could do much better by keeping track of the actual pcloads within
356;; the branch range and in the pcload range in front of the branch range.
357
358;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
359;; inside an le.
360(define_attr "short_cbranch_p" "no,yes"
361  (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
362	 (const_string "no")
363	 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
364	 (const_string "yes")
365	 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
366	 (const_string "no")
367	 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
368	 (const_string "yes")
369	 ] (const_string "no")))
370
371(define_attr "med_branch_p" "no,yes"
372  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
373	      (const_int 1988))
374	 (const_string "yes")
375	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
376	 (const_string "no")
377	 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
378	      (const_int 8186))
379	 (const_string "yes")
380	 ] (const_string "no")))
381
382(define_attr "med_cbranch_p" "no,yes"
383  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
384	      (const_int 1986))
385	 (const_string "yes")
386	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
387	 (const_string "no")
388	 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
389	       (const_int 8184))
390	 (const_string "yes")
391	 ] (const_string "no")))
392
393(define_attr "braf_branch_p" "no,yes"
394  (cond [(match_test "! TARGET_SH2")
395	 (const_string "no")
396	 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
397	      (const_int 20660))
398	 (const_string "yes")
399	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
400	 (const_string "no")
401	 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
402	      (const_int 65530))
403	 (const_string "yes")
404	 ] (const_string "no")))
405
406(define_attr "braf_cbranch_p" "no,yes"
407  (cond [(match_test "! TARGET_SH2")
408	 (const_string "no")
409	 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
410	      (const_int 20658))
411	 (const_string "yes")
412	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
413	 (const_string "no")
414	 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
415	      (const_int 65528))
416	 (const_string "yes")
417	 ] (const_string "no")))
418
419;; An unconditional jump in the range -4092..4098 can be 2 bytes long.
420;; For wider ranges, we need a combination of a code and a data part.
421;; If we can get a scratch register for a long range jump, the code
422;; part can be 4 bytes long; otherwise, it must be 8 bytes long.
423;; If the jump is in the range -32764..32770, the data part can be 2 bytes
424;; long; otherwise, it must be 6 bytes long.
425
426;; All other instructions are two bytes long by default.
427
428;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
429;; but getattrtab doesn't understand this.
430(define_attr "length" ""
431  (cond [(eq_attr "type" "cbranch")
432	 (cond [(eq_attr "short_cbranch_p" "yes")
433		(const_int 2)
434		(eq_attr "med_cbranch_p" "yes")
435		(const_int 6)
436		(eq_attr "braf_cbranch_p" "yes")
437		(const_int 12)
438;; ??? using pc is not computed transitively.
439		(ne (match_dup 0) (match_dup 0))
440		(const_int 14)
441		(match_test "flag_pic")
442		(const_int 24)
443		] (const_int 16))
444	 (eq_attr "type" "jump")
445	 (cond [(eq_attr "med_branch_p" "yes")
446		(const_int 2)
447		(and (match_test "prev_nonnote_insn (insn)")
448		     (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
449			      (symbol_ref "INSN"))
450			  (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
451			      (symbol_ref "code_for_indirect_jump_scratch"))))
452		(cond [(eq_attr "braf_branch_p" "yes")
453		       (const_int 6)
454		       (not (match_test "flag_pic"))
455		       (const_int 10)
456		       (match_test "TARGET_SH2")
457		       (const_int 10)] (const_int 18))
458		(eq_attr "braf_branch_p" "yes")
459		(const_int 10)
460;; ??? using pc is not computed transitively.
461		(ne (match_dup 0) (match_dup 0))
462		(const_int 12)
463		(match_test "flag_pic")
464		(const_int 22)
465		] (const_int 14))
466	 (eq_attr "type" "pt_media")
467	 (if_then_else (match_test "TARGET_SHMEDIA64")
468		       (const_int 20) (const_int 12))
469	 (and (eq_attr "type" "jump_media")
470	      (match_test "TARGET_SH5_CUT2_WORKAROUND"))
471	 (const_int 8)
472	 ] (if_then_else (match_test "TARGET_SHMEDIA")
473			 (const_int 4)
474			 (const_int 2))))
475
476;; DFA descriptions for the pipelines
477
478(include "sh1.md")
479(include "shmedia.md")
480(include "sh4.md")
481
482(include "iterators.md")
483(include "predicates.md")
484(include "constraints.md")
485
486;; Definitions for filling delay slots
487
488(define_attr "needs_delay_slot" "yes,no" (const_string "no"))
489
490(define_attr "banked" "yes,no" 
491	(cond [(match_test "sh_loads_bankedreg_p (insn)")
492	       (const_string "yes")]
493	      (const_string "no")))
494
495;; ??? This should be (nil) instead of (const_int 0)
496(define_attr "hit_stack" "yes,no"
497	(cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
498	       (const_string "no")]
499	      (const_string "yes")))
500
501(define_attr "interrupt_function" "no,yes"
502  (const (symbol_ref "current_function_interrupt")))
503
504(define_attr "in_delay_slot" "yes,no"
505  (cond [(eq_attr "type" "cbranch") (const_string "no")
506	 (eq_attr "type" "pcload,pcload_si") (const_string "no")
507	 (eq_attr "needs_delay_slot" "yes") (const_string "no")
508	 (eq_attr "length" "2") (const_string "yes")
509	 ] (const_string "no")))
510
511(define_attr "cond_delay_slot" "yes,no"
512  (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
513	 ] (const_string "no")))
514
515(define_attr "is_sfunc" ""
516  (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
517
518(define_attr "is_mac_media" ""
519  (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
520
521(define_attr "branch_zero" "yes,no"
522  (cond [(eq_attr "type" "!cbranch") (const_string "no")
523	 (ne (symbol_ref "(next_active_insn (insn)\
524			   == (prev_active_insn\
525			       (XEXP (SET_SRC (PATTERN (insn)), 1))))\
526			  && get_attr_length (next_active_insn (insn)) == 2")
527	     (const_int 0))
528	 (const_string "yes")]
529	(const_string "no")))
530
531;; SH4 Double-precision computation with double-precision result -
532;; the two halves are ready at different times.
533(define_attr "dfp_comp" "yes,no"
534  (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
535	(const_string "no")))
536
537;; Insns for which the latency of a preceding fp insn is decreased by one.
538(define_attr "late_fp_use" "yes,no" (const_string "no"))
539;; And feeding insns for which this relevant.
540(define_attr "any_fp_comp" "yes,no"
541  (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
542	 (const_string "yes")]
543	(const_string "no")))
544
545(define_attr "any_int_load" "yes,no"
546  (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
547	 (const_string "yes")]
548	(const_string "no")))
549
550(define_attr "highpart" "user, ignore, extend, depend, must_split"
551  (const_string "user"))
552
553(define_delay
554  (eq_attr "needs_delay_slot" "yes")
555  [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
556
557;; Since a normal return (rts) implicitly uses the PR register,
558;; we can't allow PR register loads in an rts delay slot.
559;; On the SH1* and SH2*, the rte instruction reads the return pc from the
560;; stack, and thus we can't put a pop instruction in its delay slot.
561;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
562;; pop instruction can go in the delay slot, unless it references a banked
563;; register (the register bank is switched by rte).
564(define_delay
565  (eq_attr "type" "return")
566  [(and (eq_attr "in_delay_slot" "yes")
567	(ior (and (eq_attr "interrupt_function" "no")
568		  (eq_attr "type" "!pload,prset"))
569	     (and (eq_attr "interrupt_function" "yes")
570		  (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
571		  (eq_attr "banked" "no"))))
572   (nil) (nil)])
573
574;; Since a call implicitly uses the PR register, we can't allow
575;; a PR register store in a jsr delay slot.
576
577(define_delay
578  (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
579  [(and (eq_attr "in_delay_slot" "yes")
580	(eq_attr "type" "!pstore,prget")) (nil) (nil)])
581
582;; Say that we have annulled true branches, since this gives smaller and
583;; faster code when branches are predicted as not taken.
584
585;; ??? The non-annulled condition should really be "in_delay_slot",
586;; but insns that can be filled in non-annulled get priority over insns
587;; that can only be filled in anulled.
588
589(define_delay
590  (and (eq_attr "type" "cbranch")
591       (match_test "TARGET_SH2"))
592  ;; SH2e has a hardware bug that pretty much prohibits the use of
593  ;; annulled delay slots.
594  [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
595					  (not (eq_attr "cpu" "sh2e"))) (nil)])
596
597;; -------------------------------------------------------------------------
598;; SImode signed integer comparisons
599;; -------------------------------------------------------------------------
600
601;; Various patterns to generate the TST #imm, R0 instruction.
602;; Although this adds some pressure on the R0 register, it can potentially
603;; result in faster code, even if the operand has to be moved to R0 first.
604;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group 
605;; instructions and thus will be executed in parallel.  On SH4A TST #imm, R0
606;; is an EX group instruction but still can be executed in parallel with the
607;; MT group MOV Rm, Rn instruction.
608
609;; Usual TST #imm, R0 patterns for SI, HI and QI
610;; This is usually used for bit patterns other than contiguous bits 
611;; and single bits.
612(define_insn "tstsi_t"
613  [(set (reg:SI T_REG)
614	(eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
615		       (match_operand:SI 1 "logical_operand" "K08,r"))
616	       (const_int 0)))]
617  "TARGET_SH1"
618  "tst	%1,%0"
619  [(set_attr "type" "mt_group")])
620
621(define_insn "tsthi_t"
622  [(set (reg:SI T_REG)
623	(eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
624				  (match_operand 1 "const_int_operand")) 0)
625	       (const_int 0)))]
626  "TARGET_SH1
627   && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
628  "tst	%1,%0"
629  [(set_attr "type" "mt_group")])
630
631(define_insn "tstqi_t"
632  [(set (reg:SI T_REG)
633	(eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
634				  (match_operand 1 "const_int_operand")) 0)
635	       (const_int 0)))]
636  "TARGET_SH1
637   && (CONST_OK_FOR_K08 (INTVAL (operands[1])) 
638       || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
639{
640  operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
641  return "tst	%1,%0";
642}
643  [(set_attr "type" "mt_group")])
644
645;; Test low QI subreg against zero.
646;; This avoids unnecessary zero extension before the test.
647(define_insn "*tstqi_t_zero"
648  [(set (reg:SI T_REG)
649	(eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
650  "TARGET_SH1"
651  "tst	#255,%0"
652  [(set_attr "type" "mt_group")])
653
654;; Extract LSB, negate and store in T bit.
655(define_insn "tstsi_t_and_not"
656  [(set (reg:SI T_REG)
657	 (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
658		 (const_int 1)))]
659  "TARGET_SH1"
660  "tst	#1,%0"
661  [(set_attr "type" "mt_group")])
662
663;; Extract contiguous bits and compare them against zero.
664(define_insn "tst<mode>_t_zero_extract_eq"
665  [(set (reg:SI T_REG)
666	(eq:SI (zero_extract:SI (match_operand:QIHISIDI 0 "logical_operand" "z")
667				(match_operand:SI 1 "const_int_operand")
668				(match_operand:SI 2 "const_int_operand"))
669	       (const_int 0)))]
670  "TARGET_SH1
671   && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
672{
673  operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
674  return "tst	%1,%0";
675}
676  [(set_attr "type" "mt_group")])
677
678;; This split is required when testing bits in a QI subreg.
679(define_split
680  [(set (reg:SI T_REG)
681	(eq:SI
682	  (if_then_else:SI
683	    (zero_extract:SI (match_operand 0 "logical_operand")
684			     (match_operand 1 "const_int_operand")
685			     (match_operand 2 "const_int_operand"))
686	    (match_operand 3 "const_int_operand")
687	    (const_int 0))
688	  (const_int 0)))]
689  "TARGET_SH1
690   && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
691   && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
692  [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
693			      (const_int 0)))]
694{
695  if (GET_MODE (operands[0]) == QImode)
696    operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
697})
698
699;; Extract single bit, negate and store it in the T bit.
700;; Not used for SH4A.
701(define_insn "tstsi_t_zero_extract_xor"
702  [(set (reg:SI T_REG)
703	(zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
704				 (match_operand:SI 3 "const_int_operand"))
705			 (match_operand:SI 1 "const_int_operand")
706			 (match_operand:SI 2 "const_int_operand")))]
707  "TARGET_SH1
708   && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
709   && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
710  "tst	%3,%0"
711  [(set_attr "type" "mt_group")])
712
713;; Extract single bit, negate and store it in the T bit.
714;; Used for SH4A little endian.
715(define_insn "tstsi_t_zero_extract_subreg_xor_little"
716  [(set (reg:SI T_REG)
717	(zero_extract:SI
718	 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
719			    (match_operand:SI 3 "const_int_operand")) 0)
720	 (match_operand:SI 1 "const_int_operand")
721	 (match_operand:SI 2 "const_int_operand")))]
722  "TARGET_SH1 && TARGET_LITTLE_ENDIAN
723   && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
724      == (INTVAL (operands[3]) & 255)
725   && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
726{
727  operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
728  return "tst	%3,%0";
729}
730  [(set_attr "type" "mt_group")])
731
732;; Extract single bit, negate and store it in the T bit.
733;; Used for SH4A big endian.
734(define_insn "tstsi_t_zero_extract_subreg_xor_big"
735  [(set (reg:SI T_REG)
736	(zero_extract:SI
737	 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
738			    (match_operand:SI 3 "const_int_operand")) 3)
739	 (match_operand:SI 1 "const_int_operand")
740	 (match_operand:SI 2 "const_int_operand")))]
741  "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
742   && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
743      == (INTVAL (operands[3]) & 255)
744   && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
745{
746  operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
747  return "tst	%3,%0";
748}
749  [(set_attr "type" "mt_group")])
750
751(define_insn "cmpeqsi_t"
752  [(set (reg:SI T_REG)
753	(eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
754	       (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
755  "TARGET_SH1"
756  "@
757	tst	%0,%0
758	cmp/eq	%1,%0
759	cmp/eq	%1,%0"
760   [(set_attr "type" "mt_group")])
761
762;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
763;; pattern by itself.  What this actually does is:
764;;	x == 0: (1 >> 0-0) & 1 = 1
765;;	x != 0: (1 >> 0-x) & 1 = 0
766;; Without this the test pr51244-8.c fails on SH2A and SH4A.
767(define_insn_and_split "*cmpeqsi_t"
768  [(set (reg:SI T_REG)
769	(and:SI (lshiftrt:SI
770		  (const_int 1)
771		  (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
772		(const_int 1)))]
773  "TARGET_SH1"
774  "#"
775  "&& 1"
776  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
777
778(define_insn "cmpgtsi_t"
779  [(set (reg:SI T_REG)
780	(gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
781	       (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
782  "TARGET_SH1"
783  "@
784	cmp/pl	%0
785	cmp/gt	%1,%0"
786   [(set_attr "type" "mt_group")])
787
788(define_insn "cmpgesi_t"
789  [(set (reg:SI T_REG)
790	(ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
791	       (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
792  "TARGET_SH1"
793  "@
794	cmp/pz	%0
795	cmp/ge	%1,%0"
796   [(set_attr "type" "mt_group")])
797
798;; FIXME: This is actually wrong.  There is no way to literally move a
799;; general reg to t reg.  Luckily, it seems that this pattern will be only
800;; used when the general reg is known be either '0' or '1' during combine.
801;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
802;; Due to interactions with other patterns, combine fails to pick the latter
803;; and invert the dependent logic.
804(define_insn "*negtstsi"
805  [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
806  "TARGET_SH1"
807  "cmp/pl	%0"
808   [(set_attr "type" "mt_group")])
809
810;; Some integer sign comparison patterns can be realized with the div0s insn.
811;;	div0s	Rm,Rn		T = (Rm >> 31) ^ (Rn >> 31)
812(define_insn "cmp_div0s_0"
813  [(set (reg:SI T_REG)
814	(lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
815			     (match_operand:SI 1 "arith_reg_operand" "r"))
816		     (const_int 31)))]
817  "TARGET_SH1"
818  "div0s	%0,%1"
819  [(set_attr "type" "arith")])
820
821(define_insn "cmp_div0s_1"
822  [(set (reg:SI T_REG)
823	(lt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
824		       (match_operand:SI 1 "arith_reg_operand" "r"))
825	       (const_int 0)))]
826  "TARGET_SH1"
827  "div0s	%0,%1"
828  [(set_attr "type" "arith")])
829
830(define_insn_and_split "*cmp_div0s_0"
831  [(set (match_operand:SI 0 "arith_reg_dest" "")
832	(lshiftrt:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
833			     (match_operand:SI 2 "arith_reg_operand" ""))
834		     (const_int 31)))
835   (clobber (reg:SI T_REG))]
836  "TARGET_SH1"
837  "#"
838  "&& 1"
839  [(set (reg:SI T_REG)
840	(lshiftrt:SI (xor:SI (match_dup 1) (match_dup 2)) (const_int 31)))
841   (set (match_dup 0) (reg:SI T_REG))])
842
843(define_insn_and_split "*cmp_div0s_1"
844  [(set (match_operand:SI 0 "arith_reg_dest" "")
845	(ge:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
846		       (match_operand:SI 2 "arith_reg_operand" ""))
847	       (const_int 0)))
848   (clobber (reg:SI T_REG))]
849  "TARGET_SH1"
850  "#"
851  "&& can_create_pseudo_p ()"
852  [(const_int 0)]
853;; We have to go through the movnegt expander here which will handle the
854;; SH2A vs non-SH2A cases.
855{
856  emit_insn (gen_cmp_div0s_1 (operands[1], operands[2]));
857  emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
858  DONE;
859})
860
861(define_insn_and_split "*cmp_div0s_1"
862  [(set (reg:SI T_REG)
863	(ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
864		       (match_operand:SI 1 "arith_reg_operand" ""))
865	       (const_int 0)))]
866  "TARGET_SH1"
867  "#"
868  "&& can_create_pseudo_p ()"
869  [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
870			      (const_int 0)))
871   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
872
873;; -------------------------------------------------------------------------
874;; SImode compare and branch
875;; -------------------------------------------------------------------------
876
877(define_expand "cbranchsi4"
878  [(set (pc)
879	(if_then_else (match_operator 0 "comparison_operator"
880			[(match_operand:SI 1 "arith_operand" "")
881			 (match_operand:SI 2 "arith_operand" "")])
882		      (label_ref (match_operand 3 "" ""))
883		      (pc)))
884   (clobber (reg:SI T_REG))]
885  ""
886{
887  if (TARGET_SHMEDIA)
888    emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
889					   operands[2], operands[3]));
890  else
891    expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
892
893  DONE;
894})
895
896;; Combine patterns to invert compare and branch operations for which we
897;; don't have actual comparison insns.  These patterns are used in cases
898;; which appear after the initial cbranchsi expansion, which also does
899;; some condition inversion.
900(define_split
901  [(set (pc)
902	(if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
903			  (match_operand:SI 1 "arith_reg_or_0_operand" ""))
904		      (label_ref (match_operand 2))
905		      (pc)))
906   (clobber (reg:SI T_REG))]
907  "TARGET_SH1"
908  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
909   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
910			   (label_ref (match_dup 2))
911			   (pc)))])
912
913;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
914;; and SH2A combine fails to simplify this pattern by itself.
915;; What this actually does is:
916;;	x == 0: (1 >> 0-0) & 1 = 1
917;;	x != 0: (1 >> 0-x) & 1 = 0
918;; Without this the test pr51244-8.c fails on SH2A and SH4A.
919(define_split
920  [(set (pc)
921	(if_then_else
922	  (eq (and:SI (lshiftrt:SI
923			(const_int 1)
924			(neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
925		      (const_int 1))
926	      (const_int 0))
927	  (label_ref (match_operand 2))
928	  (pc)))
929   (clobber (reg:SI T_REG))]
930  "TARGET_SH1"
931  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
932   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
933			   (label_ref (match_dup 2))
934			   (pc)))])
935
936;; FIXME: These could probably use code iterators for the compare op.
937(define_split
938  [(set (pc)
939	(if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
940			  (match_operand:SI 1 "arith_reg_or_0_operand" ""))
941		      (label_ref (match_operand 2))
942		      (pc)))
943   (clobber (reg:SI T_REG))]
944  "TARGET_SH1"
945  [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
946   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
947			   (label_ref (match_dup 2))
948			   (pc)))])
949
950(define_split
951  [(set (pc)
952	(if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
953			  (match_operand:SI 1 "arith_reg_or_0_operand" ""))
954		      (label_ref (match_operand 2))
955		      (pc)))
956   (clobber (reg:SI T_REG))]
957  "TARGET_SH1"
958  [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
959   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
960			   (label_ref (match_dup 2))
961			   (pc)))])
962
963(define_split
964  [(set (pc)
965	(if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
966			   (match_operand:SI 1 "arith_reg_operand" ""))
967		      (label_ref (match_operand 2))
968		      (pc)))
969   (clobber (reg:SI T_REG))]
970  "TARGET_SH1"
971  [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
972   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
973			   (label_ref (match_dup 2))
974			   (pc)))])
975
976(define_split
977  [(set (pc)
978	(if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
979			   (match_operand:SI 1 "arith_reg_operand" ""))
980		      (label_ref (match_operand 2))
981		      (pc)))
982   (clobber (reg:SI T_REG))]
983  "TARGET_SH1"
984  [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
985   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
986			   (label_ref (match_dup 2))
987			   (pc)))])
988
989;; Compare and branch combine patterns for div0s comparisons.
990(define_insn_and_split "*cbranch_div0s"
991  [(set (pc)
992	(if_then_else (lt (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
993				  (match_operand:SI 1 "arith_reg_operand" ""))
994			  (const_int 0))
995		      (label_ref (match_operand 2))
996		      (pc)))
997   (clobber (reg:SI T_REG))]
998  "TARGET_SH1"
999  "#"
1000  "&& 1"
1001  [(set (reg:SI T_REG)
1002	(lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1003   (set (pc)
1004	(if_then_else (ne (reg:SI T_REG) (const_int 0))
1005		      (label_ref (match_dup 2))
1006		      (pc)))])
1007
1008(define_insn_and_split "*cbranch_div0s"
1009  [(set (pc)
1010	(if_then_else (ge (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1011				  (match_operand:SI 1 "arith_reg_operand" ""))
1012			  (const_int 0))
1013		      (label_ref (match_operand 2))
1014		      (pc)))
1015   (clobber (reg:SI T_REG))]
1016  "TARGET_SH1"
1017  "#"
1018  "&& 1"
1019  [(set (reg:SI T_REG)
1020	(lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1021   (set (pc)
1022	(if_then_else (eq (reg:SI T_REG) (const_int 0))
1023		      (label_ref (match_dup 2))
1024		      (pc)))])
1025
1026;; Conditional move combine pattern for div0s comparisons.
1027;; This is used when TARGET_PRETEND_CMOVE is in effect.
1028(define_insn_and_split "*movsicc_div0s"
1029  [(set (match_operand:SI 0 "arith_reg_dest" "")
1030	(if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
1031				     (match_operand:SI 2 "arith_reg_operand" ""))
1032			     (const_int 0))
1033			 (match_operand:SI 3 "arith_reg_operand" "")
1034			 (match_operand:SI 4 "general_movsrc_operand" "")))
1035   (clobber (reg:SI T_REG))]
1036  "TARGET_PRETEND_CMOVE"
1037  "#"
1038  "&& 1"
1039  [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1040			      (const_int 0)))
1041   (set (match_dup 0)
1042	(if_then_else (ne (reg:SI T_REG) (const_int 0))
1043		      (match_dup 4)
1044		      (match_dup 3)))])
1045
1046;; -------------------------------------------------------------------------
1047;; SImode unsigned integer comparisons
1048;; -------------------------------------------------------------------------
1049
1050;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1051;; However, especially when optimizations are off (e.g. -O0) such comparisons
1052;; might remain and we have to handle them.  If the '>= 0' case wasn't
1053;; handled here, something else would just load a '0' into the second operand
1054;; and do the comparison.  We can do slightly better by just setting the
1055;; T bit to '1'.
1056(define_insn_and_split "cmpgeusi_t"
1057  [(set (reg:SI T_REG)
1058	(geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1059		(match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1060  "TARGET_SH1"
1061  "cmp/hs	%1,%0"
1062  "&& satisfies_constraint_Z (operands[1])"
1063  [(set (reg:SI T_REG) (const_int 1))]
1064  ""
1065  [(set_attr "type" "mt_group")])
1066
1067(define_insn "cmpgtusi_t"
1068  [(set (reg:SI T_REG)
1069	(gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1070		(match_operand:SI 1 "arith_reg_operand" "r")))]
1071  "TARGET_SH1"
1072  "cmp/hi	%1,%0"
1073  [(set_attr "type" "mt_group")])
1074
1075;; -------------------------------------------------------------------------
1076;; DImode compare and branch
1077;; -------------------------------------------------------------------------
1078
1079;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1080;; Therefore, we aim to have a set of three branches that go straight to the
1081;; destination, i.e. only one of them is taken at any one time.
1082;; This mechanism should also be slightly better for the sh4-200.
1083
1084(define_expand "cbranchdi4"
1085  [(set (pc)
1086	(if_then_else (match_operator 0 "comparison_operator"
1087			[(match_operand:DI 1 "arith_operand" "")
1088			 (match_operand:DI 2 "arith_operand" "")])
1089		      (label_ref (match_operand 3 "" ""))
1090		      (pc)))
1091   (clobber (match_dup 4))
1092   (clobber (reg:SI T_REG))]
1093  "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1094{
1095  enum rtx_code comparison;
1096
1097  if (TARGET_SHMEDIA)
1098    {
1099      emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1100					     operands[2], operands[3]));
1101      DONE;
1102    }
1103  else if (!TARGET_CBRANCHDI4)
1104    {
1105      sh_emit_compare_and_branch (operands, DImode);
1106      DONE;
1107    }
1108  else
1109    {
1110      if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1111	DONE;
1112
1113      comparison = prepare_cbranch_operands (operands, DImode,
1114					     LAST_AND_UNUSED_RTX_CODE);
1115      if (comparison != GET_CODE (operands[0]))
1116	operands[0]
1117	  = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1118       operands[4] = gen_rtx_SCRATCH (SImode);
1119    }
1120})
1121
1122(define_insn_and_split "cbranchdi4_i"
1123  [(set (pc)
1124	(if_then_else (match_operator 0 "comparison_operator"
1125			[(match_operand:DI 1 "arith_operand" "r,r")
1126			 (match_operand:DI 2 "arith_operand" "rN,I08")])
1127		      (label_ref (match_operand 3 "" ""))
1128		      (pc)))
1129   (clobber (match_scratch:SI 4 "=X,&r"))
1130   (clobber (reg:SI T_REG))]
1131  "TARGET_CBRANCHDI4"
1132  "#"
1133  "&& reload_completed"
1134  [(pc)]
1135{
1136  if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1137    FAIL;
1138  DONE;
1139})
1140
1141;; -------------------------------------------------------------------------
1142;; DImode signed integer comparisons
1143;; -------------------------------------------------------------------------
1144
1145(define_insn ""
1146  [(set (reg:SI T_REG)
1147	(eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1148		       (match_operand:DI 1 "arith_operand" "r"))
1149	       (const_int 0)))]
1150  "TARGET_SH1"
1151{
1152  return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1153			      insn, operands);
1154}
1155  [(set_attr "length" "6")
1156   (set_attr "type" "arith3b")])
1157
1158(define_insn "cmpeqdi_t"
1159  [(set (reg:SI T_REG)
1160	(eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1161	       (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1162  "TARGET_SH1"
1163{
1164  static const char* alt[] =
1165  {
1166       "tst	%S0,%S0"	"\n"
1167    "	bf	0f"		"\n"
1168    "	tst	%R0,%R0"	"\n"
1169    "0:",
1170
1171       "cmp/eq	%S1,%S0"	"\n"
1172    "	bf	0f"		"\n"
1173    "	cmp/eq	%R1,%R0"	"\n"
1174    "0:"
1175  };
1176  return alt[which_alternative];
1177}
1178  [(set_attr "length" "6")
1179   (set_attr "type" "arith3b")])
1180
1181(define_split
1182  [(set (reg:SI T_REG)
1183	(eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1184	       (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1185;; If we applied this split when not optimizing, it would only be
1186;; applied during the machine-dependent reorg, when no new basic blocks
1187;; may be created.
1188  "TARGET_SH1 && reload_completed && optimize"
1189  [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1190   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1191			   (label_ref (match_dup 6))
1192			   (pc)))
1193   (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1194   (match_dup 6)]
1195{
1196  operands[2] = gen_highpart (SImode, operands[0]);
1197  operands[3] = operands[1] == const0_rtx
1198		? const0_rtx
1199		: gen_highpart (SImode, operands[1]);
1200  operands[4] = gen_lowpart (SImode, operands[0]);
1201  operands[5] = gen_lowpart (SImode, operands[1]);
1202  operands[6] = gen_label_rtx ();
1203})
1204
1205(define_insn "cmpgtdi_t"
1206  [(set (reg:SI T_REG)
1207	(gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1208	       (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1209  "TARGET_SH2"
1210{
1211  static const char* alt[] =
1212  {
1213       "cmp/eq	%S1,%S0"	"\n"
1214    "	bf{.|/}s	0f"	"\n"
1215    "	cmp/gt	%S1,%S0"	"\n"
1216    "	cmp/hi	%R1,%R0"	"\n"
1217    "0:",
1218
1219        "tst	%S0,%S0"	"\n"
1220    "	bf{.|/}s	0f"	"\n"
1221    "	cmp/pl	%S0"		"\n"
1222    "	cmp/hi	%S0,%R0"	"\n"
1223    "0:"
1224  };
1225  return alt[which_alternative];
1226}
1227  [(set_attr "length" "8")
1228   (set_attr "type" "arith3")])
1229
1230(define_insn "cmpgedi_t"
1231  [(set (reg:SI T_REG)
1232	(ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1233	       (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1234  "TARGET_SH2"
1235{
1236  static const char* alt[] =
1237  {
1238       "cmp/eq	%S1,%S0"	"\n"
1239    "	bf{.|/}s	0f"	"\n"
1240    "	cmp/ge	%S1,%S0"	"\n"
1241    "	cmp/hs	%R1,%R0"	"\n"
1242    "0:",
1243
1244       "cmp/pz	%S0"
1245  };
1246  return alt[which_alternative];
1247}
1248  [(set_attr "length" "8,2")
1249   (set_attr "type" "arith3,mt_group")])
1250
1251;; -------------------------------------------------------------------------
1252;; DImode unsigned integer comparisons
1253;; -------------------------------------------------------------------------
1254
1255(define_insn "cmpgeudi_t"
1256  [(set (reg:SI T_REG)
1257	(geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1258		(match_operand:DI 1 "arith_reg_operand" "r")))]
1259  "TARGET_SH2"
1260{
1261  return       "cmp/eq	%S1,%S0"	"\n"
1262	 "	bf{.|/}s	0f"	"\n"
1263	 "	cmp/hs	%S1,%S0"	"\n"
1264	 "	cmp/hs	%R1,%R0"	"\n"
1265	 "0:";
1266}
1267  [(set_attr "length" "8")
1268   (set_attr "type" "arith3")])
1269
1270(define_insn "cmpgtudi_t"
1271  [(set (reg:SI T_REG)
1272	(gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1273		(match_operand:DI 1 "arith_reg_operand" "r")))]
1274  "TARGET_SH2"
1275{
1276  return       "cmp/eq	%S1,%S0"	"\n"
1277	 "	bf{.|/}s	0f"	"\n"
1278	 "	cmp/hi	%S1,%S0"	"\n"
1279	 "	cmp/hi	%R1,%R0"	"\n"
1280	 "0:";
1281}
1282  [(set_attr "length" "8")
1283   (set_attr "type" "arith3")])
1284
1285(define_insn "cmpeqsi_media"
1286  [(set (match_operand:SI 0 "register_operand" "=r")
1287	(eq:SI (match_operand:SI 1 "logical_operand" "%r")
1288	       (match_operand:SI 2 "cmp_operand" "Nr")))]
1289  "TARGET_SHMEDIA"
1290  "cmpeq	%1, %N2, %0"
1291  [(set_attr "type" "cmp_media")])
1292
1293(define_insn "cmpeqdi_media"
1294  [(set (match_operand:SI 0 "register_operand" "=r")
1295	(eq:SI (match_operand:DI 1 "register_operand" "%r")
1296	       (match_operand:DI 2 "cmp_operand" "Nr")))]
1297  "TARGET_SHMEDIA"
1298  "cmpeq	%1, %N2, %0"
1299  [(set_attr "type" "cmp_media")])
1300
1301(define_insn "cmpgtsi_media"
1302  [(set (match_operand:SI 0 "register_operand" "=r")
1303	(gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1304	       (match_operand:SI 2 "cmp_operand" "rN")))]
1305  "TARGET_SHMEDIA"
1306  "cmpgt	%N1, %N2, %0"
1307  [(set_attr "type" "cmp_media")])
1308
1309(define_insn "cmpgtdi_media"
1310  [(set (match_operand:SI 0 "register_operand" "=r")
1311	(gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1312	       (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1313  "TARGET_SHMEDIA"
1314  "cmpgt	%N1, %N2, %0"
1315  [(set_attr "type" "cmp_media")])
1316
1317(define_insn "cmpgtusi_media"
1318  [(set (match_operand:SI 0 "register_operand" "=r")
1319	(gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1320		(match_operand:SI 2 "cmp_operand" "rN")))]
1321  "TARGET_SHMEDIA"
1322  "cmpgtu	%N1, %N2, %0"
1323  [(set_attr "type" "cmp_media")])
1324
1325(define_insn "cmpgtudi_media"
1326  [(set (match_operand:SI 0 "register_operand" "=r")
1327	(gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1328		(match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1329  "TARGET_SHMEDIA"
1330  "cmpgtu	%N1, %N2, %0"
1331  [(set_attr "type" "cmp_media")])
1332
1333; This pattern is for combine.
1334(define_insn "*cmpne0sisi_media"
1335  [(set (match_operand:SI 0 "register_operand" "=r")
1336	(ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1337  "TARGET_SHMEDIA"
1338  "cmpgtu	%1,r63,%0"
1339  [(set_attr "type" "cmp_media")])
1340
1341;; -------------------------------------------------------------------------
1342;; Conditional move instructions
1343;; -------------------------------------------------------------------------
1344
1345;; The insn names may seem reversed, but note that cmveq performs the move
1346;; if op1 == 0, and cmvne does it if op1 != 0.
1347
1348(define_insn "movdicc_false"
1349  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1350	(if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1351			     (const_int 0))
1352	 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1353	 (match_operand:DI 3 "arith_reg_operand" "0")))]
1354  "TARGET_SHMEDIA"
1355  "cmveq	%1, %N2, %0"
1356  [(set_attr "type" "arith_media")])
1357
1358(define_insn "movdicc_true"
1359  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1360	(if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1361			     (const_int 0))
1362	 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1363	 (match_operand:DI 3 "arith_reg_operand" "0")))]
1364  "TARGET_SHMEDIA"
1365  "cmvne	%1, %N2, %0"
1366  [(set_attr "type" "arith_media")])
1367
1368(define_peephole2
1369  [(set (match_operand:DI 0 "arith_reg_dest" "")
1370	(if_then_else:DI (match_operator 3 "equality_comparison_operator"
1371			   [(match_operand:DI 1 "arith_reg_operand" "")
1372			    (const_int 0)])
1373	 (match_operand:DI 2 "arith_reg_dest" "")
1374	 (match_dup 0)))
1375   (set (match_dup 2) (match_dup 0))]
1376  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1377  [(set (match_dup 2)
1378	(if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1379{
1380  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1381				VOIDmode, operands[1], CONST0_RTX (DImode));
1382})
1383
1384(define_peephole2
1385  [(set (match_operand:DI 0 "general_movdst_operand" "")
1386	(match_operand:DI 1 "arith_reg_or_0_operand" ""))
1387   (set (match_operand:DI 2 "arith_reg_dest" "")
1388	(if_then_else:DI (match_operator 4 "equality_comparison_operator"
1389			   [(match_operand:DI 3 "arith_reg_operand" "")
1390			    (const_int 0)])
1391	 (match_dup 0)
1392	 (match_dup 2)))]
1393  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1394  [(set (match_dup 2)
1395	(if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1396  "")
1397
1398(define_expand "movdicc"
1399  [(set (match_operand:DI 0 "register_operand" "")
1400	(if_then_else:DI (match_operand 1 "comparison_operator" "")
1401			 (match_operand:DI 2 "register_operand" "")
1402			 (match_operand:DI 3 "register_operand" "")))]
1403  "TARGET_SHMEDIA"
1404{
1405  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1406      && GET_MODE (XEXP (operands[1], 0)) == DImode
1407      && XEXP (operands[1], 1) == const0_rtx)
1408    ;
1409  else
1410    {
1411      if (!can_create_pseudo_p ())
1412	FAIL;
1413
1414      operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1415					      GET_CODE (operands[1]),
1416					      XEXP (operands[1], 0),
1417					      XEXP (operands[1], 1));
1418      if (!operands[1])
1419	FAIL;
1420    }
1421})
1422
1423;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1424;; SImode to DImode.
1425(define_insn "movsicc_false"
1426  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1427	(if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1428			  (const_int 0))
1429	 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1430	 (match_operand:SI 3 "arith_reg_operand" "0")))]
1431  "TARGET_SHMEDIA"
1432  "cmveq	%1, %N2, %0"
1433  [(set_attr "type" "arith_media")])
1434
1435(define_insn "movsicc_true"
1436  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1437	(if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1438			  (const_int 0))
1439	 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1440	 (match_operand:SI 3 "arith_reg_operand" "0")))]
1441  "TARGET_SHMEDIA"
1442  "cmvne	%1, %N2, %0"
1443  [(set_attr "type" "arith_media")])
1444
1445(define_peephole2
1446  [(set (match_operand:SI 0 "arith_reg_dest" "")
1447	(if_then_else:SI (match_operator 3 "equality_comparison_operator"
1448			   [(match_operand:SI 1 "arith_reg_operand" "")
1449			    (const_int 0)])
1450	 (match_operand:SI 2 "arith_reg_dest" "")
1451	 (match_dup 0)))
1452   (set (match_dup 2) (match_dup 0))]
1453  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1454  [(set (match_dup 2)
1455	(if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1456{
1457  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1458				VOIDmode, operands[1], CONST0_RTX (SImode));
1459})
1460
1461(define_peephole2
1462  [(set (match_operand:SI 0 "general_movdst_operand" "")
1463	(match_operand:SI 1 "arith_reg_or_0_operand" ""))
1464   (set (match_operand:SI 2 "arith_reg_dest" "")
1465	(if_then_else:SI (match_operator 4 "equality_comparison_operator"
1466			   [(match_operand:SI 3 "arith_reg_operand" "")
1467			    (const_int 0)])
1468	 (match_dup 0)
1469	 (match_dup 2)))]
1470  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1471   && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1472  [(set (match_dup 2)
1473	(if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1474{
1475  replace_rtx (operands[4], operands[0], operands[1]);
1476})
1477
1478(define_peephole2
1479  [(set (match_operand 0 "any_register_operand" "")
1480	(match_operand 1 "any_register_operand" ""))
1481   (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1482   (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1483  "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1484    <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1485   && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1486   && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1487   && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1488   && ! reg_overlap_mentioned_p (operands[0], operands[3])
1489   && ! reg_overlap_mentioned_p (operands[2], operands[0])
1490   && ! reg_overlap_mentioned_p (operands[0], operands[1])
1491   && (REGNO_REG_CLASS (REGNO (operands[0]))
1492       == REGNO_REG_CLASS (REGNO (operands[2])))
1493   && (REGNO_REG_CLASS (REGNO (operands[1]))
1494       == REGNO_REG_CLASS (REGNO (operands[0])))"
1495  [(set (match_dup 0) (match_dup 3))
1496   (set (match_dup 4) (match_dup 5))]
1497{
1498  rtx set1, set2, insn2;
1499  rtx replacements[4];
1500
1501  /* We want to replace occurrences of operands[0] with operands[1] and
1502     operands[2] with operands[0] in operands[4]/operands[5].
1503     Doing just two replace_rtx calls naively would result in the second
1504     replacement undoing all that the first did if operands[1] and operands[2]
1505     are identical, so we must do this simultaneously.  */
1506  replacements[0] = operands[0];
1507  replacements[1] = operands[1];
1508  replacements[2] = operands[2];
1509  replacements[3] = operands[0];
1510  if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1511      || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1512      || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1513    FAIL;
1514
1515  operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1516  replace_n_hard_rtx (operands[4], replacements, 2, 1);
1517  operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1518  /* The operands array is aliased to recog_data.operand, which gets
1519     clobbered by extract_insn, so finish with it now.  */
1520  set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1521  set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1522  /* ??? The last insn might be a jump insn, but the generic peephole2 code
1523     always uses emit_insn.  */
1524  /* Check that we don't violate matching constraints or earlyclobbers.  */
1525  extract_insn (emit_insn (set1));
1526  if (! constrain_operands (1))
1527    goto failure;
1528  insn2 = emit (set2);
1529  if (GET_CODE (insn2) == BARRIER)
1530    goto failure;
1531  extract_insn (insn2);
1532  if (! constrain_operands (1))
1533    {
1534      rtx tmp;
1535    failure:
1536      tmp = replacements[0];
1537      replacements[0] = replacements[1];
1538      replacements[1] = tmp;
1539      tmp = replacements[2];
1540      replacements[2] = replacements[3];
1541      replacements[3] = tmp;
1542      replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1543      replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1544      replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1545      FAIL;
1546    }
1547  DONE;
1548})
1549
1550;; The register allocator is rather clumsy in handling multi-way conditional
1551;; moves, so allow the combiner to make them, and we split them up after
1552;; reload.  */
1553(define_insn_and_split "*movsicc_umin"
1554  [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1555	(umin:SI (if_then_else:SI
1556		   (eq (match_operand:SI 1 "arith_reg_operand" "r")
1557		       (const_int 0))
1558		   (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1559		   (match_operand:SI 3 "register_operand" "0"))
1560		 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1561   (clobber (match_scratch:SI 5 "=&r"))]
1562  "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1563  "#"
1564  "TARGET_SHMEDIA && reload_completed"
1565  [(pc)]
1566{
1567  emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1568				operands[3]));
1569  emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1570  emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1571				operands[0]));
1572  DONE;
1573})
1574
1575(define_insn "*movsicc_t_false"
1576  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1577	(if_then_else (eq (reg:SI T_REG) (const_int 0))
1578		      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1579		      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1580  "TARGET_PRETEND_CMOVE
1581   && (arith_reg_operand (operands[1], SImode)
1582       || (immediate_operand (operands[1], SImode)
1583	   && satisfies_constraint_I08 (operands[1])))"
1584{
1585  return       "bt	0f"	"\n"
1586	 "	mov	%1,%0"	"\n"
1587	 "0:";
1588}
1589  [(set_attr "type" "mt_group,arith") ;; poor approximation
1590   (set_attr "length" "4")])
1591
1592(define_insn "*movsicc_t_true"
1593  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1594	(if_then_else (ne (reg:SI T_REG) (const_int 0))
1595		      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1596		      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1597  "TARGET_PRETEND_CMOVE
1598   && (arith_reg_operand (operands[1], SImode)
1599       || (immediate_operand (operands[1], SImode)
1600	   && satisfies_constraint_I08 (operands[1])))"
1601{
1602  return       "bf	0f"	"\n"
1603	 "	mov	%1,%0"	"\n"
1604	 "0:";
1605}
1606  [(set_attr "type" "mt_group,arith") ;; poor approximation
1607   (set_attr "length" "4")])
1608
1609(define_expand "movsicc"
1610  [(set (match_operand:SI 0 "arith_reg_dest" "")
1611	(if_then_else:SI (match_operand 1 "comparison_operator" "")
1612			 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1613			 (match_operand:SI 3 "arith_reg_operand" "")))]
1614  "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1615{
1616  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1617      && GET_MODE (XEXP (operands[1], 0)) == SImode
1618      && (TARGET_SHMEDIA
1619	  || (REG_P (XEXP (operands[1], 0))
1620	      && REGNO (XEXP (operands[1], 0)) == T_REG))
1621      && XEXP (operands[1], 1) == const0_rtx)
1622    ;
1623
1624  else if (TARGET_PRETEND_CMOVE)
1625    {
1626      enum rtx_code code = GET_CODE (operands[1]);
1627      enum rtx_code new_code = code;
1628      rtx op0 = XEXP (operands[1], 0);
1629      rtx op1 = XEXP (operands[1], 1);
1630
1631      if (! currently_expanding_to_rtl)
1632	FAIL;
1633      switch (code)
1634	{
1635	case LT: case LE: case LEU: case LTU:
1636	  if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1637	    break;
1638	case NE:
1639	  new_code = reverse_condition (code);
1640	  break;
1641	case EQ: case GT: case GE: case GEU: case GTU:
1642	  break;
1643	default:
1644	  FAIL;
1645	}
1646      sh_emit_scc_to_t (new_code, op0, op1);
1647      operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1648				    gen_rtx_REG (SImode, T_REG), const0_rtx);
1649    }
1650  else
1651    {
1652      if (!can_create_pseudo_p ())
1653	FAIL;
1654
1655      operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1656					      GET_CODE (operands[1]),
1657					      XEXP (operands[1], 0),
1658					      XEXP (operands[1], 1));
1659      if (!operands[1])
1660	FAIL;
1661    }
1662})
1663
1664(define_expand "movqicc"
1665  [(set (match_operand:QI 0 "register_operand" "")
1666	(if_then_else:QI (match_operand 1 "comparison_operator" "")
1667			 (match_operand:QI 2 "register_operand" "")
1668			 (match_operand:QI 3 "register_operand" "")))]
1669  "TARGET_SHMEDIA"
1670{
1671  operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1672  operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1673  operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1674  emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1675  DONE;
1676})
1677
1678;; -------------------------------------------------------------------------
1679;; Addition instructions
1680;; -------------------------------------------------------------------------
1681
1682(define_expand "adddi3"
1683  [(set (match_operand:DI 0 "arith_reg_operand" "")
1684	(plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1685		 (match_operand:DI 2 "arith_operand" "")))]
1686  ""
1687{
1688  if (TARGET_SH1)
1689    {
1690      if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
1691	FAIL;
1692      operands[2] = force_reg (DImode, operands[2]);
1693      emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1694      DONE;
1695    }
1696})
1697
1698(define_insn "*adddi3_media"
1699  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1700	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1701		 (match_operand:DI 2 "arith_operand" "r,I10")))]
1702  "TARGET_SHMEDIA"
1703  "@
1704	add	%1, %2, %0
1705	addi	%1, %2, %0"
1706  [(set_attr "type" "arith_media")])
1707
1708(define_insn "*adddisi3_media"
1709  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1710	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1711		 (match_operand:DI 2 "arith_operand" "r,I10")))]
1712  "TARGET_SHMEDIA"
1713  "@
1714	add.l	%1, %2, %0
1715	addi.l	%1, %2, %0"
1716  [(set_attr "type" "arith_media")
1717   (set_attr "highpart" "ignore")])
1718
1719(define_insn "adddi3z_media"
1720  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1721	(zero_extend:DI
1722	 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1723		  (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1724  "TARGET_SHMEDIA"
1725  "addz.l	%1, %N2, %0"
1726  [(set_attr "type" "arith_media")
1727   (set_attr "highpart" "ignore")])
1728
1729(define_insn_and_split "adddi3_compact"
1730  [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1731	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1732		 (match_operand:DI 2 "arith_reg_operand" "r")))
1733   (clobber (reg:SI T_REG))]
1734  "TARGET_SH1"
1735  "#"
1736  "&& reload_completed"
1737  [(const_int 0)]
1738{
1739  rtx high0 = gen_highpart (SImode, operands[0]);
1740  rtx high2 = gen_highpart (SImode, operands[2]);
1741  rtx low0 = gen_lowpart (SImode, operands[0]);
1742
1743  emit_insn (gen_clrt ());
1744  emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1745  emit_insn (gen_addc (high0, high0, high2));
1746  DONE;
1747})
1748
1749(define_insn "addc"
1750  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1751	(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1752			  (match_operand:SI 2 "arith_reg_operand" "r"))
1753		 (reg:SI T_REG)))
1754   (set (reg:SI T_REG)
1755	(ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1756  "TARGET_SH1"
1757  "addc	%2,%0"
1758  [(set_attr "type" "arith")])
1759
1760;; A simplified version of the addc insn, where the exact value of the
1761;; T bit doesn't matter.  This is easier for combine to pick up.
1762;; We allow a reg or 0 for one of the operands in order to be able to
1763;; do 'reg + T' sequences.  Reload will load the constant 0 into the reg
1764;; as needed.
1765(define_insn "*addc"
1766  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1767	(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1768			  (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1769		 (match_operand:SI 3 "t_reg_operand" "")))
1770   (clobber (reg:SI T_REG))]
1771  "TARGET_SH1"
1772  "addc	%2,%0"
1773  [(set_attr "type" "arith")])
1774
1775;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
1776;; better, if the sett insn can be done early.
1777(define_insn_and_split "*addc"
1778  [(set (match_operand:SI 0 "arith_reg_dest" "")
1779	(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
1780			  (match_operand:SI 2 "arith_reg_operand" ""))
1781		 (const_int 1)))
1782   (clobber (reg:SI T_REG))]
1783  "TARGET_SH1"
1784  "#"
1785  "&& 1"
1786  [(set (reg:SI T_REG) (const_int 1))
1787   (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
1788				          (reg:SI T_REG)))
1789	      (clobber (reg:SI T_REG))])])
1790
1791;; Left shifts by one are usually done with an add insn to avoid T_REG
1792;; clobbers.  Thus addc can also be used to do something like '(x << 1) + 1'.
1793(define_insn_and_split "*addc"
1794  [(set (match_operand:SI 0 "arith_reg_dest")
1795	(plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
1796			  (const_int 2))
1797		 (const_int 1)))
1798   (clobber (reg:SI T_REG))]
1799  "TARGET_SH1"
1800  "#"
1801  "&& 1"
1802  [(set (reg:SI T_REG) (const_int 1))
1803   (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
1804				          (reg:SI T_REG)))
1805	      (clobber (reg:SI T_REG))])])
1806
1807;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1808;; matched.  Split this up into a simple sub add sequence, as this will save
1809;; us one sett insn.
1810(define_insn_and_split "*minus_plus_one"
1811  [(set (match_operand:SI 0 "arith_reg_dest" "")
1812	(plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1813			   (match_operand:SI 2 "arith_reg_operand" ""))
1814		 (const_int 1)))]
1815  "TARGET_SH1"
1816  "#"
1817  "&& 1"
1818  [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1819   (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
1820
1821;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
1822;; If the 0 constant can be CSE-ed, this becomes a one instruction
1823;; operation, as opposed to sequences such as
1824;;	movt	r2
1825;;	add	r2,r3
1826;;
1827;; Even if the constant is not CSE-ed, a sequence such as
1828;;	mov	#0,r2
1829;;	addc	r2,r3
1830;; can be scheduled much better since the load of the constant can be
1831;; done earlier, before any comparison insns that store the result in
1832;; the T bit.
1833(define_insn_and_split "*addc"
1834  [(set (match_operand:SI 0 "arith_reg_dest" "")
1835	(plus:SI (match_operand:SI 1 "t_reg_operand" "")
1836		 (match_operand:SI 2 "arith_reg_operand" "")))
1837   (clobber (reg:SI T_REG))]
1838  "TARGET_SH1"
1839  "#"
1840  "&& 1"
1841  [(parallel [(set (match_dup 0)
1842		   (plus:SI (plus:SI (match_dup 2) (const_int 0))
1843			    (match_dup 1)))
1844	      (clobber (reg:SI T_REG))])])
1845
1846(define_expand "addsi3"
1847  [(set (match_operand:SI 0 "arith_reg_operand" "")
1848	(plus:SI (match_operand:SI 1 "arith_operand" "")
1849		 (match_operand:SI 2 "arith_operand" "")))]
1850  ""
1851{
1852  if (TARGET_SHMEDIA)
1853    operands[1] = force_reg (SImode, operands[1]);
1854})
1855
1856(define_insn "addsi3_media"
1857  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1858	(plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1859		 (match_operand:SI 2 "arith_operand" "r,I10")))]
1860  "TARGET_SHMEDIA"
1861  "@
1862	add.l	%1, %2, %0
1863	addi.l	%1, %2, %0"
1864  [(set_attr "type" "arith_media")
1865   (set_attr "highpart" "ignore")])
1866
1867(define_insn "addsidi3_media"
1868  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1869	(sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1870				  "%r,r")
1871				 (match_operand:SI 2 "arith_operand"
1872				  "r,I10"))))]
1873  "TARGET_SHMEDIA"
1874  "@
1875	add.l	%1, %2, %0
1876	addi.l	%1, %2, %0"
1877  [(set_attr "type" "arith_media")
1878   (set_attr "highpart" "ignore")])
1879
1880(define_insn "*addsi3_compact"
1881  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1882	(plus:SI (match_operand:SI 1 "arith_operand" "%0")
1883		 (match_operand:SI 2 "arith_operand" "rI08")))]
1884  "TARGET_SH1"
1885  "add	%2,%0"
1886  [(set_attr "type" "arith")])
1887
1888;; -------------------------------------------------------------------------
1889;; Subtraction instructions
1890;; -------------------------------------------------------------------------
1891
1892(define_expand "subdi3"
1893  [(set (match_operand:DI 0 "arith_reg_operand" "")
1894	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1895		  (match_operand:DI 2 "arith_reg_operand" "")))]
1896  ""
1897{
1898  if (TARGET_SH1)
1899    {
1900      operands[1] = force_reg (DImode, operands[1]);
1901      emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1902      DONE;
1903    }
1904})
1905
1906(define_insn "*subdi3_media"
1907  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1908	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1909		  (match_operand:DI 2 "arith_reg_operand" "r")))]
1910  "TARGET_SHMEDIA"
1911  "sub	%N1, %2, %0"
1912  [(set_attr "type" "arith_media")])
1913  
1914(define_insn "subdisi3_media"
1915  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1916	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1917		  (match_operand:DI 2 "arith_reg_operand" "r")))]
1918  "TARGET_SHMEDIA"
1919  "sub.l	%N1, %2, %0"
1920  [(set_attr "type" "arith_media")
1921   (set_attr "highpart" "ignore")])
1922
1923(define_insn_and_split "subdi3_compact"
1924  [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1925	(minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1926		 (match_operand:DI 2 "arith_reg_operand" "r")))
1927   (clobber (reg:SI T_REG))]
1928  "TARGET_SH1"
1929  "#"
1930  "&& reload_completed"
1931  [(const_int 0)]
1932{
1933  rtx high0 = gen_highpart (SImode, operands[0]);
1934  rtx high2 = gen_highpart (SImode, operands[2]);
1935  rtx low0 = gen_lowpart (SImode, operands[0]);
1936
1937  emit_insn (gen_clrt ());
1938  emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1939  emit_insn (gen_subc (high0, high0, high2));
1940  DONE;
1941})
1942
1943(define_insn "subc"
1944  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1945	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1946			    (match_operand:SI 2 "arith_reg_operand" "r"))
1947		  (reg:SI T_REG)))
1948   (set (reg:SI T_REG)
1949	(gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1950			  (reg:SI T_REG))
1951		(match_dup 1)))]
1952  "TARGET_SH1"
1953  "subc	%2,%0"
1954  [(set_attr "type" "arith")])
1955
1956;; A simplified version of the subc insn, where the exact value of the
1957;; T bit doesn't matter.  This is easier for combine to pick up.
1958;; We allow a reg or 0 for one of the operands in order to be able to
1959;; do 'reg - T' sequences.  Reload will load the constant 0 into the reg
1960;; as needed.
1961(define_insn "*subc"
1962  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1963	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1964			    (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1965		  (match_operand:SI 3 "t_reg_operand" "")))
1966   (clobber (reg:SI T_REG))]
1967  "TARGET_SH1"
1968  "subc	%2,%0"
1969  [(set_attr "type" "arith")])
1970
1971;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
1972;; better, if the sett insn can be done early.
1973;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
1974(define_insn_and_split "*subc"
1975  [(set (match_operand:SI 0 "arith_reg_dest" "")
1976	(plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
1977		 (match_operand:SI 2 "arith_reg_operand" "")))
1978   (clobber (reg:SI T_REG))]
1979  "TARGET_SH1"
1980  "#"
1981  "&& 1"
1982  [(set (reg:SI T_REG) (const_int 1))
1983   (parallel [(set (match_dup 0)
1984		   (minus:SI (minus:SI (match_dup 2) (match_dup 1))
1985			     (reg:SI T_REG)))
1986	      (clobber (reg:SI T_REG))])])
1987
1988;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
1989;; If the 0 constant can be CSE-ed, this becomes a one instruction
1990;; operation, as opposed to sequences such as
1991;;	movt	r2
1992;;	sub	r2,r3
1993;;
1994;; Even if the constant is not CSE-ed, a sequence such as
1995;;	mov	#0,r2
1996;;	subc	r2,r3
1997;; can be scheduled much better since the load of the constant can be
1998;; done earlier, before any comparison insns that store the result in
1999;; the T bit.
2000(define_insn_and_split "*subc"
2001  [(set (match_operand:SI 0 "arith_reg_dest" "")
2002	(minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2003		  (match_operand:SI 2 "t_reg_operand" "")))
2004   (clobber (reg:SI T_REG))]
2005  "TARGET_SH1"
2006  "#"
2007  "&& 1"
2008  [(parallel [(set (match_dup 0)
2009		   (minus:SI (minus:SI (match_dup 1) (const_int 0))
2010			     (match_dup 2)))
2011	      (clobber (reg:SI T_REG))])])
2012
2013(define_insn "*subsi3_internal"
2014  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2015	(minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2016		  (match_operand:SI 2 "arith_reg_operand" "r")))]
2017  "TARGET_SH1"
2018  "sub	%2,%0"
2019  [(set_attr "type" "arith")])
2020
2021(define_insn_and_split "*subsi3_media"
2022  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2023	(minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2024		  (match_operand:SI 2 "extend_reg_operand" "r")))]
2025  "TARGET_SHMEDIA
2026   && (operands[1] != constm1_rtx
2027       || (GET_CODE (operands[2]) != TRUNCATE
2028	   && GET_CODE (operands[2]) != SUBREG))"
2029  "sub.l	%N1, %2, %0"
2030  "operands[1] == constm1_rtx"
2031  [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2032  ""
2033  [(set_attr "type" "arith_media")
2034   (set_attr "highpart" "ignore")])
2035
2036(define_split
2037  [(set (match_operand:SI 0 "arith_reg_dest" "")
2038	(zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2039						       "general_extend_operand"
2040						       "") 0)) 0)))]
2041  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2042  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2043   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2044  "")
2045
2046(define_split
2047  [(set (match_operand:SI 0 "arith_reg_dest" "")
2048	(zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2049						       "general_extend_operand"
2050						       "") 0)) 3)))]
2051  "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
2052  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2053   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2054  "")
2055
2056;; Convert
2057;;	constant - reg
2058;; to
2059;;	neg reg
2060;;	add reg, #const
2061;; since this will sometimes save one instruction.
2062;; Otherwise we might get a sequence like
2063;;	mov #const, rY
2064;;	sub rY, rX
2065;;	mov rX, rY
2066;; if the source and dest regs are the same.
2067(define_expand "subsi3"
2068  [(set (match_operand:SI 0 "arith_reg_operand" "")
2069	(minus:SI (match_operand:SI 1 "arith_operand" "")
2070		  (match_operand:SI 2 "arith_reg_operand" "")))]
2071  ""
2072{
2073  if (TARGET_SH1 && CONST_INT_P (operands[1]))
2074    {
2075      emit_insn (gen_negsi2 (operands[0], operands[2]));
2076      emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2077      DONE;
2078    }
2079  if (TARGET_SHMEDIA)
2080    {
2081      if (!can_create_pseudo_p ()
2082	  && ! arith_reg_or_0_operand (operands[1], SImode))
2083	FAIL;
2084      if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2085	operands[1] = force_reg (SImode, operands[1]);
2086    }
2087})
2088
2089;; -------------------------------------------------------------------------
2090;; Division instructions
2091;; -------------------------------------------------------------------------
2092
2093;; We take advantage of the library routines which don't clobber as many
2094;; registers as a normal function call would.
2095
2096;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2097;; also has an effect on the register that holds the address of the sfunc.
2098;; To make this work, we have an extra dummy insn that shows the use
2099;; of this register for reorg.
2100
2101(define_insn "use_sfunc_addr"
2102  [(set (reg:SI PR_REG)
2103	(unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2104  "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2105  ""
2106  [(set_attr "length" "0")])
2107
2108(define_insn "udivsi3_sh2a"
2109  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2110	(udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2111		(match_operand:SI 2 "arith_reg_operand" "z")))]
2112  "TARGET_SH2A"
2113  "divu	%2,%1"
2114  [(set_attr "type" "arith")
2115   (set_attr "in_delay_slot" "no")])
2116
2117;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2118;; hard register 0.  If we used hard register 0, then the next instruction
2119;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
2120;; gets allocated to a stack slot that needs its address reloaded, then
2121;; there is nothing to prevent reload from using r0 to reload the address.
2122;; This reload would clobber the value in r0 we are trying to store.
2123;; If we let reload allocate r0, then this problem can never happen.
2124(define_insn "udivsi3_i1"
2125  [(set (match_operand:SI 0 "register_operand" "=z")
2126	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2127   (clobber (reg:SI T_REG))
2128   (clobber (reg:SI PR_REG))
2129   (clobber (reg:SI R1_REG))
2130   (clobber (reg:SI R4_REG))
2131   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2132  "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2133  "jsr	@%1%#"
2134  [(set_attr "type" "sfunc")
2135   (set_attr "needs_delay_slot" "yes")])
2136
2137; Since shmedia-nofpu code could be linked against shcompact code, and
2138; the udivsi3 libcall has the same name, we must consider all registers
2139; clobbered that are in the union of the registers clobbered by the
2140; shmedia and the shcompact implementation.  Note, if the shcompact
2141; implementation actually used shcompact code, we'd need to clobber
2142; also r23 and fr23.
2143(define_insn "udivsi3_i1_media"
2144  [(set (match_operand:SI 0 "register_operand" "=z")
2145	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2146   (clobber (reg:SI T_MEDIA_REG))
2147   (clobber (reg:SI PR_MEDIA_REG))
2148   (clobber (reg:SI R20_REG))
2149   (clobber (reg:SI R21_REG))
2150   (clobber (reg:SI R22_REG))
2151   (clobber (reg:DI TR0_REG))
2152   (clobber (reg:DI TR1_REG))
2153   (clobber (reg:DI TR2_REG))
2154   (use (match_operand 1 "target_reg_operand" "b"))]
2155  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2156  "blink	%1, r18"
2157  [(set_attr "type" "sfunc")
2158   (set_attr "needs_delay_slot" "yes")])
2159
2160(define_expand "udivsi3_i4_media"
2161  [(set (match_dup 3)
2162	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2163   (set (match_dup 4)
2164	(zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2165   (set (match_dup 5) (float:DF (match_dup 3)))
2166   (set (match_dup 6) (float:DF (match_dup 4)))
2167   (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2168   (set (match_dup 8) (fix:DI (match_dup 7)))
2169   (set (match_operand:SI 0 "register_operand" "")
2170	(truncate:SI (match_dup 8)))]
2171  "TARGET_SHMEDIA_FPU"
2172{
2173  operands[3] = gen_reg_rtx (DImode);
2174  operands[4] = gen_reg_rtx (DImode);
2175  operands[5] = gen_reg_rtx (DFmode);
2176  operands[6] = gen_reg_rtx (DFmode);
2177  operands[7] = gen_reg_rtx (DFmode);
2178  operands[8] = gen_reg_rtx (DImode);
2179})
2180
2181(define_insn "udivsi3_i4"
2182  [(set (match_operand:SI 0 "register_operand" "=y")
2183	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2184   (clobber (reg:SI T_REG))
2185   (clobber (reg:SI PR_REG))
2186   (clobber (reg:DF DR0_REG))
2187   (clobber (reg:DF DR2_REG))
2188   (clobber (reg:DF DR4_REG))
2189   (clobber (reg:SI R0_REG))
2190   (clobber (reg:SI R1_REG))
2191   (clobber (reg:SI R4_REG))
2192   (clobber (reg:SI R5_REG))
2193   (use (reg:PSI FPSCR_REG))
2194   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2195  "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2196  "jsr	@%1%#"
2197  [(set_attr "type" "sfunc")
2198   (set_attr "fp_mode" "double")
2199   (set_attr "needs_delay_slot" "yes")])
2200
2201(define_insn "udivsi3_i4_single"
2202  [(set (match_operand:SI 0 "register_operand" "=y")
2203	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2204   (clobber (reg:SI T_REG))
2205   (clobber (reg:SI PR_REG))
2206   (clobber (reg:DF DR0_REG))
2207   (clobber (reg:DF DR2_REG))
2208   (clobber (reg:DF DR4_REG))
2209   (clobber (reg:SI R0_REG))
2210   (clobber (reg:SI R1_REG))
2211   (clobber (reg:SI R4_REG))
2212   (clobber (reg:SI R5_REG))
2213   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2214  "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2215   && TARGET_FPU_SINGLE"
2216  "jsr	@%1%#"
2217  [(set_attr "type" "sfunc")
2218   (set_attr "needs_delay_slot" "yes")])
2219
2220(define_insn "udivsi3_i4_int"
2221  [(set (match_operand:SI 0 "register_operand" "=z")
2222	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2223   (clobber (reg:SI T_REG))
2224   (clobber (reg:SI R1_REG))
2225   (clobber (reg:SI PR_REG))
2226   (clobber (reg:SI MACH_REG))
2227   (clobber (reg:SI MACL_REG))
2228   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2229  "TARGET_SH1"
2230  "jsr	@%1%#"
2231  [(set_attr "type" "sfunc")
2232   (set_attr "needs_delay_slot" "yes")])
2233
2234
2235(define_expand "udivsi3"
2236  [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2237   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2238   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2239   (parallel [(set (match_operand:SI 0 "register_operand" "")
2240		   (udiv:SI (reg:SI R4_REG)
2241			    (reg:SI R5_REG)))
2242	      (clobber (reg:SI T_REG))
2243	      (clobber (reg:SI PR_REG))
2244	      (clobber (reg:SI R4_REG))
2245	      (use (match_dup 3))])]
2246  ""
2247{
2248  rtx last;
2249
2250  operands[3] = gen_reg_rtx (Pmode);
2251  /* Emit the move of the address to a pseudo outside of the libcall.  */
2252  if (TARGET_DIVIDE_CALL_TABLE)
2253    {
2254      /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2255	 that causes problems when the divide code is supposed to come from a
2256	 separate library.  Division by zero is undefined, so dividing 1 can be
2257	 implemented by comparing with the divisor.  */
2258      if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2259	{
2260	  rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2261	  emit_insn (gen_cstoresi4 (operands[0], test,
2262				    operands[1], operands[2]));
2263	  DONE;
2264	}
2265      else if (operands[2] == const0_rtx)
2266	{
2267	  emit_move_insn (operands[0], operands[2]);
2268	  DONE;
2269	}
2270      function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2271      last = gen_udivsi3_i4_int (operands[0], operands[3]);
2272    }
2273  else if (TARGET_DIVIDE_CALL_FP)
2274    {
2275      function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
2276      if (TARGET_FPU_SINGLE)
2277	last = gen_udivsi3_i4_single (operands[0], operands[3]);
2278      else
2279	last = gen_udivsi3_i4 (operands[0], operands[3]);
2280    }
2281  else if (TARGET_SHMEDIA_FPU)
2282    {
2283      operands[1] = force_reg (SImode, operands[1]);
2284      operands[2] = force_reg (SImode, operands[2]);
2285      emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2286      DONE;
2287    }
2288  else if (TARGET_SH2A)
2289    {
2290      operands[1] = force_reg (SImode, operands[1]);
2291      operands[2] = force_reg (SImode, operands[2]);
2292      emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2293      DONE;
2294    }
2295  else if (TARGET_SH5)
2296    {
2297      function_symbol (operands[3],
2298		       TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2299		       SFUNC_STATIC);
2300
2301      if (TARGET_SHMEDIA)
2302	last = gen_udivsi3_i1_media (operands[0], operands[3]);
2303      else if (TARGET_FPU_ANY)
2304	last = gen_udivsi3_i4_single (operands[0], operands[3]);
2305      else
2306	last = gen_udivsi3_i1 (operands[0], operands[3]);
2307    }
2308  else
2309    {
2310      function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
2311      last = gen_udivsi3_i1 (operands[0], operands[3]);
2312    }
2313  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2314  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2315  emit_insn (last);
2316  DONE;
2317})
2318
2319(define_insn "divsi3_sh2a"
2320  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2321	(div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2322		(match_operand:SI 2 "arith_reg_operand" "z")))]
2323  "TARGET_SH2A"
2324  "divs	%2,%1"
2325  [(set_attr "type" "arith")
2326   (set_attr "in_delay_slot" "no")])
2327
2328(define_insn "divsi3_i1"
2329  [(set (match_operand:SI 0 "register_operand" "=z")
2330	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2331   (clobber (reg:SI T_REG))
2332   (clobber (reg:SI PR_REG))
2333   (clobber (reg:SI R1_REG))
2334   (clobber (reg:SI R2_REG))
2335   (clobber (reg:SI R3_REG))
2336   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2337  "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2338  "jsr	@%1%#"
2339  [(set_attr "type" "sfunc")
2340   (set_attr "needs_delay_slot" "yes")])
2341
2342(define_insn "divsi3_i1_media"
2343  [(set (match_operand:SI 0 "register_operand" "=z")
2344	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2345   (clobber (reg:SI T_MEDIA_REG))
2346   (clobber (reg:SI PR_MEDIA_REG))
2347   (clobber (reg:SI R1_REG))
2348   (clobber (reg:SI R20_REG))
2349   (clobber (reg:SI R21_REG))
2350   (clobber (reg:SI TR0_REG))
2351   (use (match_operand 1 "target_reg_operand" "b"))]
2352  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2353  "blink	%1, r18"
2354  [(set_attr "type" "sfunc")])
2355
2356(define_insn "divsi3_media_2"
2357  [(set (match_operand:SI 0 "register_operand" "=z")
2358	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2359   (clobber (reg:SI T_MEDIA_REG))
2360   (clobber (reg:SI PR_MEDIA_REG))
2361   (clobber (reg:SI R1_REG))
2362   (clobber (reg:SI R21_REG))
2363   (clobber (reg:SI TR0_REG))
2364   (use (reg:SI R20_REG))
2365   (use (match_operand 1 "target_reg_operand" "b"))]
2366  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2367  "blink	%1, r18"
2368  [(set_attr "type" "sfunc")])
2369
2370;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2371;; hard reg clobbers and data dependencies that we need when we want
2372;; to rematerialize the division into a call.
2373(define_insn_and_split "divsi_inv_call"
2374  [(set (match_operand:SI 0 "register_operand" "=r")
2375	(div:SI (match_operand:SI 1 "register_operand" "r")
2376		(match_operand:SI 2 "register_operand" "r")))
2377   (clobber (reg:SI R4_REG))
2378   (clobber (reg:SI R5_REG))
2379   (clobber (reg:SI T_MEDIA_REG))
2380   (clobber (reg:SI PR_MEDIA_REG))
2381   (clobber (reg:SI R1_REG))
2382   (clobber (reg:SI R21_REG))
2383   (clobber (reg:SI TR0_REG))
2384   (clobber (reg:SI R20_REG))
2385   (use (match_operand:SI 3 "register_operand" "r"))]
2386  "TARGET_SHMEDIA"
2387  "#"
2388  "&& (reload_in_progress || reload_completed)"
2389  [(set (match_dup 0) (match_dup 3))]
2390  ""
2391  [(set_attr "highpart" "must_split")])
2392
2393;; This is the combiner pattern for -mdiv=inv:call .
2394(define_insn_and_split "*divsi_inv_call_combine"
2395  [(set (match_operand:SI 0 "register_operand" "=z")
2396	(div:SI (match_operand:SI 1 "register_operand" "r")
2397		(match_operand:SI 2 "register_operand" "r")))
2398   (clobber (reg:SI R4_REG))
2399   (clobber (reg:SI R5_REG))
2400   (clobber (reg:SI T_MEDIA_REG))
2401   (clobber (reg:SI PR_MEDIA_REG))
2402   (clobber (reg:SI R1_REG))
2403   (clobber (reg:SI R21_REG))
2404   (clobber (reg:SI TR0_REG))
2405   (clobber (reg:SI R20_REG))
2406   (use (unspec:SI [(match_dup 1)
2407		    (match_operand:SI 3 "" "")
2408		    (unspec:SI [(match_operand:SI 4 "" "")
2409				(match_dup 3)
2410				(match_operand:DI 5 "" "")]
2411		     UNSPEC_DIV_INV_M2)
2412		    (match_operand:DI 6 "" "")
2413		    (const_int 0)
2414		    (const_int 0)]
2415	 UNSPEC_DIV_INV_M3))]
2416  "TARGET_SHMEDIA"
2417  "#"
2418  "&& (reload_in_progress || reload_completed)"
2419  [(pc)]
2420{
2421  const char *name = sh_divsi3_libfunc;
2422  enum sh_function_kind kind = SFUNC_GOT;
2423  rtx sym;
2424
2425  emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2426  emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2427  while (TARGET_DIVIDE_INV_CALL2)
2428    {
2429      rtx x = operands[3];
2430
2431      if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2432	break;
2433      x = XVECEXP (x, 0, 0);
2434      name = "__sdivsi3_2";
2435      kind = SFUNC_STATIC;
2436      emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2437      break;
2438    }
2439  sym = function_symbol (NULL, name, kind);
2440  emit_insn (gen_divsi3_media_2 (operands[0], sym));
2441  DONE;
2442}
2443  [(set_attr "highpart" "must_split")])
2444
2445(define_expand "divsi3_i4_media"
2446  [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2447   (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2448   (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2449   (set (match_operand:SI 0 "register_operand" "=r")
2450	(fix:SI (match_dup 5)))]
2451  "TARGET_SHMEDIA_FPU"
2452{
2453  operands[3] = gen_reg_rtx (DFmode);
2454  operands[4] = gen_reg_rtx (DFmode);
2455  operands[5] = gen_reg_rtx (DFmode);
2456})
2457
2458(define_insn "divsi3_i4"
2459  [(set (match_operand:SI 0 "register_operand" "=y")
2460	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2461   (clobber (reg:SI PR_REG))
2462   (clobber (reg:DF DR0_REG))
2463   (clobber (reg:DF DR2_REG))
2464   (use (reg:PSI FPSCR_REG))
2465   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2466  "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2467  "jsr	@%1%#"
2468  [(set_attr "type" "sfunc")
2469   (set_attr "fp_mode" "double")
2470   (set_attr "needs_delay_slot" "yes")])
2471
2472(define_insn "divsi3_i4_single"
2473  [(set (match_operand:SI 0 "register_operand" "=y")
2474	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2475   (clobber (reg:SI PR_REG))
2476   (clobber (reg:DF DR0_REG))
2477   (clobber (reg:DF DR2_REG))
2478   (clobber (reg:SI R2_REG))
2479   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2480  "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2481   && TARGET_FPU_SINGLE"
2482  "jsr	@%1%#"
2483  [(set_attr "type" "sfunc")
2484   (set_attr "needs_delay_slot" "yes")])
2485
2486(define_insn "divsi3_i4_int"
2487  [(set (match_operand:SI 0 "register_operand" "=z")
2488	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2489   (clobber (reg:SI T_REG))
2490   (clobber (reg:SI PR_REG))
2491   (clobber (reg:SI R1_REG))
2492   (clobber (reg:SI MACH_REG))
2493   (clobber (reg:SI MACL_REG))
2494   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2495  "TARGET_SH1"
2496  "jsr	@%1%#"
2497  [(set_attr "type" "sfunc")
2498   (set_attr "needs_delay_slot" "yes")])
2499
2500(define_expand "divsi3"
2501  [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2502   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2503   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2504   (parallel [(set (match_operand:SI 0 "register_operand" "")
2505		   (div:SI (reg:SI R4_REG)
2506			   (reg:SI R5_REG)))
2507	      (clobber (reg:SI T_REG))
2508	      (clobber (reg:SI PR_REG))
2509	      (clobber (reg:SI R1_REG))
2510	      (clobber (reg:SI R2_REG))
2511	      (clobber (reg:SI R3_REG))
2512	      (use (match_dup 3))])]
2513  ""
2514{
2515  rtx last;
2516
2517  operands[3] = gen_reg_rtx (Pmode);
2518  /* Emit the move of the address to a pseudo outside of the libcall.  */
2519  if (TARGET_DIVIDE_CALL_TABLE)
2520    {
2521      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2522      last = gen_divsi3_i4_int (operands[0], operands[3]);
2523    }
2524  else if (TARGET_DIVIDE_CALL_FP)
2525    {
2526      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2527      if (TARGET_FPU_SINGLE)
2528	last = gen_divsi3_i4_single (operands[0], operands[3]);
2529      else
2530	last = gen_divsi3_i4 (operands[0], operands[3]);
2531    }
2532  else if (TARGET_SH2A)
2533    {
2534      operands[1] = force_reg (SImode, operands[1]);
2535      operands[2] = force_reg (SImode, operands[2]);
2536      emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2537      DONE;
2538    }
2539  else if (TARGET_DIVIDE_INV)
2540    {
2541      rtx dividend = operands[1];
2542      rtx divisor = operands[2];
2543      rtx tab_base;
2544      rtx nsb_res = gen_reg_rtx (DImode);
2545      rtx norm64 = gen_reg_rtx (DImode);
2546      rtx tab_ix = gen_reg_rtx (DImode);
2547      rtx norm32 = gen_reg_rtx (SImode);
2548      rtx i92 = force_reg (DImode, GEN_INT (92));
2549      rtx scratch0a = gen_reg_rtx (DImode);
2550      rtx scratch0b = gen_reg_rtx (DImode);
2551      rtx inv0 = gen_reg_rtx (SImode);
2552      rtx scratch1a = gen_reg_rtx (DImode);
2553      rtx scratch1b = gen_reg_rtx (DImode);
2554      rtx shift = gen_reg_rtx (DImode);
2555      rtx i2p27, i43;
2556      rtx inv1 = gen_reg_rtx (SImode);
2557      rtx scratch2a = gen_reg_rtx (DImode);
2558      rtx scratch2b = gen_reg_rtx (SImode);
2559      rtx inv2 = gen_reg_rtx (SImode);
2560      rtx scratch3a = gen_reg_rtx (DImode);
2561      rtx scratch3b = gen_reg_rtx (DImode);
2562      rtx scratch3c = gen_reg_rtx (DImode);
2563      rtx scratch3d = gen_reg_rtx (SImode);
2564      rtx scratch3e = gen_reg_rtx (DImode);
2565      rtx result = gen_reg_rtx (SImode);
2566
2567      if (! arith_reg_or_0_operand (dividend, SImode))
2568	dividend = force_reg (SImode, dividend);
2569      if (! arith_reg_operand (divisor, SImode))
2570	divisor = force_reg (SImode, divisor);
2571      if (flag_pic && Pmode != DImode)
2572	{
2573	  tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2574	  tab_base = gen_datalabel_ref (tab_base);
2575	  tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2576	}
2577      else
2578	{
2579	  tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
2580	  tab_base = gen_datalabel_ref (tab_base);
2581	  tab_base = force_reg (DImode, tab_base);
2582	}
2583      if (TARGET_DIVIDE_INV20U)
2584	i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2585      else
2586	i2p27 = GEN_INT (0);
2587      if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2588	i43 = force_reg (DImode, GEN_INT (43));
2589      else
2590	i43 = GEN_INT (0);
2591      emit_insn (gen_nsbdi (nsb_res,
2592			    simplify_gen_subreg (DImode, divisor, SImode, 0)));
2593      emit_insn (gen_ashldi3_media (norm64,
2594				    gen_rtx_SUBREG (DImode, divisor, 0),
2595				    nsb_res));
2596      emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2597      emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2598      emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2599				   inv0, scratch0a, scratch0b,
2600				   scratch1a, scratch1b));
2601      emit_insn (gen_subdi3 (shift, i92, nsb_res));
2602      emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2603				   scratch2a));
2604      emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2605				   i2p27, i43,
2606				   scratch3a, scratch3b, scratch3c,
2607				   scratch2a, scratch2b, scratch3d, scratch3e));
2608      if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2609	emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2610      else if (TARGET_DIVIDE_INV_FP)
2611	emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2612				     gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2613				     gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2614				     gen_reg_rtx (DFmode)));
2615      else
2616	emit_move_insn (operands[0], result);
2617      DONE;
2618    }
2619  else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2620    {
2621      operands[1] = force_reg (SImode, operands[1]);
2622      operands[2] = force_reg (SImode, operands[2]);
2623      emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2624      DONE;
2625    }
2626  else if (TARGET_SH5)
2627    {
2628      if (TARGET_DIVIDE_CALL2)
2629	{
2630	  rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2631	  tab_base = gen_datalabel_ref (tab_base);
2632	  emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2633	}
2634      if (TARGET_FPU_ANY && TARGET_SH1)
2635	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2636      else if (TARGET_DIVIDE_CALL2)
2637	function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
2638      else
2639	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2640
2641      if (TARGET_SHMEDIA)
2642	last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2643		(operands[0], operands[3]));
2644      else if (TARGET_FPU_ANY)
2645	last = gen_divsi3_i4_single (operands[0], operands[3]);
2646      else
2647	last = gen_divsi3_i1 (operands[0], operands[3]);
2648    }
2649  else
2650    {
2651      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2652      last = gen_divsi3_i1 (operands[0], operands[3]);
2653    }
2654  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2655  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2656  emit_insn (last);
2657  DONE;
2658})
2659
2660;; operands: scratch, tab_base, tab_ix
2661;; These are unspecs because we could generate an indexed addressing mode
2662;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2663;; confuse reload.  See PR27117.
2664(define_insn "divsi_inv_qitable"
2665  [(set (match_operand:DI 0 "register_operand" "=r")
2666	(zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2667				    (match_operand:DI 2 "register_operand" "r")]
2668			 UNSPEC_DIV_INV_TABLE)))]
2669  "TARGET_SHMEDIA"
2670  "ldx.ub	%1, %2, %0"
2671  [(set_attr "type" "load_media")
2672   (set_attr "highpart" "user")])
2673
2674;; operands: scratch, tab_base, tab_ix
2675(define_insn "divsi_inv_hitable"
2676  [(set (match_operand:DI 0 "register_operand" "=r")
2677	(sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2678				    (match_operand:DI 2 "register_operand" "r")]
2679			 UNSPEC_DIV_INV_TABLE)))]
2680  "TARGET_SHMEDIA"
2681  "ldx.w	%1, %2, %0"
2682  [(set_attr "type" "load_media")
2683   (set_attr "highpart" "user")])
2684
2685;; operands: inv0, tab_base, tab_ix, norm32
2686;; scratch equiv in sdivsi3_2: r19, r21
2687(define_expand "divsi_inv_m0"
2688  [(set (match_operand:SI 0 "register_operand" "=r")
2689	(unspec:SI [(match_operand:DI 1 "register_operand" "r")
2690		    (match_operand:DI 2 "register_operand" "r")
2691		    (match_operand:SI 3 "register_operand" "r")]
2692	 UNSPEC_DIV_INV_M0))
2693   (clobber (match_operand:DI 4 "register_operand" "=r"))
2694   (clobber (match_operand:DI 5 "register_operand" "=r"))]
2695  "TARGET_SHMEDIA"
2696{
2697/*
2698tab_base: r20
2699tab_ix: r21
2700norm32: r25
2701 ldx.ub r20, r21, r19 // u0.8
2702 shlli r21, 1, r21
2703 muls.l r25, r19, r19 // s2.38
2704 ldx.w r20, r21, r21  // s2.14
2705 shari r19, 24, r19   // truncate to s2.14
2706 sub r21, r19, r19    // some 11 bit inverse in s1.14
2707*/
2708
2709  rtx inv0 = operands[0];
2710  rtx tab_base = operands[1];
2711  rtx tab_ix = operands[2];
2712  rtx norm32 = operands[3];
2713  rtx scratch0 = operands[4];
2714  rtx scratch0_si = gen_lowpart (SImode, scratch0);
2715  rtx scratch1 = operands[5];
2716
2717  emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2718  emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2719  emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2720  emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2721  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2722  emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2723  DONE;
2724})
2725
2726;; operands: inv1, tab_base, tab_ix, norm32
2727(define_insn_and_split "divsi_inv_m1"
2728  [(set (match_operand:SI 0 "register_operand" "=r")
2729	(unspec:SI [(match_operand:DI 1 "register_operand" "r")
2730		    (match_operand:DI 2 "register_operand" "r")
2731		    (match_operand:SI 3 "register_operand" "r")]
2732	 UNSPEC_DIV_INV_M1))
2733   (clobber (match_operand:SI 4 "register_operand" "=r"))
2734   (clobber (match_operand:DI 5 "register_operand" "=r"))
2735   (clobber (match_operand:DI 6 "register_operand" "=r"))
2736   (clobber (match_operand:DI 7 "register_operand" "=r"))
2737   (clobber (match_operand:DI 8 "register_operand" "=r"))]
2738  "TARGET_SHMEDIA"
2739  "#"
2740  "&& !can_create_pseudo_p ()"
2741  [(pc)]
2742{
2743/* inv0: r19
2744 muls.l r19, r19, r18 // u0.28
2745 muls.l r25, r18, r18 // s2.58
2746 shlli r19, 45, r0    // multiply by two and convert to s2.58
2747 sub r0, r18, r18
2748 shari r18, 28, r18   // some 18 bit inverse in s1.30
2749*/
2750
2751  rtx inv1 = operands[0];
2752  rtx tab_base = operands[1];
2753  rtx tab_ix = operands[2];
2754  rtx norm32 = operands[3];
2755  rtx inv0 = operands[4];
2756  rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2757  rtx scratch0a = operands[5];
2758  rtx scratch0b = operands[6];
2759  rtx scratch0 = operands[7];
2760  rtx scratch1 = operands[8];
2761  rtx scratch1_si = gen_lowpart (SImode, scratch1);
2762
2763  emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2764			       scratch0a, scratch0b));
2765  emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2766  emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2767  emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2768  emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2769  emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2770  DONE;
2771})
2772
2773;; operands: inv2, norm32, inv1, i92
2774(define_insn_and_split "divsi_inv_m2"
2775  [(set (match_operand:SI 0 "register_operand" "=r")
2776	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
2777		    (match_operand:SI 2 "register_operand" "r")
2778		    (match_operand:DI 3 "register_operand" "r")]
2779	 UNSPEC_DIV_INV_M2))
2780   (clobber (match_operand:DI 4 "register_operand" "=r"))]
2781  "TARGET_SHMEDIA"
2782  "#"
2783  "&& !can_create_pseudo_p ()"
2784  [(pc)]
2785{
2786/*
2787 muls.l r18, r25, r0  // s2.60
2788 shari r0, 16, r0     // s-16.44
2789  sub
2790 muls.l r0, r18, r19  // s-16.74
2791 shari r19, 30, r19   // s-16.44
2792*/
2793  rtx inv2 = operands[0];
2794  rtx norm32 = operands[1];
2795  rtx inv1 = operands[2];
2796  rtx i92 = operands[3];
2797  rtx scratch0 = operands[4];
2798  rtx scratch0_si = gen_lowpart (SImode, scratch0);
2799
2800  emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2801  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2802  emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2803  emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2804  emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2805  DONE;
2806})
2807
2808(define_insn_and_split "divsi_inv_m3"
2809  [(set (match_operand:SI 0 "register_operand" "=r")
2810	(unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2811		    (match_operand:SI 2 "register_operand" "r")
2812		    (match_operand:SI 3 "register_operand" "r")
2813		    (match_operand:DI 4 "register_operand" "r")
2814		    (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2815		    (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2816	 UNSPEC_DIV_INV_M3))
2817   (clobber (match_operand:DI 7 "register_operand" "=r"))
2818   (clobber (match_operand:DI 8 "register_operand" "=r"))
2819   (clobber (match_operand:DI 9 "register_operand" "=r"))
2820   (clobber (match_operand:DI 10 "register_operand" "=r"))
2821   (clobber (match_operand:SI 11 "register_operand" "=r"))
2822   (clobber (match_operand:SI 12 "register_operand" "=r"))
2823   (clobber (match_operand:DI 13 "register_operand" "=r"))]
2824  "TARGET_SHMEDIA"
2825  "#"
2826  "&& !can_create_pseudo_p ()"
2827  [(pc)]
2828{
2829/*
2830  r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
2831  r0: scratch0  r19: scratch1 r21: scratch2
2832
2833  muls.l r18, r4, r25 // s32.30
2834 muls.l r19, r4, r19  // s15.30
2835 shari r25, 63, r21
2836  shari r19, 14, r19  // s18.-14
2837 sub r25, r19, r0
2838 shard r0, r1, r0
2839 sub r0, r21, r0
2840*/
2841
2842  rtx result = operands[0];
2843  rtx dividend = operands[1];
2844  rtx inv1 = operands[2];
2845  rtx inv2 = operands[3];
2846  rtx shift = operands[4];
2847  rtx scratch0 = operands[7];
2848  rtx scratch1 = operands[8];
2849  rtx scratch2 = operands[9];
2850
2851  if (satisfies_constraint_N (dividend))
2852    {
2853      emit_move_insn (result, dividend);
2854      DONE;
2855    }
2856
2857  emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2858  emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2859  emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2860  emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2861  emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2862  emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2863  emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2864  DONE;
2865})
2866
2867;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2868;; inv1: tab_base, tab_ix, norm32
2869;; inv2: norm32, inv1, i92
2870(define_insn_and_split "divsi_inv_m1_3"
2871  [(set (match_operand:SI 0 "register_operand" "=r")
2872	(unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2873		    (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2874				(match_operand:DI 3 "register_operand" "r")
2875				(match_operand:SI 4 "register_operand" "r")]
2876		     UNSPEC_DIV_INV_M1)
2877		    (unspec:SI [(match_dup 4)
2878				(unspec:SI [(match_dup 2)
2879					    (match_dup 3)
2880					    (match_dup 4)] UNSPEC_DIV_INV_M1)
2881				(match_operand:SI 5 "" "")]
2882		     UNSPEC_DIV_INV_M2)
2883		    (match_operand:DI 6 "register_operand" "r")
2884		    (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2885		    (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2886	 UNSPEC_DIV_INV_M3))
2887   (clobber (match_operand:DI 9 "register_operand" "=r"))
2888   (clobber (match_operand:DI 10 "register_operand" "=r"))
2889   (clobber (match_operand:DI 11 "register_operand" "=r"))
2890   (clobber (match_operand:DI 12 "register_operand" "=r"))
2891   (clobber (match_operand:SI 13 "register_operand" "=r"))
2892   (clobber (match_operand:SI 14 "register_operand" "=r"))
2893   (clobber (match_operand:DI 15 "register_operand" "=r"))]
2894  "TARGET_SHMEDIA
2895   && (TARGET_DIVIDE_INV_MINLAT
2896       || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2897  "#"
2898  "&& !can_create_pseudo_p ()"
2899  [(pc)]
2900{
2901  rtx result = operands[0];
2902  rtx dividend = operands[1];
2903  rtx tab_base = operands[2];
2904  rtx tab_ix = operands[3];
2905  rtx norm32 = operands[4];
2906  /* rtx i92 = operands[5]; */
2907  rtx shift = operands[6];
2908  rtx i2p27 = operands[7];
2909  rtx i43 = operands[8];
2910  rtx scratch0 = operands[9];
2911  rtx scratch0_si = gen_lowpart (SImode, scratch0);
2912  rtx scratch1 = operands[10];
2913  rtx scratch1_si = gen_lowpart (SImode, scratch1);
2914  rtx scratch2 = operands[11];
2915  rtx scratch3 = operands[12];
2916  rtx scratch4 = operands[13];
2917  rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2918  rtx scratch5 = operands[14];
2919  rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2920  rtx scratch6 = operands[15];
2921
2922  emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2923			       scratch0, scratch1));
2924  /* inv0 == scratch4 */
2925  if (! TARGET_DIVIDE_INV20U)
2926    {
2927      emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2928      i2p27 = scratch0;
2929      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2930    }
2931  else
2932    {
2933      emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2934      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2935    }
2936  emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2937  emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2938  emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2939  /* inv1 == scratch4 */
2940
2941  if (TARGET_DIVIDE_INV_MINLAT)
2942    {
2943      emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2944      emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2945      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2946      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2947      emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2948      emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2949      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2950      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2951      emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2952      emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2953      emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2954    }
2955  else
2956    {
2957      rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2958      /* Use separate scratch regs for nsb and sign to allow scheduling.  */
2959      emit_insn (gen_nsbdi (scratch6,
2960			    simplify_gen_subreg (DImode, dividend, SImode, 0)));
2961      emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2962      emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2963      emit_insn (gen_divsi_inv20 (scratch2,
2964				  norm32, scratch4, dividend,
2965				  scratch6, scratch3, i43,
2966				  /* scratch0 may be shared with i2p27.  */
2967				  scratch0, scratch1, scratch5,
2968				  label, label, i2p27));
2969    }
2970  emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2971  emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2972  DONE;
2973})
2974
2975(define_insn "divsi_inv20"
2976  [(set (match_operand:DI 0 "register_operand" "=&r")
2977	(unspec:DI [(match_operand:SI 1 "register_operand" "r")
2978		    (match_operand:SI 2 "register_operand" "r")
2979		    (match_operand:SI 3 "register_operand" "r")
2980		    (match_operand:DI 4 "register_operand" "r")
2981		    (match_operand:DI 5 "register_operand" "r")
2982		    (match_operand:DI 6 "register_operand" "r")
2983		    (match_operand:DI 12 "register_operand" "r")
2984		    (match_operand 10 "target_operand" "b")
2985		    (match_operand 11 "immediate_operand" "i")]
2986	 UNSPEC_DIV_INV20))
2987   (clobber (match_operand:DI 7 "register_operand" "=&r"))
2988   (clobber (match_operand:DI 8 "register_operand" "=&r"))
2989   (clobber (match_operand:SI 9 "register_operand" "=r"))]
2990  "TARGET_SHMEDIA
2991   && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2992{
2993/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2994	     %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2995	     %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2996	     %10 label (tr), %11 label (imm)
2997
2998 muls.l inv1, norm32, scratch0  // s2.60
2999  muls.l inv1, dividend, result // s32.30
3000  xor i2p27, result_sign, round_scratch
3001 bge/u dividend_nsb, i43, tr.. (label)
3002 shari scratch0, 16, scratch0   // s-16.44
3003 muls.l sratch0_si, inv1, scratch0 // s-16.74
3004  sub result, round_scratch, result
3005  shari dividend, 14, scratch1   // s19.-14
3006 shari scratch0, 30, scratch0   // s-16.44
3007 muls.l scratch0, scratch1, round_scratch // s15.30
3008label:
3009 sub result, round_scratch, result */
3010
3011  const bool likely = TARGET_DIVIDE_INV20L;
3012  if (likely)
3013    return
3014	       "muls.l	%2, %3, %0"	"\n"
3015	"	xor	%12, %5, %7"	"\n"
3016	"	bge/l	%4, %6, %10"	"\n"
3017	"	muls.l	%2, %1, %8"	"\n"
3018	"	shari	%8, 16, %8"	"\n"
3019	"	muls.l	%8, %2, %8"	"\n"
3020	"	shari	%3, 14, %9"	"\n"
3021	"	shari	%8, 30, %8"	"\n"
3022	"	muls.l	%8, %9, %8"	"\n"
3023	"	sub	%0, %8, %0"	"\n"
3024	"%11:	add	%0, %7, %0";
3025  else
3026    return
3027	       "muls.l	%2, %1, %8"	"\n"
3028	"	muls.l	%2, %3, %0"	"\n"
3029	"	xor	%12, %5, %7"	"\n"
3030	"	bge/u	%4, %6, %10"	"\n"
3031	"	shari	%8, 16, %8"	"\n"
3032	"	muls.l	%8, %2, %8"	"\n"
3033	"	sub	%0, %7, %0"	"\n"
3034	"	shari	%3, 14, %9"	"\n"
3035	"	shari	%8, 30, %8"	"\n"
3036	"	muls.l	%8, %9, %7"	"\n"
3037	"%11:	sub	%0, %7, %0";
3038})
3039
3040(define_insn_and_split "divsi_inv_fp"
3041  [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3042	(div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3043		(match_operand:SI 2 "register_operand" "rf")))
3044   (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3045   (clobber (match_operand:SI 4 "register_operand" "=r"))
3046   (clobber (match_operand:SI 5 "register_operand" "=r"))
3047   (clobber (match_operand:DF 6 "register_operand" "=r"))
3048   (clobber (match_operand:DF 7 "register_operand" "=r"))
3049   (clobber (match_operand:DF 8 "register_operand" "=r"))]
3050  "TARGET_SHMEDIA_FPU"
3051  "#"
3052  "&& (reload_in_progress || reload_completed)"
3053  [(set (match_dup 0) (match_dup 3))]
3054  ""
3055  [(set_attr "highpart" "must_split")])
3056
3057;; If a matching group of divide-by-inverse instructions is in the same
3058;; basic block after gcse & loop optimizations, we want to transform them
3059;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3060(define_insn_and_split "*divsi_inv_fp_combine"
3061  [(set (match_operand:SI 0 "register_operand" "=f")
3062	(div:SI (match_operand:SI 1 "register_operand" "f")
3063		(match_operand:SI 2 "register_operand" "f")))
3064   (use (unspec:SI [(match_dup 1)
3065		    (match_operand:SI 3 "" "")
3066		    (unspec:SI [(match_operand:SI 4 "" "")
3067				(match_dup 3)
3068				(match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3069		    (match_operand:DI 6 "" "")
3070		    (const_int 0)
3071		    (const_int 0)] UNSPEC_DIV_INV_M3))
3072   (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3073   (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3074   (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3075   (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3076   (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3077  "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3078  "#"
3079  "&& 1"
3080  [(set (match_dup 9) (float:DF (match_dup 1)))
3081   (set (match_dup 10) (float:DF (match_dup 2)))
3082   (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3083   (set (match_dup 8)
3084	(fix:SI (match_dup 11)))
3085   (set (match_dup 0) (match_dup 8))]
3086{
3087  if (! fp_arith_reg_operand (operands[1], SImode))
3088    {
3089      emit_move_insn (operands[7], operands[1]);
3090      operands[1] = operands[7];
3091    }
3092  if (! fp_arith_reg_operand (operands[2], SImode))
3093    {
3094      emit_move_insn (operands[8], operands[2]);
3095      operands[2] = operands[8];
3096    }
3097}
3098  [(set_attr "highpart" "must_split")])
3099
3100;; -------------------------------------------------------------------------
3101;; Multiplication instructions
3102;; -------------------------------------------------------------------------
3103
3104(define_insn "umulhisi3_i"
3105  [(set (reg:SI MACL_REG)
3106	(mult:SI (zero_extend:SI
3107		  (match_operand:HI 0 "arith_reg_operand" "r"))
3108		 (zero_extend:SI
3109		  (match_operand:HI 1 "arith_reg_operand" "r"))))]
3110  "TARGET_SH1"
3111  "mulu.w	%1,%0"
3112  [(set_attr "type" "smpy")])
3113
3114(define_insn "mulhisi3_i"
3115  [(set (reg:SI MACL_REG)
3116	(mult:SI (sign_extend:SI
3117		  (match_operand:HI 0 "arith_reg_operand" "r"))
3118		 (sign_extend:SI
3119		  (match_operand:HI 1 "arith_reg_operand" "r"))))]
3120  "TARGET_SH1"
3121  "muls.w	%1,%0"
3122  [(set_attr "type" "smpy")])
3123
3124(define_expand "mulhisi3"
3125  [(set (reg:SI MACL_REG)
3126	(mult:SI (sign_extend:SI
3127		  (match_operand:HI 1 "arith_reg_operand" ""))
3128		 (sign_extend:SI
3129		  (match_operand:HI 2 "arith_reg_operand" ""))))
3130   (set (match_operand:SI 0 "arith_reg_operand" "")
3131	(reg:SI MACL_REG))]
3132  "TARGET_SH1"
3133{
3134  rtx insn, macl;
3135
3136  macl = gen_rtx_REG (SImode, MACL_REG);
3137  start_sequence ();
3138  emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3139  insn = get_insns ();  
3140  end_sequence ();
3141  /* expand_binop can't find a suitable code in umul_widen_optab to
3142     make a REG_EQUAL note from, so make one here.
3143     See also smulsi3_highpart.
3144     ??? Alternatively, we could put this at the calling site of expand_binop,
3145     i.e. expand_expr.  */
3146  /* Use emit_libcall_block for loop invariant code motion and to make
3147     a REG_EQUAL note.  */
3148  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3149
3150  DONE;
3151})
3152
3153(define_expand "umulhisi3"
3154  [(set (reg:SI MACL_REG)
3155	(mult:SI (zero_extend:SI
3156		  (match_operand:HI 1 "arith_reg_operand" ""))
3157		 (zero_extend:SI
3158		  (match_operand:HI 2 "arith_reg_operand" ""))))
3159   (set (match_operand:SI 0 "arith_reg_operand" "")
3160	(reg:SI MACL_REG))]
3161  "TARGET_SH1"
3162{
3163  rtx insn, macl;
3164
3165  macl = gen_rtx_REG (SImode, MACL_REG);
3166  start_sequence ();
3167  emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3168  insn = get_insns ();  
3169  end_sequence ();
3170  /* expand_binop can't find a suitable code in umul_widen_optab to
3171     make a REG_EQUAL note from, so make one here.
3172     See also smulsi3_highpart.
3173     ??? Alternatively, we could put this at the calling site of expand_binop,
3174     i.e. expand_expr.  */
3175  /* Use emit_libcall_block for loop invariant code motion and to make
3176     a REG_EQUAL note.  */
3177  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3178
3179  DONE;
3180})
3181
3182;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3183;; a call to a routine which clobbers known registers.
3184(define_insn ""
3185  [(set (match_operand:SI 1 "register_operand" "=z")
3186	(mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3187   (clobber (reg:SI MACL_REG))
3188   (clobber (reg:SI T_REG))
3189   (clobber (reg:SI PR_REG))
3190   (clobber (reg:SI R3_REG))
3191   (clobber (reg:SI R2_REG))
3192   (clobber (reg:SI R1_REG))
3193   (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3194  "TARGET_SH1"
3195  "jsr	@%0%#"
3196  [(set_attr "type" "sfunc")
3197   (set_attr "needs_delay_slot" "yes")])
3198
3199(define_expand "mulsi3_call"
3200  [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3201   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3202   (parallel[(set (match_operand:SI 0 "register_operand" "")
3203		  (mult:SI (reg:SI R4_REG)
3204			   (reg:SI R5_REG)))
3205	     (clobber (reg:SI MACL_REG))
3206	     (clobber (reg:SI T_REG))
3207	     (clobber (reg:SI PR_REG))
3208	     (clobber (reg:SI R3_REG))
3209	     (clobber (reg:SI R2_REG))
3210	     (clobber (reg:SI R1_REG))
3211	     (use (match_operand:SI 3 "register_operand" ""))])]
3212  "TARGET_SH1"
3213  "")
3214
3215(define_insn "mul_r"
3216  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3217	(mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3218		 (match_operand:SI 2 "arith_reg_operand" "z")))]
3219  "TARGET_SH2A"
3220  "mulr	%2,%0"
3221  [(set_attr "type" "dmpy")])
3222
3223(define_insn "mul_l"
3224  [(set (reg:SI MACL_REG)
3225	(mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3226		 (match_operand:SI 1 "arith_reg_operand" "r")))]
3227  "TARGET_SH2"
3228  "mul.l	%1,%0"
3229  [(set_attr "type" "dmpy")])
3230
3231(define_expand "mulsi3"
3232  [(set (reg:SI MACL_REG)
3233	(mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
3234		  (match_operand:SI 2 "arith_reg_operand" "")))
3235   (set (match_operand:SI 0 "arith_reg_operand" "")
3236	(reg:SI MACL_REG))]
3237  "TARGET_SH1"
3238{
3239  if (!TARGET_SH2)
3240    {
3241      /* The address must be set outside the libcall,
3242	 since it goes into a pseudo.  */
3243      rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
3244      rtx addr = force_reg (SImode, sym);
3245      rtx insns = gen_mulsi3_call (operands[0], operands[1],
3246				   operands[2], addr);
3247      emit_insn (insns);
3248    }
3249  else
3250    {
3251      rtx macl = gen_rtx_REG (SImode, MACL_REG);
3252
3253      emit_insn (gen_mul_l (operands[1], operands[2]));
3254      /* consec_sets_giv can only recognize the first insn that sets a
3255	 giv as the giv insn.  So we must tag this also with a REG_EQUAL
3256	 note.  */
3257      emit_insn (gen_movsi_i ((operands[0]), macl));
3258    }
3259  DONE;
3260})
3261
3262(define_insn "mulsidi3_i"
3263  [(set (reg:SI MACH_REG)
3264	(truncate:SI
3265	 (lshiftrt:DI
3266	  (mult:DI
3267	   (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3268	   (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3269	  (const_int 32))))
3270   (set (reg:SI MACL_REG)
3271	(mult:SI (match_dup 0)
3272		 (match_dup 1)))]
3273  "TARGET_SH2"
3274  "dmuls.l	%1,%0"
3275  [(set_attr "type" "dmpy")])
3276
3277(define_expand "mulsidi3"
3278  [(set (match_operand:DI 0 "arith_reg_dest" "")
3279	(mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3280		 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3281  "TARGET_SH2 || TARGET_SHMEDIA"
3282{
3283  if (TARGET_SH2)
3284    {
3285      emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3286      DONE;
3287    }
3288})
3289
3290(define_insn "mulsidi3_media"
3291  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3292	(mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3293		 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3294  "TARGET_SHMEDIA"
3295  "muls.l	%1, %2, %0"
3296  [(set_attr "type" "dmpy_media")
3297   (set_attr "highpart" "ignore")])
3298
3299(define_insn_and_split "mulsidi3_compact"
3300  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3301	(mult:DI
3302	 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3303	 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3304   (clobber (reg:SI MACH_REG))
3305   (clobber (reg:SI MACL_REG))]
3306  "TARGET_SH2"
3307  "#"
3308  "&& 1"
3309  [(const_int 0)]
3310{
3311  rtx low_dst = gen_lowpart (SImode, operands[0]);
3312  rtx high_dst = gen_highpart (SImode, operands[0]);
3313
3314  emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3315
3316  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3317  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3318  /* We need something to tag the possible REG_EQUAL notes on to.  */
3319  emit_move_insn (operands[0], operands[0]);
3320  DONE;
3321})
3322
3323(define_insn "umulsidi3_i"
3324  [(set (reg:SI MACH_REG)
3325	(truncate:SI
3326	 (lshiftrt:DI
3327	  (mult:DI
3328	   (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3329	   (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3330	  (const_int 32))))
3331   (set (reg:SI MACL_REG)
3332	(mult:SI (match_dup 0)
3333		 (match_dup 1)))]
3334  "TARGET_SH2"
3335  "dmulu.l	%1,%0"
3336  [(set_attr "type" "dmpy")])
3337
3338(define_expand "umulsidi3"
3339  [(set (match_operand:DI 0 "arith_reg_dest" "")
3340	(mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3341		 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3342  "TARGET_SH2 || TARGET_SHMEDIA"
3343{
3344  if (TARGET_SH2)
3345    {
3346      emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3347      DONE;
3348    }
3349})
3350
3351(define_insn "umulsidi3_media"
3352  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3353	(mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3354		 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3355  "TARGET_SHMEDIA"
3356  "mulu.l	%1, %2, %0"
3357  [(set_attr "type" "dmpy_media")
3358   (set_attr "highpart" "ignore")])
3359
3360(define_insn_and_split "umulsidi3_compact"
3361  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3362	(mult:DI
3363	 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3364	 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3365   (clobber (reg:SI MACH_REG))
3366   (clobber (reg:SI MACL_REG))]
3367  "TARGET_SH2"
3368  "#"
3369  "&& 1"
3370  [(const_int 0)]
3371{
3372  rtx low_dst = gen_lowpart (SImode, operands[0]);
3373  rtx high_dst = gen_highpart (SImode, operands[0]);
3374
3375  emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3376
3377  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3378  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3379  /* We need something to tag the possible REG_EQUAL notes on to.  */
3380  emit_move_insn (operands[0], operands[0]);
3381  DONE;
3382})
3383
3384(define_insn "smulsi3_highpart_i"
3385  [(set (reg:SI MACH_REG)
3386	(truncate:SI
3387	 (lshiftrt:DI
3388	  (mult:DI
3389	   (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3390	   (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3391	  (const_int 32))))
3392   (clobber (reg:SI MACL_REG))]
3393  "TARGET_SH2"
3394  "dmuls.l	%1,%0"
3395  [(set_attr "type" "dmpy")])
3396
3397(define_expand "smulsi3_highpart"
3398  [(parallel
3399    [(set (reg:SI MACH_REG)
3400	  (truncate:SI
3401	   (lshiftrt:DI
3402	    (mult:DI
3403	     (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3404	     (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3405	    (const_int 32))))
3406    (clobber (reg:SI MACL_REG))])
3407   (set (match_operand:SI 0 "arith_reg_operand" "")
3408	(reg:SI MACH_REG))]
3409  "TARGET_SH2"
3410{
3411  rtx insn, mach;
3412
3413  mach = gen_rtx_REG (SImode, MACH_REG);
3414  start_sequence ();
3415  emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3416  insn = get_insns ();  
3417  end_sequence ();
3418  /* expand_binop can't find a suitable code in mul_highpart_optab to
3419     make a REG_EQUAL note from, so make one here.
3420     See also {,u}mulhisi.
3421     ??? Alternatively, we could put this at the calling site of expand_binop,
3422     i.e. expand_mult_highpart.  */
3423  /* Use emit_libcall_block for loop invariant code motion and to make
3424     a REG_EQUAL note.  */
3425  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3426
3427  DONE;
3428})
3429
3430(define_insn "umulsi3_highpart_i"
3431  [(set (reg:SI MACH_REG)
3432	(truncate:SI
3433	 (lshiftrt:DI
3434	  (mult:DI
3435	   (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3436	   (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3437	  (const_int 32))))
3438   (clobber (reg:SI MACL_REG))]
3439  "TARGET_SH2"
3440  "dmulu.l	%1,%0"
3441  [(set_attr "type" "dmpy")])
3442
3443(define_expand "umulsi3_highpart"
3444  [(parallel
3445    [(set (reg:SI MACH_REG)
3446	  (truncate:SI
3447	   (lshiftrt:DI
3448	    (mult:DI
3449	     (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3450	     (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3451	    (const_int 32))))
3452    (clobber (reg:SI MACL_REG))])
3453   (set (match_operand:SI 0 "arith_reg_operand" "")
3454	(reg:SI MACH_REG))]
3455  "TARGET_SH2"
3456{
3457  rtx insn, mach;
3458
3459  mach = gen_rtx_REG (SImode, MACH_REG);
3460  start_sequence ();
3461  emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3462  insn = get_insns ();  
3463  end_sequence ();
3464  /* Use emit_libcall_block for loop invariant code motion and to make
3465     a REG_EQUAL note.  */
3466  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3467
3468  DONE;
3469})
3470
3471(define_insn_and_split "muldi3"
3472  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3473	(mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3474		 (match_operand:DI 2 "arith_reg_operand" "r")))
3475   (clobber (match_scratch:DI 3 "=&r"))
3476   (clobber (match_scratch:DI 4 "=r"))]
3477  "TARGET_SHMEDIA"
3478  "#"
3479  "reload_completed"
3480  [(const_int 0)]
3481{
3482  rtx op3_v2si, op2_v2si;
3483
3484  op3_v2si = operands[3];
3485  if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3486    {
3487      op3_v2si = XEXP (op3_v2si, 0);
3488      op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3489    }
3490  op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3491  op2_v2si = operands[2];
3492  if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3493    {
3494      op2_v2si = XEXP (op2_v2si, 0);
3495      op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3496    }
3497  op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3498  emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3499  emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3500  emit_insn (gen_umulsidi3_media (operands[4],
3501				 sh_gen_truncate (SImode, operands[1], 0),
3502				 sh_gen_truncate (SImode, operands[2], 0)));
3503  emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3504  emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3505  emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3506  emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3507  DONE;
3508})
3509
3510;; -------------------------------------------------------------------------
3511;; Logical operations
3512;; -------------------------------------------------------------------------
3513
3514(define_expand "andsi3"
3515  [(set (match_operand:SI 0 "arith_reg_operand" "")
3516	(and:SI (match_operand:SI 1 "logical_reg_operand" "")
3517		(match_operand:SI 2 "logical_and_operand" "")))]
3518  ""
3519{
3520  /* If it is possible to turn the and insn into a zero extension
3521     already, redundant zero extensions will be folded, which results
3522     in better code.  
3523     Ideally the splitter of *andsi_compact would be enough, if redundant
3524     zero extensions were detected after the combine pass, which does not
3525     happen at the moment.  */
3526  if (TARGET_SH1)
3527    {
3528      if (satisfies_constraint_Jmb (operands[2]))
3529	{
3530	  emit_insn (gen_zero_extendqisi2 (operands[0],
3531					   gen_lowpart (QImode, operands[1])));
3532	  DONE;
3533	}
3534      else if (satisfies_constraint_Jmw (operands[2]))
3535	{
3536	  emit_insn (gen_zero_extendhisi2 (operands[0],
3537					   gen_lowpart (HImode, operands[1])));
3538	  DONE;
3539	}
3540    }
3541})
3542
3543(define_insn_and_split "*andsi_compact"
3544  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
3545	(and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
3546		(match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
3547  "TARGET_SH1"
3548  "@
3549	extu.b	%1,%0
3550	extu.w	%1,%0
3551	and	%2,%0
3552	and	%2,%0"
3553  "&& 1"
3554 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
3555{
3556  if (satisfies_constraint_Jmb (operands[2]))
3557    operands[1] = gen_lowpart (QImode, operands[1]);
3558  else if (satisfies_constraint_Jmw (operands[2]))
3559    operands[1] = gen_lowpart (HImode, operands[1]);
3560  else
3561    FAIL;
3562}
3563  [(set_attr "type" "arith")])
3564
3565(define_insn "*andsi3_media"
3566  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3567	(and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3568		(match_operand:SI 2 "logical_operand" "r,I10")))]
3569  "TARGET_SHMEDIA"
3570  "@
3571	and	%1, %2, %0
3572	andi	%1, %2, %0"
3573  [(set_attr "type" "arith_media")])
3574
3575(define_insn "*andsi3_bclr"
3576  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3577	(and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3578		(match_operand:SI 2 "const_int_operand" "Psz")))]
3579  "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3580  "bclr	%W2,%0"
3581  [(set_attr "type" "arith")])
3582
3583(define_insn_and_split "anddi3"
3584  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3585	(and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3586		(match_operand:DI 2 "and_operand" "r,I10,J16")))]
3587  "TARGET_SHMEDIA"
3588  "@
3589	and	%1, %2, %0
3590	andi	%1, %2, %0
3591	#"
3592  "reload_completed
3593   && ! logical_operand (operands[2], DImode)"
3594  [(const_int 0)]
3595{
3596  if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3597    emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3598  else
3599    emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3600  DONE;
3601}
3602  [(set_attr "type" "arith_media")])
3603
3604(define_insn "andcsi3"
3605  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3606	(and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3607		(not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3608  "TARGET_SHMEDIA"
3609  "andc	%1,%2,%0"
3610  [(set_attr "type" "arith_media")])
3611
3612(define_insn "andcdi3"
3613  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3614	(and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3615		(not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3616  "TARGET_SHMEDIA"
3617  "andc	%1,%2,%0"
3618  [(set_attr "type" "arith_media")])
3619
3620(define_expand "iorsi3"
3621  [(set (match_operand:SI 0 "arith_reg_operand" "")
3622	(ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3623		(match_operand:SI 2 "logical_operand" "")))]
3624  ""
3625  "")
3626
3627(define_insn "*iorsi3_compact"
3628  [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3629	(ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3630		(match_operand:SI 2 "logical_operand" "r,K08")))]
3631  "TARGET_SH1
3632   && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3633  "or	%2,%0"
3634  [(set_attr "type" "arith")])
3635
3636(define_insn "*iorsi3_media"
3637  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3638	(ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3639		(match_operand:SI 2 "logical_operand" "r,I10")))]
3640  "TARGET_SHMEDIA"
3641  "@
3642	or	%1, %2, %0
3643	ori	%1, %2, %0"
3644  [(set_attr "type" "arith_media")])
3645
3646(define_insn "*iorsi3_bset"
3647  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3648	(ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3649	(match_operand:SI 2 "const_int_operand" "Pso")))]
3650  "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3651  "bset	%V2,%0"
3652  [(set_attr "type" "arith")])
3653
3654(define_insn "iordi3"
3655  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3656	(ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3657		(match_operand:DI 2 "logical_operand" "r,I10")))]
3658  "TARGET_SHMEDIA"
3659  "@
3660	or	%1, %2, %0
3661	ori	%1, %2, %0"
3662  [(set_attr "type" "arith_media")])
3663
3664(define_insn_and_split "*logical_sidi3"
3665  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3666	(sign_extend:DI (match_operator:SI 3 "logical_operator"
3667			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3668			   (match_operand:SI 2 "logical_operand" "r,I10")])))]
3669  "TARGET_SHMEDIA"
3670  "#"
3671  "&& reload_completed"
3672  [(set (match_dup 0) (match_dup 3))]
3673{
3674  operands[3]
3675    = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3676		      simplify_gen_subreg (DImode, operands[1], SImode, 0),
3677		      simplify_gen_subreg (DImode, operands[2], SImode, 0));
3678})
3679
3680(define_insn_and_split "*logical_sidisi3"
3681  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3682	(truncate:SI (sign_extend:DI
3683			(match_operator:SI 3 "logical_operator"
3684			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3685			   (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3686  "TARGET_SHMEDIA"
3687  "#"
3688  "&& 1"
3689  [(set (match_dup 0) (match_dup 3))])
3690
3691(define_insn_and_split "*logical_sidi3_2"
3692  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3693	(sign_extend:DI (truncate:SI (sign_extend:DI
3694			(match_operator:SI 3 "logical_operator"
3695			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3696			   (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3697  "TARGET_SHMEDIA"
3698  "#"
3699  "&& 1"
3700  [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3701
3702(define_expand "xorsi3"
3703  [(set (match_operand:SI 0 "arith_reg_operand" "")
3704	(xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3705		(match_operand:SI 2 "xor_operand" "")))]
3706  ""
3707  "")
3708
3709(define_insn "*xorsi3_compact"
3710  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3711	(xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3712		(match_operand:SI 2 "logical_operand" "K08,r")))]
3713  "TARGET_SH1"
3714  "xor	%2,%0"
3715  [(set_attr "type" "arith")])
3716
3717;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
3718;; of results where one of the inputs is a T bit store.  Notice that this
3719;; pattern must not match during reload.  If reload picks this pattern it
3720;; will be impossible to split it afterwards.
3721(define_insn_and_split "*logical_op_t"
3722  [(set (match_operand:SI 0 "arith_reg_dest")
3723	(match_operator:SI 3 "logical_operator"
3724	  [(match_operand:SI 1 "arith_reg_operand")
3725	   (match_operand:SI 2 "t_reg_operand")]))]
3726  "TARGET_SH1 && can_create_pseudo_p ()"
3727  "#"
3728  "&& 1"
3729  [(set (match_dup 4) (reg:SI T_REG))
3730   (set (match_dup 0) (match_dup 3))]
3731{
3732  operands[4] = gen_reg_rtx (SImode);
3733  operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
3734				operands[1], operands[4]);
3735})
3736
3737(define_insn "*xorsi3_media"
3738  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3739	(xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3740		(match_operand:SI 2 "xor_operand" "r,I06")))]
3741  "TARGET_SHMEDIA"
3742  "@
3743	xor	%1, %2, %0
3744	xori	%1, %2, %0"
3745  [(set_attr "type" "arith_media")])
3746
3747(define_insn "xordi3"
3748  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3749	(xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3750		(match_operand:DI 2 "xor_operand" "r,I06")))]
3751  "TARGET_SHMEDIA"
3752  "@
3753	xor	%1, %2, %0
3754	xori	%1, %2, %0"
3755  [(set_attr "type" "arith_media")])
3756
3757;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3758;; converts 2 * sign extend -> logical op into logical op -> sign extend
3759(define_split
3760  [(set (match_operand:DI 0 "arith_reg_dest" "")
3761	(sign_extend:DI (match_operator 4 "binary_logical_operator"
3762			  [(match_operand 1 "any_register_operand" "")
3763			   (match_operand 2 "any_register_operand" "")])))]
3764  "TARGET_SHMEDIA"
3765  [(set (match_dup 5) (match_dup 4))
3766   (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3767{
3768  enum machine_mode inmode = GET_MODE (operands[1]);
3769  int offset = 0;
3770
3771  if (GET_CODE (operands[0]) == SUBREG)
3772    {
3773      offset = SUBREG_BYTE (operands[0]);
3774      operands[0] = SUBREG_REG (operands[0]);
3775    }
3776  gcc_assert (REG_P (operands[0]));
3777  if (! TARGET_LITTLE_ENDIAN)
3778    offset += 8 - GET_MODE_SIZE (inmode);
3779  operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3780})
3781
3782;; -------------------------------------------------------------------------
3783;; Shifts and rotates
3784;; -------------------------------------------------------------------------
3785
3786(define_expand "rotldi3"
3787  [(set (match_operand:DI 0 "arith_reg_dest" "")
3788	(rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
3789		   (match_operand:HI 2 "mextr_bit_offset" "")))]
3790  "TARGET_SHMEDIA"
3791{
3792  if (! mextr_bit_offset (operands[2], HImode))
3793    FAIL;
3794})
3795
3796(define_insn "rotldi3_mextr"
3797  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3798	(rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3799		   (match_operand:HI 2 "mextr_bit_offset" "i")))]
3800  "TARGET_SHMEDIA"
3801{
3802  static char templ[16];
3803  sprintf (templ, "mextr%d	%%1,%%1,%%0",
3804	   8 - (int) (INTVAL (operands[2]) >> 3));
3805  return templ;
3806}
3807  [(set_attr "type" "arith_media")])
3808
3809(define_expand "rotrdi3"
3810  [(set (match_operand:DI 0 "arith_reg_dest" "")
3811	(rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
3812		     (match_operand:HI 2 "mextr_bit_offset" "")))]
3813  "TARGET_SHMEDIA"
3814{
3815  if (! mextr_bit_offset (operands[2], HImode))
3816    FAIL;
3817})
3818
3819(define_insn "rotrdi3_mextr"
3820  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3821	(rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3822		     (match_operand:HI 2 "mextr_bit_offset" "i")))]
3823  "TARGET_SHMEDIA"
3824{
3825  static char templ[16];
3826  sprintf (templ, "mextr%d	%%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
3827  return templ;
3828}
3829  [(set_attr "type" "arith_media")])
3830
3831(define_split
3832  [(set (match_operand:DI 0 "arith_reg_dest" "")
3833	(ior:DI (zero_extend:DI (mem:QI (match_operand 1
3834					 "ua_address_operand" "")))
3835		(ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3836			   (const_int 8))))
3837   (clobber (match_operand:DI 3 "register_operand" ""))]
3838  "TARGET_SHMEDIA"
3839  [(match_dup 4) (match_dup 5)]
3840{
3841  operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3842		 (operands[3], operands[1]));
3843  operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3844			      GEN_INT (56), GEN_INT (8));
3845})
3846
3847(define_expand "rotrsi3"
3848  [(set (match_operand:SI 0 "arith_reg_dest")
3849	(rotatert:SI (match_operand:SI 1 "arith_reg_operand")
3850		     (match_operand:SI 2 "const_int_operand")))]
3851  "TARGET_SH1"
3852{
3853  HOST_WIDE_INT ival = INTVAL (operands[2]);
3854  if (ival == 1)
3855    {
3856      emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
3857      DONE;
3858    }
3859
3860  FAIL;
3861})
3862
3863(define_insn "rotrsi3_1"
3864  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3865	(rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3866		     (const_int 1)))
3867   (set (reg:SI T_REG)
3868	(and:SI (match_dup 1) (const_int 1)))]
3869  "TARGET_SH1"
3870  "rotr	%0"
3871  [(set_attr "type" "arith")])
3872
3873;; A slimplified version of rotr for combine.
3874(define_insn "*rotrsi3_1"
3875  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3876	(rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3877		     (const_int 1)))
3878   (clobber (reg:SI T_REG))]
3879  "TARGET_SH1"
3880  "rotr	%0"
3881  [(set_attr "type" "arith")])
3882
3883(define_insn "rotlsi3_1"
3884  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3885	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3886		   (const_int 1)))
3887   (set (reg:SI T_REG)
3888	(lshiftrt:SI (match_dup 1) (const_int 31)))]
3889  "TARGET_SH1"
3890  "rotl	%0"
3891  [(set_attr "type" "arith")])
3892
3893;; A simplified version of rotl for combine.
3894(define_insn "*rotlsi3_1"
3895  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3896	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3897		   (const_int 1)))
3898   (clobber (reg:SI T_REG))]
3899  "TARGET_SH1"
3900  "rotl	%0"
3901  [(set_attr "type" "arith")])
3902
3903(define_insn "rotlsi3_31"
3904  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3905	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3906		   (const_int 31)))
3907   (clobber (reg:SI T_REG))]
3908  "TARGET_SH1"
3909  "rotr	%0"
3910  [(set_attr "type" "arith")])
3911
3912(define_insn "rotlsi3_16"
3913  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3914	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3915		   (const_int 16)))]
3916  "TARGET_SH1"
3917  "swap.w	%1,%0"
3918  [(set_attr "type" "arith")])
3919
3920(define_expand "rotlsi3"
3921  [(set (match_operand:SI 0 "arith_reg_dest")
3922	(rotate:SI (match_operand:SI 1 "arith_reg_operand")
3923		   (match_operand:SI 2 "const_int_operand")))]
3924  "TARGET_SH1"
3925{
3926  static const char rot_tab[] = {
3927    000, 000, 000, 000, 000, 000, 010, 001,
3928    001, 001, 011, 013, 003, 003, 003, 003,
3929    003, 003, 003, 003, 003, 013, 012, 002,
3930    002, 002, 010, 000, 000, 000, 000, 000,
3931  };
3932
3933  int count = INTVAL (operands[2]);
3934  int choice = rot_tab[count];
3935  if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3936    FAIL;
3937  choice &= 7;
3938  switch (choice)
3939    {
3940    case 0:
3941      emit_move_insn (operands[0], operands[1]);
3942      count -= (count & 16) * 2;
3943      break;
3944    case 3:
3945     emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3946     count -= 16;
3947     break;
3948    case 1:
3949    case 2:
3950      {
3951	rtx parts[2];
3952	parts[0] = gen_reg_rtx (SImode);
3953	parts[1] = gen_reg_rtx (SImode);
3954	emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3955	emit_move_insn (parts[choice-1], operands[1]);
3956	emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3957	emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3958	emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3959	count = (count & ~16) - 8;
3960      }
3961    }
3962
3963  for (; count > 0; count--)
3964    emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3965  for (; count < 0; count++)
3966    emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3967
3968  DONE;
3969})
3970
3971(define_insn "*rotlhi3_8"
3972  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3973	(rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3974		   (const_int 8)))]
3975  "TARGET_SH1"
3976  "swap.b	%1,%0"
3977  [(set_attr "type" "arith")])
3978
3979(define_expand "rotlhi3"
3980  [(set (match_operand:HI 0 "arith_reg_operand")
3981	(rotate:HI (match_operand:HI 1 "arith_reg_operand")
3982		   (match_operand:HI 2 "const_int_operand")))]
3983  "TARGET_SH1"
3984{
3985  if (INTVAL (operands[2]) != 8)
3986    FAIL;
3987})
3988
3989;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
3990;; They can also be used to implement things like
3991;;	bool t = a == b;
3992;;	int x0 = (y >> 1) | (t << 31);	// rotcr
3993;;	int x1 = (y << 1) | t;		// rotcl
3994(define_insn "rotcr"
3995  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3996	(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3997			     (const_int 1))
3998		(ashift:SI (match_operand:SI 2 "t_reg_operand")
3999			   (const_int 31))))
4000   (set (reg:SI T_REG)
4001	(and:SI (match_dup 1) (const_int 1)))]
4002  "TARGET_SH1"
4003  "rotcr	%0"
4004  [(set_attr "type" "arith")])
4005
4006(define_insn "rotcl"
4007  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4008	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4009			   (const_int 1))
4010		(match_operand:SI 2 "t_reg_operand")))
4011   (set (reg:SI T_REG)
4012	(lshiftrt:SI (match_dup 1) (const_int 31)))]
4013  "TARGET_SH1"
4014  "rotcl	%0"
4015  [(set_attr "type" "arith")])
4016
4017;; Simplified rotcr version for combine, which allows arbitrary shift
4018;; amounts for the reg.  If the shift amount is '1' rotcr can be used
4019;; directly.  Otherwise we have to insert a shift in between.
4020(define_insn_and_split "*rotcr"
4021  [(set (match_operand:SI 0 "arith_reg_dest")
4022	(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4023			     (match_operand:SI 2 "const_int_operand"))
4024		(ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4025			   (const_int 31))))
4026   (clobber (reg:SI T_REG))]
4027  "TARGET_SH1"
4028  "#"
4029  "&& can_create_pseudo_p ()"
4030  [(const_int 0)]
4031{
4032  if (INTVAL (operands[2]) > 1)
4033    {
4034      const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4035      rtx prev_set_t_insn = NULL_RTX;
4036      rtx tmp_t_reg = NULL_RTX;
4037
4038      /* If we're going to emit a shift sequence that clobbers the T_REG,
4039	 try to find the previous insn that sets the T_REG and emit the 
4040	 shift insn before that insn, to remove the T_REG dependency.
4041	 If the insn that sets the T_REG cannot be found, store the T_REG
4042	 in a temporary reg and restore it after the shift.  */
4043      if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4044	  && ! sh_dynamicalize_shift_p (shift_count))
4045	{
4046	  prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4047
4048	  /* Skip the nott insn, which was probably inserted by the splitter
4049	     of *rotcr_neg_t.  Don't use one of the recog functions
4050	     here during insn splitting, since that causes problems in later
4051	     passes.  */
4052	  if (prev_set_t_insn != NULL_RTX)
4053	    {
4054	      rtx pat = PATTERN (prev_set_t_insn);
4055	      if (GET_CODE (pat) == SET
4056		  && t_reg_operand (XEXP (pat, 0), SImode)
4057		  && negt_reg_operand (XEXP (pat, 1), SImode))
4058	      prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4059	    }
4060
4061	  if (! (prev_set_t_insn != NULL_RTX
4062		 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4063		 && ! reg_referenced_p (get_t_reg_rtx (),
4064					PATTERN (prev_set_t_insn))))
4065	    {
4066	      prev_set_t_insn = NULL_RTX;
4067	      tmp_t_reg = gen_reg_rtx (SImode);
4068	      emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4069	    } 
4070	}
4071
4072      rtx shift_result = gen_reg_rtx (SImode);
4073      rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4074      operands[1] = shift_result;
4075
4076      /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4077      if (prev_set_t_insn != NULL_RTX)
4078	emit_insn_before (shift_insn, prev_set_t_insn);
4079      else
4080	emit_insn (shift_insn);
4081
4082      /* Restore T_REG if it has been saved before.  */
4083      if (tmp_t_reg != NULL_RTX)
4084	emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4085    }
4086
4087  /* For the rotcr insn to work, operands[3] must be in T_REG.
4088     If it is not we can get it there by shifting it right one bit.
4089     In this case T_REG is not an input for this insn, thus we don't have to
4090     pay attention as of where to insert the shlr insn.  */
4091  if (! t_reg_operand (operands[3], SImode))
4092    {
4093      /* We don't care about the shifted result here, only the T_REG.  */
4094      emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4095      operands[3] = get_t_reg_rtx ();
4096    }
4097
4098  emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4099  DONE;
4100})
4101
4102;; If combine tries the same as above but with swapped operands, split
4103;; it so that it will try the pattern above.
4104(define_split
4105  [(set (match_operand:SI 0 "arith_reg_dest")
4106	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4107			   (const_int 31))
4108		(lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4109			     (match_operand:SI 3 "const_int_operand"))))]
4110  "TARGET_SH1 && can_create_pseudo_p ()"
4111  [(parallel [(set (match_dup 0)
4112		   (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4113			   (ashift:SI (match_dup 1) (const_int 31))))
4114	      (clobber (reg:SI T_REG))])])
4115
4116;; Basically the same as the rotcr pattern above, but for rotcl.
4117;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4118(define_insn_and_split "*rotcl"
4119  [(set (match_operand:SI 0 "arith_reg_dest")
4120	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4121			   (match_operand:SI 2 "const_int_operand"))
4122		(and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4123			(const_int 1))))
4124   (clobber (reg:SI T_REG))]
4125  "TARGET_SH1"
4126  "#"
4127  "&& can_create_pseudo_p ()"
4128  [(const_int 0)]
4129{
4130  gcc_assert (INTVAL (operands[2]) > 0);
4131
4132  if (INTVAL (operands[2]) > 1)
4133    {
4134      const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4135      rtx prev_set_t_insn = NULL_RTX;
4136      rtx tmp_t_reg = NULL_RTX;
4137
4138      /* If we're going to emit a shift sequence that clobbers the T_REG,
4139	 try to find the previous insn that sets the T_REG and emit the 
4140	 shift insn before that insn, to remove the T_REG dependency.
4141	 If the insn that sets the T_REG cannot be found, store the T_REG
4142	 in a temporary reg and restore it after the shift.  */
4143      if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4144	  && ! sh_dynamicalize_shift_p (shift_count))
4145	{
4146	  prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4147
4148	  /* Skip the nott insn, which was probably inserted by the splitter
4149	     of *rotcl_neg_t.  Don't use one of the recog functions
4150	     here during insn splitting, since that causes problems in later
4151	     passes.  */
4152	  if (prev_set_t_insn != NULL_RTX)
4153	    {
4154	      rtx pat = PATTERN (prev_set_t_insn);
4155	      if (GET_CODE (pat) == SET
4156		  && t_reg_operand (XEXP (pat, 0), SImode)
4157		  && negt_reg_operand (XEXP (pat, 1), SImode))
4158	      prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4159	    }
4160
4161	  if (! (prev_set_t_insn != NULL_RTX
4162		 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4163		 && ! reg_referenced_p (get_t_reg_rtx (),
4164					PATTERN (prev_set_t_insn))))
4165	    {
4166	      prev_set_t_insn = NULL_RTX;
4167	      tmp_t_reg = gen_reg_rtx (SImode);
4168	      emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4169	    } 
4170	}
4171
4172      rtx shift_result = gen_reg_rtx (SImode);
4173      rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4174      operands[1] = shift_result;
4175
4176      /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4177      if (prev_set_t_insn != NULL_RTX)
4178	emit_insn_before (shift_insn, prev_set_t_insn);
4179      else
4180	emit_insn (shift_insn);
4181
4182      /* Restore T_REG if it has been saved before.  */
4183      if (tmp_t_reg != NULL_RTX)
4184	emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4185    }
4186
4187  /* For the rotcl insn to work, operands[3] must be in T_REG.
4188     If it is not we can get it there by shifting it right one bit.
4189     In this case T_REG is not an input for this insn, thus we don't have to
4190     pay attention as of where to insert the shlr insn.  */
4191  if (! t_reg_operand (operands[3], SImode))
4192    {
4193      /* We don't care about the shifted result here, only the T_REG.  */
4194      emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4195      operands[3] = get_t_reg_rtx ();
4196    }
4197
4198  emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4199  DONE;
4200})
4201
4202;; rotcl combine pattern variations
4203(define_insn_and_split "*rotcl"
4204  [(set (match_operand:SI 0 "arith_reg_dest")
4205	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4206			   (match_operand:SI 2 "const_int_operand"))
4207		(match_operand:SI 3 "t_reg_operand")))
4208   (clobber (reg:SI T_REG))]
4209  "TARGET_SH1"
4210  "#"
4211  "&& can_create_pseudo_p ()"
4212  [(parallel [(set (match_dup 0)
4213		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4214			   (and:SI (match_dup 3) (const_int 1))))
4215	      (clobber (reg:SI T_REG))])])
4216
4217(define_insn_and_split "*rotcl"
4218  [(set (match_operand:SI 0 "arith_reg_dest")
4219	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4220			(const_int 1))
4221		(ashift:SI (match_operand:SI 2 "arith_reg_operand")
4222			   (match_operand:SI 3 "const_int_operand"))))
4223   (clobber (reg:SI T_REG))]
4224  "TARGET_SH1"
4225  "#"
4226  "&& can_create_pseudo_p ()"
4227  [(parallel [(set (match_dup 0)
4228		   (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4229			   (and:SI (match_dup 1) (const_int 1))))
4230	      (clobber (reg:SI T_REG))])])
4231
4232(define_insn_and_split "*rotcl"
4233  [(set (match_operand:SI 0 "arith_reg_dest")
4234	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4235			   (match_operand:SI 2 "const_int_operand"))
4236		(lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4237			     (const_int 31))))
4238   (clobber (reg:SI T_REG))]
4239  "TARGET_SH1"
4240  "#"
4241  "&& can_create_pseudo_p ()"
4242  [(parallel [(set (match_dup 0)
4243		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4244			   (and:SI (reg:SI T_REG) (const_int 1))))
4245	      (clobber (reg:SI T_REG))])]
4246{
4247  /* We don't care about the result of the left shift, only the T_REG.  */
4248  emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4249})
4250
4251(define_insn_and_split "*rotcl"
4252  [(set (match_operand:SI 0 "arith_reg_dest")
4253	(ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4254			     (const_int 31))
4255		(ashift:SI (match_operand:SI 1 "arith_reg_operand")
4256			   (match_operand:SI 2 "const_int_operand"))))
4257   (clobber (reg:SI T_REG))]
4258  "TARGET_SH1"
4259  "#"
4260  "&& can_create_pseudo_p ()"
4261  [(parallel [(set (match_dup 0)
4262		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4263			   (and:SI (reg:SI T_REG) (const_int 1))))
4264	      (clobber (reg:SI T_REG))])]
4265{
4266  /* We don't care about the result of the left shift, only the T_REG.  */
4267  emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4268})
4269
4270;; rotcr combine bridge pattern which will make combine try out more
4271;; complex patterns.
4272(define_insn_and_split "*rotcr"
4273  [(set (match_operand:SI 0 "arith_reg_dest")
4274	(ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
4275  "TARGET_SH1"
4276  "#"
4277  "&& 1"
4278  [(set (match_dup 0) (match_dup 1))
4279   (parallel [(set (match_dup 0)
4280		   (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
4281			   (ashift:SI (match_dup 1) (const_int 31))))
4282	      (set (reg:SI T_REG)
4283		   (and:SI (match_dup 0) (const_int 1)))])])
4284
4285(define_insn_and_split "*rotcr"
4286  [(set (match_operand:SI 0 "arith_reg_dest")
4287	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4288			(const_int -2147483648)) ;; 0xffffffff80000000
4289		(lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4290			     (const_int 1))))
4291   (clobber (reg:SI T_REG))]
4292  "TARGET_SH1"
4293  "#"
4294  "&& can_create_pseudo_p ()"
4295  [(const_int 0)]
4296{
4297  rtx tmp = gen_reg_rtx (SImode);
4298  emit_insn (gen_shll (tmp, operands[1]));
4299  emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4300  DONE;
4301})
4302
4303;; rotcr combine patterns for rotating in the negated T_REG value.
4304(define_insn_and_split "*rotcr_neg_t"
4305  [(set (match_operand:SI 0 "arith_reg_dest")
4306	(ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4307		(lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4308			     (match_operand:SI 3 "const_int_operand"))))
4309   (clobber (reg:SI T_REG))]
4310  "TARGET_SH1"
4311  "#"
4312  "&& can_create_pseudo_p ()"
4313  [(parallel [(set (match_dup 0)
4314		   (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4315			   (ashift:SI (reg:SI T_REG) (const_int 31))))
4316	      (clobber (reg:SI T_REG))])]
4317{
4318  emit_insn (gen_nott (get_t_reg_rtx ()));
4319})
4320
4321(define_insn_and_split "*rotcr_neg_t"
4322  [(set (match_operand:SI 0 "arith_reg_dest")
4323	(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4324			     (match_operand:SI 2 "const_int_operand"))
4325		(match_operand:SI 3 "negt_reg_shl31_operand")))
4326   (clobber (reg:SI T_REG))]
4327  "TARGET_SH1"
4328  "#"
4329  "&& can_create_pseudo_p ()"
4330  [(parallel [(set (match_dup 0)
4331		   (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4332			   (ashift:SI (reg:SI T_REG) (const_int 31))))
4333	      (clobber (reg:SI T_REG))])]
4334{
4335  emit_insn (gen_nott (get_t_reg_rtx ()));
4336})
4337
4338;; rotcl combine patterns for rotating in the negated T_REG value.
4339;; For some strange reason these have to be specified as splits which combine
4340;; will pick up.  If they are specified as insn_and_split like the
4341;; *rotcr_neg_t patterns above, combine would recognize them successfully
4342;; but not emit them on non-SH2A targets.
4343(define_split
4344  [(set (match_operand:SI 0 "arith_reg_dest")
4345	(ior:SI (match_operand:SI 1 "negt_reg_operand")
4346		(ashift:SI (match_operand:SI 2 "arith_reg_operand")
4347			   (match_operand:SI 3 "const_int_operand"))))]
4348  "TARGET_SH1"
4349  [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4350   (parallel [(set (match_dup 0)
4351		   (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4352			   (and:SI (reg:SI T_REG) (const_int 1))))
4353	      (clobber (reg:SI T_REG))])])
4354
4355(define_split
4356  [(set (match_operand:SI 0 "arith_reg_dest")
4357	(ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4358			   (match_operand:SI 3 "const_int_operand"))
4359		(match_operand:SI 1 "negt_reg_operand")))]
4360  "TARGET_SH1"
4361  [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4362   (parallel [(set (match_dup 0)
4363		   (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4364			   (and:SI (reg:SI T_REG) (const_int 1))))
4365	      (clobber (reg:SI T_REG))])])
4366
4367;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4368;; SImode shift left
4369
4370(define_expand "ashlsi3"
4371  [(set (match_operand:SI 0 "arith_reg_operand" "")
4372	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4373		   (match_operand:SI 2 "shift_count_operand" "")))]
4374  ""
4375{
4376  if (TARGET_SHMEDIA)
4377    {
4378      emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4379      DONE;
4380    }
4381  if (TARGET_DYNSHIFT
4382      && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4383      operands[2] = force_reg (SImode, operands[2]);
4384
4385  /*  If the ashlsi3_* insn is going to clobber the T_REG it must be
4386      expanded here.  */
4387  if (CONST_INT_P (operands[2])
4388      && sh_ashlsi_clobbers_t_reg_p (operands[2])
4389      && ! sh_dynamicalize_shift_p (operands[2]))
4390    {
4391      emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4392					   operands[2]));
4393      DONE;
4394    }
4395
4396  /* Expand a library call for the dynamic shift.  */
4397  if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4398    {
4399      emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4400      rtx funcaddr = gen_reg_rtx (Pmode);
4401      function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4402      emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4403
4404      DONE;
4405    }
4406})
4407
4408(define_insn "ashlsi3_k"
4409  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4410	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4411		   (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4412  "TARGET_SH1"
4413  "@
4414	add	%0,%0
4415	shll%O2	%0"
4416  [(set_attr "type" "arith")])
4417
4418(define_insn_and_split "ashlsi3_d"
4419  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4420	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4421		   (match_operand:SI 2 "shift_count_operand" "r")))]
4422  "TARGET_DYNSHIFT"
4423  "shld	%2,%0"
4424  "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4425   && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4426  [(const_int 0)]
4427{
4428  if (satisfies_constraint_P27 (operands[2]))
4429    {
4430      emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
4431      DONE;
4432    }
4433  else if (! satisfies_constraint_P27 (operands[2]))
4434    {
4435      /* This must happen before reload, otherwise the constant will be moved
4436	 into a register due to the "r" constraint, after which this split
4437	 cannot be done anymore.
4438	 Unfortunately the move insn will not always be eliminated.
4439	 Also, here we must not create a shift sequence that clobbers the
4440	 T_REG.  */
4441      emit_move_insn (operands[0], operands[1]);
4442      gen_shifty_op (ASHIFT, operands);
4443      DONE;
4444    }
4445
4446  FAIL;
4447}
4448  [(set_attr "type" "dyn_shift")])
4449
4450;; If dynamic shifts are not available use a library function.
4451;; By specifying the pattern we reduce the number of call clobbered regs.
4452;; In order to make combine understand the truncation of the shift amount
4453;; operand we have to allow it to use pseudo regs for the shift operands.
4454(define_insn "ashlsi3_d_call"
4455  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4456	(ashift:SI (reg:SI R4_REG)
4457		   (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4458			   (const_int 31))))
4459   (use (match_operand:SI 2 "arith_reg_operand" "r"))
4460   (clobber (reg:SI T_REG))
4461   (clobber (reg:SI PR_REG))]
4462  "TARGET_SH1 && !TARGET_DYNSHIFT"
4463  "jsr	@%2%#"
4464  [(set_attr "type" "sfunc")
4465   (set_attr "needs_delay_slot" "yes")])
4466
4467(define_insn_and_split "ashlsi3_n"
4468  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4469	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4470		   (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
4471  "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4472  "#"
4473  "&& (reload_completed
4474       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4475  [(const_int 0)]
4476{
4477  if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4478    {
4479      /* If this pattern was picked and dynamic shifts are supported, switch
4480	 to dynamic shift pattern before reload.  */
4481      operands[2] = force_reg (SImode, operands[2]);
4482      emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4483    }
4484  else
4485    gen_shifty_op (ASHIFT, operands);
4486
4487  DONE;
4488})
4489
4490(define_insn_and_split "ashlsi3_n_clobbers_t"
4491  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4492	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4493		   (match_operand:SI 2 "not_p27_shift_count_operand" "")))
4494   (clobber (reg:SI T_REG))]
4495  "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
4496  "#"
4497  "&& (reload_completed || INTVAL (operands[2]) == 31
4498       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4499  [(const_int 0)]
4500{
4501  if (INTVAL (operands[2]) == 31)
4502    {
4503      /* If the shift amount is 31 we split into a different sequence before
4504	 reload so that it gets a chance to allocate R0 for the sequence.
4505	 If it fails to do so (due to pressure on R0), it will take one insn
4506	 more for the and.  */
4507      emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
4508      emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4509    }
4510  else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4511    {
4512      /* If this pattern was picked and dynamic shifts are supported, switch
4513	 to dynamic shift pattern before reload.  */
4514      operands[2] = force_reg (SImode, operands[2]);
4515      emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4516    }
4517  else
4518    gen_shifty_op (ASHIFT, operands);
4519
4520  DONE;
4521})
4522
4523(define_insn "shll"
4524  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4525	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
4526   (set (reg:SI T_REG)
4527	(lt:SI (match_dup 1) (const_int 0)))]
4528  "TARGET_SH1"
4529  "shll	%0"
4530  [(set_attr "type" "arith")])
4531
4532(define_insn "*ashlsi_c_void"
4533  [(set (reg:SI T_REG)
4534	(lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
4535   (clobber (match_scratch:SI 1 "=0"))]
4536  "TARGET_SH1 && cse_not_expected"
4537  "shll	%0"
4538  [(set_attr "type" "arith")])
4539
4540(define_peephole2
4541  [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
4542   (set (reg:SI T_REG)
4543	(gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
4544  "TARGET_SH1
4545   && peep2_reg_dead_p (2, operands[0])
4546   && peep2_reg_dead_p (2, operands[1])"
4547  [(const_int 0)]
4548{
4549  emit_insn (gen_shll (operands[1], operands[1]));
4550  DONE;
4551})
4552
4553(define_insn "ashlsi3_media"
4554  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4555	(ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4556		   (match_operand:SI 2 "shift_count_operand" "r,n")))]
4557  "TARGET_SHMEDIA"
4558  "@
4559	shlld.l	%1, %2, %0
4560	shlli.l	%1, %2, %0"
4561  [(set_attr "type" "arith_media")
4562   (set_attr "highpart" "ignore")])
4563
4564;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4565;; HImode shift left
4566
4567(define_expand "ashlhi3"
4568  [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
4569		   (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
4570			      (match_operand:SI 2 "nonmemory_operand" "")))
4571	      (clobber (reg:SI T_REG))])]
4572  "TARGET_SH1"
4573{
4574  if (!CONST_INT_P (operands[2]))
4575    FAIL;
4576  /* It may be possible to call gen_ashlhi3 directly with more generic
4577     operands.  Make sure operands[1] is a HImode register here.  */
4578  if (!arith_reg_operand (operands[1], HImode))
4579    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4580})
4581
4582(define_insn "ashlhi3_k"
4583  [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4584	(ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
4585		   (match_operand:HI 2 "const_int_operand" "M,P27")))]
4586  "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
4587  "@
4588	add	%0,%0
4589	shll%O2	%0"
4590  [(set_attr "type" "arith")])
4591
4592(define_insn_and_split "*ashlhi3_n"
4593  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4594	(ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
4595		   (match_operand:HI 2 "const_int_operand" "n")))
4596   (clobber (reg:SI T_REG))]
4597  "TARGET_SH1"
4598  "#"
4599  "&& reload_completed"
4600  [(use (reg:SI R0_REG))]
4601{
4602  gen_shifty_hi_op (ASHIFT, operands);
4603  DONE;
4604})
4605
4606;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4607;; DImode shift left
4608
4609(define_expand "ashldi3"
4610  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4611		   (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4612			      (match_operand:DI 2 "immediate_operand" "")))
4613	      (clobber (reg:SI T_REG))])]
4614  ""
4615{
4616  if (TARGET_SHMEDIA)
4617    {
4618      emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4619      DONE;
4620    }
4621  if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
4622    {
4623      emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4624      DONE;
4625    }
4626  else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
4627    {
4628      emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4629      DONE;
4630    }
4631  else
4632    FAIL;
4633})
4634
4635;; Expander for DImode shift left with SImode operations.
4636(define_expand "ashldi3_std"
4637  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4638	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4639                   (match_operand:DI 2 "const_int_operand" "n")))]
4640  "TARGET_SH1 && INTVAL (operands[2]) < 32"
4641{
4642  rtx low_src = gen_lowpart (SImode, operands[1]);
4643  rtx high_src = gen_highpart (SImode, operands[1]);
4644  rtx dst = gen_reg_rtx (DImode);
4645  rtx low_dst = gen_lowpart (SImode, dst);
4646  rtx high_dst = gen_highpart (SImode, dst);
4647  rtx tmp0 = gen_reg_rtx (SImode);
4648  rtx tmp1 = gen_reg_rtx (SImode);
4649
4650  emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
4651  emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));  
4652  emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));  
4653  emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
4654  emit_move_insn (operands[0], dst);
4655  DONE;
4656})
4657
4658(define_insn_and_split "ashldi3_k"
4659  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4660	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
4661		   (const_int 1)))
4662   (clobber (reg:SI T_REG))]
4663  "TARGET_SH1"
4664  "#"
4665  "&& reload_completed"
4666  [(const_int 0)]
4667{
4668  rtx high = gen_highpart (SImode, operands[0]);
4669  rtx low = gen_lowpart (SImode, operands[0]);
4670  emit_insn (gen_shll (low, low));
4671  emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
4672  DONE;
4673})
4674
4675(define_insn "ashldi3_media"
4676  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4677	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4678		   (match_operand:DI 2 "shift_count_operand" "r,n")))]
4679  "TARGET_SHMEDIA"
4680  "@
4681	shlld	%1, %2, %0
4682	shlli	%1, %2, %0"
4683  [(set_attr "type" "arith_media")])
4684
4685(define_insn "*ashldisi3_media"
4686  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4687	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4688		   (match_operand:DI 2 "const_int_operand" "n")))]
4689  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4690  "shlli.l	%1, %2, %0"
4691  [(set_attr "type" "arith_media")
4692   (set_attr "highpart" "ignore")])
4693
4694;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4695;; SImode arithmetic shift right
4696;;
4697;; We can't do HImode right shifts correctly unless we start out with an
4698;; explicit zero / sign extension; doing that would result in worse overall
4699;; code, so just let the machine independent code widen the mode.
4700;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
4701
4702(define_expand "ashrsi3"
4703  [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4704		   (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4705				(match_operand:SI 2 "nonmemory_operand" "")))
4706	      (clobber (reg:SI T_REG))])]
4707  ""
4708{
4709  if (TARGET_SHMEDIA)
4710    {
4711      emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4712      DONE;
4713    }
4714  if (expand_ashiftrt (operands))
4715    DONE;
4716  else
4717    FAIL;
4718})
4719
4720(define_insn "shar"
4721  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4722	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4723		     (const_int 1)))
4724   (set (reg:SI T_REG)
4725	(and:SI (match_dup 1) (const_int 1)))]
4726  "TARGET_SH1"
4727  "shar	%0"
4728  [(set_attr "type" "arith")])
4729
4730(define_insn "ashrsi3_k"
4731  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4732	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4733		     (match_operand:SI 2 "const_int_operand" "M")))
4734   (clobber (reg:SI T_REG))]
4735  "TARGET_SH1 && INTVAL (operands[2]) == 1"
4736  "shar	%0"
4737  [(set_attr "type" "arith")])
4738
4739(define_insn_and_split "ashrsi2_16"
4740  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4741        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
4742                     (const_int 16)))]
4743  "TARGET_SH1"
4744  "#"
4745  "&& 1"
4746  [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
4747   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
4748{
4749  operands[2] = gen_lowpart (HImode, operands[0]);
4750})
4751
4752(define_insn_and_split "ashrsi2_31"
4753  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4754	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4755		     (const_int 31)))
4756   (clobber (reg:SI T_REG))]
4757  "TARGET_SH1"
4758  "#"
4759  "&& 1"
4760  [(const_int 0)]
4761{
4762  emit_insn (gen_shll (operands[0], operands[1]));
4763  emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
4764  DONE;
4765})
4766
4767(define_insn "ashrsi3_d"
4768  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4769	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4770		     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4771  "TARGET_DYNSHIFT"
4772  "shad	%2,%0"
4773  [(set_attr "type" "dyn_shift")])
4774
4775(define_insn "ashrsi3_n"
4776  [(set (reg:SI R4_REG)
4777	(ashiftrt:SI (reg:SI R4_REG)
4778		     (match_operand:SI 0 "const_int_operand" "i")))
4779   (clobber (reg:SI T_REG))
4780   (clobber (reg:SI PR_REG))
4781   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
4782  "TARGET_SH1"
4783  "jsr	@%1%#"
4784  [(set_attr "type" "sfunc")
4785   (set_attr "needs_delay_slot" "yes")])
4786
4787(define_insn "ashrsi3_media"
4788  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4789	(ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4790		     (match_operand:SI 2 "shift_count_operand" "r,n")))]
4791  "TARGET_SHMEDIA"
4792  "@
4793	shard.l	%1, %2, %0
4794	shari.l	%1, %2, %0"
4795  [(set_attr "type" "arith_media")
4796   (set_attr "highpart" "ignore")])
4797
4798;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4799;; DImode arithmetic shift right
4800
4801(define_expand "ashrdi3"
4802  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4803		   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4804				(match_operand:DI 2 "immediate_operand" "")))
4805	      (clobber (reg:SI T_REG))])]
4806  ""
4807{
4808  if (TARGET_SHMEDIA)
4809    {
4810      emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4811      DONE;
4812    }
4813  if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
4814    FAIL;
4815})
4816
4817(define_insn_and_split "ashrdi3_k"
4818  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4819	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4820		     (const_int 1)))
4821   (clobber (reg:SI T_REG))]
4822  "TARGET_SH1"
4823  "#"
4824  "&& reload_completed"
4825  [(const_int 0)]
4826{
4827  rtx high = gen_highpart (SImode, operands[0]);
4828  rtx low = gen_lowpart (SImode, operands[0]);
4829  emit_insn (gen_shar (high, high));
4830  emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
4831  DONE;
4832})
4833
4834(define_insn "ashrdi3_media"
4835  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4836	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4837		     (match_operand:DI 2 "shift_count_operand" "r,n")))]
4838  "TARGET_SHMEDIA
4839   && (arith_reg_dest (operands[0], DImode)
4840       || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4841  "@
4842	shard	%1, %2, %0
4843	shari	%1, %2, %0"
4844  [(set_attr "type" "arith_media")])
4845
4846(define_insn "*ashrdisi3_media"
4847  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4848	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4849		     (match_operand:DI 2 "const_int_operand" "n")))]
4850  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4851  "shari.l	%1, %2, %0"
4852  [(set_attr "type" "arith_media")
4853   (set_attr "highpart" "ignore")])
4854
4855(define_insn "ashrdisi3_media_high"
4856  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4857	(truncate:SI
4858	   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4859			(match_operand:DI 2 "const_int_operand" "n"))))]
4860  "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4861  "shari	%1, %2, %0"
4862  [(set_attr "type" "arith_media")])
4863
4864(define_insn "ashrdisi3_media_opaque"
4865  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4866	(unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4867		    (match_operand:DI 2 "const_int_operand" "n")]
4868	 UNSPEC_ASHIFTRT))]
4869  "TARGET_SHMEDIA"
4870  "shari	%1, %2, %0"
4871  [(set_attr "type" "arith_media")])
4872
4873;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4874;; SImode logical shift right
4875
4876(define_expand "lshrsi3"
4877  [(set (match_operand:SI 0 "arith_reg_dest" "")
4878	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4879		     (match_operand:SI 2 "shift_count_operand" "")))]
4880  ""
4881{
4882  if (TARGET_SHMEDIA)
4883    {
4884      emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
4885      DONE;
4886    }
4887
4888  /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
4889     here, otherwise the pattern will never match due to the shift amount reg
4890     negation.  */
4891  if (TARGET_DYNSHIFT
4892      && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4893    {
4894      rtx neg_count = force_reg (SImode,
4895			         gen_int_mode (- INTVAL (operands[2]), SImode));
4896      emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
4897      DONE;
4898    }
4899
4900  if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
4901    {
4902      rtx neg_count = gen_reg_rtx (SImode);
4903      emit_insn (gen_negsi2 (neg_count, operands[2]));
4904      emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
4905      DONE;
4906    }
4907
4908  /* If the lshrsi3_* insn is going to clobber the T_REG it must be
4909     expanded here.  */
4910  if (CONST_INT_P (operands[2])
4911      && sh_lshrsi_clobbers_t_reg_p (operands[2])
4912      && ! sh_dynamicalize_shift_p (operands[2]))
4913    {
4914      emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
4915		 operands[2]));
4916      DONE;
4917    }
4918
4919  /* Expand a library call for the dynamic shift.  */
4920  if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4921    {
4922      emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4923      rtx funcaddr = gen_reg_rtx (Pmode);
4924      function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
4925      emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
4926      DONE;
4927    }
4928})
4929
4930(define_insn "lshrsi3_k"
4931  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4932	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4933		     (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
4934  "TARGET_SH1"
4935  "shlr%O2	%0"
4936  [(set_attr "type" "arith")])
4937
4938(define_insn_and_split "lshrsi3_d"
4939  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4940	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4941		     (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
4942  "TARGET_DYNSHIFT"
4943  "shld	%2,%0"
4944  "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4945   && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
4946  [(const_int 0)]
4947{
4948  if (satisfies_constraint_P27 (operands[2]))
4949    {
4950      /* This will not be done for a shift amount of 1, because it would
4951	 clobber the T_REG.  */
4952      emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
4953      DONE;
4954    }
4955  else if (! satisfies_constraint_P27 (operands[2]))
4956    {
4957      /* This must happen before reload, otherwise the constant will be moved
4958	 into a register due to the "r" constraint, after which this split
4959	 cannot be done anymore.
4960	 Unfortunately the move insn will not always be eliminated.
4961	 Also, here we must not create a shift sequence that clobbers the
4962	 T_REG.  */
4963      emit_move_insn (operands[0], operands[1]);
4964      gen_shifty_op (LSHIFTRT, operands);
4965      DONE;
4966    }
4967
4968  FAIL;
4969}
4970  [(set_attr "type" "dyn_shift")])
4971
4972;; If dynamic shifts are not available use a library function.
4973;; By specifying the pattern we reduce the number of call clobbered regs.
4974;; In order to make combine understand the truncation of the shift amount
4975;; operand we have to allow it to use pseudo regs for the shift operands.
4976(define_insn "lshrsi3_d_call"
4977  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4978	(lshiftrt:SI (reg:SI R4_REG)
4979		     (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4980			     (const_int 31))))
4981   (use (match_operand:SI 2 "arith_reg_operand" "r"))
4982   (clobber (reg:SI T_REG))
4983   (clobber (reg:SI PR_REG))]
4984  "TARGET_SH1 && !TARGET_DYNSHIFT"
4985  "jsr	@%2%#"
4986  [(set_attr "type" "sfunc")
4987   (set_attr "needs_delay_slot" "yes")])
4988
4989(define_insn_and_split "lshrsi3_n"
4990  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4991	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4992		     (match_operand:SI 2 "not_p27_rshift_count_operand")))]
4993  "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
4994  "#"
4995  "&& (reload_completed
4996       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4997  [(const_int 0)]
4998{
4999  if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5000    {
5001      /* If this pattern was picked and dynamic shifts are supported, switch
5002	 to dynamic shift pattern before reload.  */
5003      operands[2] = force_reg (SImode,
5004			       gen_int_mode (- INTVAL (operands[2]), SImode));
5005      emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5006    }
5007  else
5008    gen_shifty_op (LSHIFTRT, operands);
5009
5010  DONE;
5011})
5012
5013;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5014;; the shlr pattern.
5015(define_insn_and_split "lshrsi3_n_clobbers_t"
5016  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5017	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5018		     (match_operand:SI 2 "not_p27_rshift_count_operand")))
5019   (clobber (reg:SI T_REG))]
5020  "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
5021  "#"
5022  "&& (reload_completed || INTVAL (operands[2]) == 31
5023       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5024  [(const_int 0)]
5025{
5026  if (INTVAL (operands[2]) == 31)
5027    {
5028      emit_insn (gen_shll (operands[0], operands[1]));
5029      emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5030    }
5031  else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5032    {
5033      /* If this pattern was picked and dynamic shifts are supported, switch
5034	 to dynamic shift pattern before reload.  */
5035      operands[2] = force_reg (SImode,
5036			       gen_int_mode (- INTVAL (operands[2]), SImode));
5037      emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5038    }
5039  else
5040    gen_shifty_op (LSHIFTRT, operands);
5041
5042  DONE;
5043})
5044
5045(define_insn "shlr"
5046  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5047	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5048		     (const_int 1)))
5049   (set (reg:SI T_REG)
5050	(and:SI (match_dup 1) (const_int 1)))]
5051  "TARGET_SH1"
5052  "shlr	%0"
5053  [(set_attr "type" "arith")])
5054
5055(define_insn "lshrsi3_media"
5056  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5057	(lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5058		     (match_operand:SI 2 "shift_count_operand" "r,n")))]
5059  "TARGET_SHMEDIA"
5060  "@
5061	shlrd.l	%1, %2, %0
5062	shlri.l	%1, %2, %0"
5063  [(set_attr "type" "arith_media")
5064   (set_attr "highpart" "ignore")])
5065
5066;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5067;; DImode logical shift right
5068
5069(define_expand "lshrdi3"
5070  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5071		   (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5072			       (match_operand:DI 2 "immediate_operand" "")))
5073	     (clobber (reg:SI T_REG))])]
5074  ""
5075{
5076  if (TARGET_SHMEDIA)
5077    {
5078      emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
5079      DONE;
5080    }
5081  if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5082    FAIL;
5083})
5084
5085(define_insn_and_split "lshrdi3_k"
5086  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5087	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5088		     (const_int 1)))
5089   (clobber (reg:SI T_REG))]
5090  "TARGET_SH1"
5091  "#"
5092  "&& reload_completed"
5093  [(const_int 0)]
5094{
5095  rtx high = gen_highpart (SImode, operands[0]);
5096  rtx low = gen_lowpart (SImode, operands[0]);
5097  emit_insn (gen_shlr (high, high));
5098  emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5099  DONE;
5100})
5101
5102(define_insn "lshrdi3_media"
5103  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5104	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5105		     (match_operand:DI 2 "shift_count_operand" "r,n")))]
5106  "TARGET_SHMEDIA
5107   && (arith_reg_dest (operands[0], DImode)
5108       || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
5109  "@
5110	shlrd	%1, %2, %0
5111	shlri	%1, %2, %0"
5112  [(set_attr "type" "arith_media")])
5113
5114(define_insn "*lshrdisi3_media"
5115  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5116	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5117		     (match_operand:DI 2 "const_int_operand" "n")))]
5118  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5119  "shlri.l	%1, %2, %0"
5120  [(set_attr "type" "arith_media")
5121   (set_attr "highpart" "ignore")])
5122
5123;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5124;; Combined left/right shifts
5125
5126(define_split
5127  [(set (match_operand:SI 0 "register_operand" "")
5128	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5129			   (match_operand:SI 2 "const_int_operand" ""))
5130		(match_operand:SI 3 "const_int_operand" "")))]
5131  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5132  [(use (reg:SI R0_REG))]
5133{
5134  if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5135    FAIL;
5136  DONE;
5137})
5138
5139(define_split
5140  [(set (match_operand:SI 0 "register_operand" "")
5141	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5142			   (match_operand:SI 2 "const_int_operand" ""))
5143		(match_operand:SI 3 "const_int_operand" "")))
5144   (clobber (reg:SI T_REG))]
5145  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5146  [(use (reg:SI R0_REG))]
5147{
5148  if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5149    FAIL;
5150  DONE;
5151})
5152
5153(define_insn ""
5154  [(set (match_operand:SI 0 "register_operand" "=r")
5155	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5156			   (match_operand:SI 2 "const_int_operand" "n"))
5157		(match_operand:SI 3 "const_int_operand" "n")))
5158   (clobber (reg:SI T_REG))]
5159  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
5160  "#"
5161  [(set (attr "length")
5162	(cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5163	       (const_string "4")
5164	       (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5165	       (const_string "6")
5166	       (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5167	       (const_string "8")
5168	       (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5169	       (const_string "10")
5170	       (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5171	       (const_string "12")
5172	       (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5173	       (const_string "14")
5174	       (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5175	       (const_string "16")]
5176	      (const_string "18")))
5177   (set_attr "type" "arith")])
5178
5179(define_insn ""
5180  [(set (match_operand:SI 0 "register_operand" "=z")
5181	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5182			   (match_operand:SI 2 "const_int_operand" "n"))
5183		(match_operand:SI 3 "const_int_operand" "n")))
5184   (clobber (reg:SI T_REG))]
5185  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
5186  "#"
5187  [(set (attr "length")
5188	(cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5189	       (const_string "4")
5190	       (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5191	       (const_string "6")
5192	       (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5193	       (const_string "8")]
5194	      (const_string "10")))
5195   (set_attr "type" "arith")])
5196
5197;; shift left / and combination with a scratch register: The combine pass
5198;; does not accept the individual instructions, even though they are
5199;; cheap.  But it needs a precise description so that it is usable after
5200;; reload.
5201(define_insn "and_shl_scratch"
5202  [(set (match_operand:SI 0 "register_operand" "=r,&r")
5203	(lshiftrt:SI
5204	 (ashift:SI
5205	  (and:SI
5206	   (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5207			(match_operand:SI 2 "const_int_operand" "N,n"))
5208	   (match_operand:SI 3 "" "0,r"))
5209	  (match_operand:SI 4 "const_int_operand" "n,n"))
5210	 (match_operand:SI 5 "const_int_operand" "n,n")))
5211   (clobber (reg:SI T_REG))]
5212  "TARGET_SH1"
5213  "#"
5214  [(set (attr "length")
5215	(cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5216	       (const_string "4")
5217	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5218	       (const_string "6")
5219	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5220	       (const_string "8")
5221	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5222	       (const_string "10")]
5223	      (const_string "12")))
5224   (set_attr "type" "arith")])
5225
5226(define_split
5227  [(set (match_operand:SI 0 "register_operand" "")
5228	(lshiftrt:SI
5229	 (ashift:SI
5230	  (and:SI
5231	   (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5232			(match_operand:SI 2 "const_int_operand" ""))
5233	   (match_operand:SI 3 "register_operand" ""))
5234	  (match_operand:SI 4 "const_int_operand" ""))
5235	 (match_operand:SI 5 "const_int_operand" "")))
5236   (clobber (reg:SI T_REG))]
5237  "TARGET_SH1"
5238  [(use (reg:SI R0_REG))]
5239{
5240  rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5241
5242  if (INTVAL (operands[2]))
5243    {
5244      gen_shifty_op (LSHIFTRT, operands);
5245    }
5246  emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5247  operands[2] = operands[4];
5248  gen_shifty_op (ASHIFT, operands);
5249  if (INTVAL (operands[5]))
5250    {
5251      operands[2] = operands[5];
5252      gen_shifty_op (LSHIFTRT, operands);
5253    }
5254  DONE;
5255})
5256
5257;; signed left/right shift combination.
5258(define_split
5259  [(set (match_operand:SI 0 "register_operand" "")
5260        (sign_extract:SI
5261	 (ashift:SI (match_operand:SI 1 "register_operand" "")
5262		    (match_operand:SI 2 "const_int_operand" ""))
5263	 (match_operand:SI 3 "const_int_operand" "")
5264	 (const_int 0)))
5265   (clobber (reg:SI T_REG))]
5266  "TARGET_SH1"
5267  [(use (reg:SI R0_REG))]
5268{
5269  if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5270    FAIL;
5271  DONE;
5272})
5273
5274(define_insn "shl_sext_ext"
5275  [(set (match_operand:SI 0 "register_operand" "=r")
5276        (sign_extract:SI
5277	 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5278		    (match_operand:SI 2 "const_int_operand" "n"))
5279	 (match_operand:SI 3 "const_int_operand" "n")
5280	 (const_int 0)))
5281   (clobber (reg:SI T_REG))]
5282  "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5283  "#"
5284  [(set (attr "length")
5285	(cond [(match_test "shl_sext_length (insn)")
5286	       (const_string "2")
5287	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5288	       (const_string "4")
5289	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5290	       (const_string "6")
5291	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5292	       (const_string "8")
5293	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5294	       (const_string "10")
5295	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5296	       (const_string "12")
5297	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5298	       (const_string "14")
5299	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5300	       (const_string "16")]
5301	      (const_string "18")))
5302    (set_attr "type" "arith")])
5303
5304(define_insn "shl_sext_sub"
5305  [(set (match_operand:SI 0 "register_operand" "=z")
5306        (sign_extract:SI
5307	 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5308		    (match_operand:SI 2 "const_int_operand" "n"))
5309	 (match_operand:SI 3 "const_int_operand" "n")
5310	 (const_int 0)))
5311   (clobber (reg:SI T_REG))]
5312  "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
5313  "#"
5314  [(set (attr "length")
5315	(cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5316	       (const_string "6")
5317	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5318	       (const_string "8")
5319	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5320	       (const_string "10")
5321	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5322	       (const_string "12")]
5323	      (const_string "14")))
5324    (set_attr "type" "arith")])
5325
5326;; The xtrct_left and xtrct_right patterns are used in expansions of DImode
5327;; shifts by 16, and allow the xtrct instruction to be generated from C
5328;; source.
5329(define_insn "xtrct_left"
5330  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5331        (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5332			   (const_int 16))
5333 	        (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5334			     (const_int 16))))]
5335  "TARGET_SH1"
5336  "xtrct	%1,%0"
5337  [(set_attr "type" "arith")])
5338
5339(define_insn "xtrct_right"
5340  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5341        (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5342			     (const_int 16))
5343 	        (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5344			   (const_int 16))))]
5345  "TARGET_SH1"
5346  "xtrct	%2,%0"
5347  [(set_attr "type" "arith")])
5348
5349;; -------------------------------------------------------------------------
5350;; Unary arithmetic
5351;; -------------------------------------------------------------------------
5352
5353(define_insn "negc"
5354  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5355	(neg:SI (plus:SI (reg:SI T_REG)
5356			 (match_operand:SI 1 "arith_reg_operand" "r"))))
5357   (set (reg:SI T_REG)
5358	(ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
5359	       (const_int 0)))]
5360  "TARGET_SH1"
5361  "negc	%1,%0"
5362  [(set_attr "type" "arith")])
5363
5364;; A simplified version of the negc insn, where the exact value of the
5365;; T bit doesn't matter.  This is easier for combine to pick up.
5366;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5367;; extra patterns for this case.
5368(define_insn "*negc"
5369  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5370	(minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5371		  (match_operand:SI 2 "t_reg_operand" "")))
5372   (clobber (reg:SI T_REG))]
5373  "TARGET_SH1"
5374  "negc	%1,%0"
5375  [(set_attr "type" "arith")])
5376
5377(define_insn "*negdi_media"
5378  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5379	(neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5380  "TARGET_SHMEDIA"
5381  "sub	r63, %1, %0"
5382  [(set_attr "type" "arith_media")])
5383
5384;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
5385;; combined.
5386(define_expand "negdi2"
5387  [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
5388		   (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5389	      (clobber (reg:SI T_REG))])]
5390  "TARGET_SH1")
5391
5392(define_insn_and_split "*negdi2"
5393  [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
5394	(neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))
5395   (clobber (reg:SI T_REG))]
5396  "TARGET_SH1"
5397  "#"
5398  "&& reload_completed"
5399  [(const_int 0)]
5400{
5401  emit_insn (gen_clrt ());
5402  emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5403		       gen_lowpart (SImode, operands[1])));
5404  emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5405		       gen_highpart (SImode, operands[1])));
5406  DONE;
5407})
5408
5409(define_insn "negsi2"
5410  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5411	(neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5412  "TARGET_SH1"
5413  "neg	%1,%0"
5414  [(set_attr "type" "arith")])
5415
5416(define_insn_and_split "one_cmplsi2"
5417  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5418	(not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5419  "TARGET_SH1"
5420  "not	%1,%0"
5421  "&& can_create_pseudo_p ()"
5422  [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
5423   (set (match_dup 0) (reg:SI T_REG))]
5424{
5425/* PR 54685
5426   If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
5427   sequence:
5428
5429     (set (reg0) (not:SI (reg0) (reg1)))
5430     (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
5431		(clobber (reg:SI T_REG))])
5432
5433   ... match and combine the sequence manually in the split pass after the
5434   combine pass.  Notice that combine does try the target pattern of this
5435   split, but if the pattern is added it interferes with other patterns, in
5436   particular with the div0s comparisons.
5437   This could also be done with a peephole but doing it here before register
5438   allocation can save one temporary.
5439   When we're here, the not:SI pattern obviously has been matched already
5440   and we only have to see whether the following insn is the left shift.  */
5441
5442  rtx i = next_nonnote_insn_bb (curr_insn);
5443  if (i == NULL_RTX || !NONJUMP_INSN_P (i))
5444    FAIL;
5445
5446  rtx p = PATTERN (i);
5447  if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
5448    FAIL;
5449
5450  rtx p0 = XVECEXP (p, 0, 0);
5451  rtx p1 = XVECEXP (p, 0, 1);
5452
5453  if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31)))  */
5454      GET_CODE (p0) == SET
5455      && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
5456      && REG_P (XEXP (XEXP (p0, 1), 0))
5457      && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
5458      && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
5459      && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
5460
5461      /* (clobber (reg:SI T_REG))  */
5462      && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
5463      && REGNO (XEXP (p1, 0)) == T_REG)
5464    {
5465      operands[0] = XEXP (p0, 0);
5466      set_insn_deleted (i);
5467    }
5468  else
5469    FAIL;
5470}
5471  [(set_attr "type" "arith")])
5472
5473(define_expand "one_cmpldi2"
5474  [(set (match_operand:DI 0 "arith_reg_dest" "")
5475	(xor:DI (match_operand:DI 1 "arith_reg_operand" "")
5476		(const_int -1)))]
5477  "TARGET_SHMEDIA" "")
5478
5479(define_expand "abs<mode>2"
5480  [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
5481		   (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5482	      (clobber (reg:SI T_REG))])]
5483  "TARGET_SH1")
5484
5485(define_insn_and_split "*abs<mode>2"
5486  [(set (match_operand:SIDI 0 "arith_reg_dest")
5487  	(abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5488   (clobber (reg:SI T_REG))]
5489  "TARGET_SH1"
5490  "#"
5491  "&& can_create_pseudo_p ()"
5492  [(const_int 0)]
5493{
5494  if (<MODE>mode == SImode)
5495    emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5496  else
5497    {
5498      rtx high_src = gen_highpart (SImode, operands[1]);
5499      emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5500    }
5501
5502  emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5503				 const1_rtx));
5504  DONE;
5505})
5506
5507(define_insn_and_split "*negabs<mode>2"
5508  [(set (match_operand:SIDI 0 "arith_reg_dest")
5509	(neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
5510   (clobber (reg:SI T_REG))]
5511  "TARGET_SH1"
5512  "#"
5513  "&& can_create_pseudo_p ()"
5514  [(const_int 0)]
5515{
5516  if (<MODE>mode == SImode)
5517    emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5518  else
5519    {
5520      rtx high_src = gen_highpart (SImode, operands[1]);
5521      emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5522    }
5523
5524  emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5525				 const0_rtx));
5526  DONE;
5527})
5528
5529;; The SH4 202 can do zero-offset branches without pipeline stalls.
5530;; This can be used as some kind of conditional execution, which is useful
5531;; for abs.
5532;; Actually the instruction scheduling should decide whether to use a
5533;; zero-offset branch or not for any generic case involving a single
5534;; instruction on SH4 202.
5535(define_insn_and_split "negsi_cond"
5536  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5537	(if_then_else
5538	  (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
5539	  (match_operand:SI 1 "arith_reg_operand" "0,0")
5540	  (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
5541  "TARGET_SH1 && TARGET_ZDCBRANCH"
5542{
5543  static const char* alt[] =
5544  {
5545       "bt	0f"	"\n"
5546    "	neg	%2,%0"	"\n"
5547    "0:",
5548
5549       "bf	0f"	"\n"
5550    "	neg	%2,%0"	"\n"
5551    "0:"
5552  };
5553  return alt[which_alternative];
5554}
5555  "TARGET_SH1 && ! TARGET_ZDCBRANCH"
5556  [(const_int 0)]
5557{
5558  rtx skip_neg_label = gen_label_rtx ();
5559
5560  emit_move_insn (operands[0], operands[1]);
5561
5562  emit_jump_insn (INTVAL (operands[3])
5563		  ? gen_branch_true (skip_neg_label)
5564		  : gen_branch_false (skip_neg_label));
5565
5566  emit_label_after (skip_neg_label,
5567		    emit_insn (gen_negsi2 (operands[0], operands[1])));
5568  DONE;
5569}
5570  [(set_attr "type" "arith") ;; poor approximation
5571   (set_attr "length" "4")])
5572
5573(define_insn_and_split "negdi_cond"
5574  [(set (match_operand:DI 0 "arith_reg_dest")
5575	(if_then_else
5576	  (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
5577	  (match_operand:DI 1 "arith_reg_operand")
5578	  (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
5579   (clobber (reg:SI T_REG))]
5580  "TARGET_SH1"
5581  "#"
5582  "&& can_create_pseudo_p ()"
5583  [(const_int 0)]
5584{
5585  rtx skip_neg_label = gen_label_rtx ();
5586
5587  emit_move_insn (operands[0], operands[1]);
5588
5589  emit_jump_insn (INTVAL (operands[3]) 
5590		  ? gen_branch_true (skip_neg_label)
5591		  : gen_branch_false (skip_neg_label));
5592
5593  if (!INTVAL (operands[3]))
5594    emit_insn (gen_clrt ());
5595
5596  emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5597		       gen_lowpart (SImode, operands[1])));
5598  emit_label_after (skip_neg_label,
5599		    emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5600					 gen_highpart (SImode, operands[1]))));
5601  DONE;
5602})
5603
5604(define_expand "bswapsi2"
5605  [(set (match_operand:SI 0 "arith_reg_dest" "")
5606	(bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
5607  "TARGET_SH1"
5608{
5609  if (! can_create_pseudo_p ())
5610    FAIL;
5611  else
5612    {
5613      rtx tmp0 = gen_reg_rtx (SImode);
5614      rtx tmp1 = gen_reg_rtx (SImode);
5615
5616      emit_insn (gen_swapbsi2 (tmp0, operands[1]));
5617      emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
5618      emit_insn (gen_swapbsi2 (operands[0], tmp1));
5619      DONE;
5620    }
5621})
5622
5623(define_insn "swapbsi2"
5624  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5625	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
5626			(const_int -65536)) ;; 0xFFFF0000
5627		(ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5628				(const_int 65280))
5629			(and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5630				(const_int 255)))))]
5631  "TARGET_SH1"
5632  "swap.b	%1,%0"
5633  [(set_attr "type" "arith")])
5634
5635;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
5636;; partial byte swap expressions such as...
5637;;   ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
5638;; ...which are currently not handled by the tree optimizers.
5639;; The combine pass will not initially try to combine the full expression,
5640;; but only some sub-expressions.  In such a case the *swapbisi2_and_shl8
5641;; pattern acts as an intermediate pattern that will eventually lead combine
5642;; to the swapbsi2 pattern above.
5643;; As a side effect this also improves code that does (x & 0xFF) << 8
5644;; or (x << 8) & 0xFF00.
5645(define_insn_and_split "*swapbisi2_and_shl8"
5646  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5647	(ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5648				   (const_int 8))
5649			(const_int 65280))
5650		(match_operand:SI 2 "arith_reg_operand" "r")))]
5651  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5652  "#"
5653  "&& can_create_pseudo_p ()"
5654  [(const_int 0)]
5655{
5656  rtx tmp0 = gen_reg_rtx (SImode);
5657  rtx tmp1 = gen_reg_rtx (SImode);
5658
5659  emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
5660  emit_insn (gen_swapbsi2 (tmp1, tmp0));
5661  emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
5662  DONE;
5663})
5664
5665;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
5666;; intermediate pattern that will help the combine pass arriving at swapbsi2.
5667(define_insn_and_split "*swapbhisi2"
5668  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5669	(ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5670				   (const_int 8))
5671			(const_int 65280))
5672		(zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
5673  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5674  "#"
5675  "&& can_create_pseudo_p ()"
5676  [(const_int 0)]
5677{
5678  rtx tmp = gen_reg_rtx (SImode);
5679
5680  emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
5681  emit_insn (gen_swapbsi2 (operands[0], tmp));
5682  DONE;
5683})
5684
5685;; In some cases the swapbsi2 pattern might leave a sequence such as...
5686;;   swap.b  r4,r4
5687;;   mov     r4,r0
5688;;
5689;; which can be simplified to...
5690;;   swap.b  r4,r0
5691(define_peephole2
5692  [(set (match_operand:SI 0 "arith_reg_dest" "")
5693	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5694			(const_int -65536)) ;; 0xFFFF0000
5695		(ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5696				(const_int 65280))
5697			(and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5698				(const_int 255)))))
5699   (set (match_operand:SI 2 "arith_reg_dest" "")
5700	(match_dup 0))]
5701  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
5702  [(set (match_dup 2)
5703	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5704			(const_int -65536)) ;; 0xFFFF0000
5705		(ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5706				(const_int 65280))
5707			(and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5708				(const_int 255)))))])
5709
5710;; -------------------------------------------------------------------------
5711;; Zero extension instructions
5712;; -------------------------------------------------------------------------
5713
5714(define_insn "zero_extendsidi2"
5715  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5716	(zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
5717  "TARGET_SHMEDIA"
5718  "addz.l	%1, r63, %0"
5719  [(set_attr "type" "arith_media")
5720   (set_attr "highpart" "extend")])
5721
5722(define_insn "zero_extendhidi2"
5723  [(set (match_operand:DI 0 "register_operand" "=r,r")
5724	(zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5725  "TARGET_SHMEDIA"
5726  "@
5727	#
5728	ld%M1.uw	%m1, %0"
5729  [(set_attr "type" "*,load_media")
5730   (set (attr "highpart")
5731	(cond [(match_test "sh_contains_memref_p (insn)")
5732	       (const_string "user")]
5733	      (const_string "ignore")))])
5734
5735(define_split
5736  [(set (match_operand:DI 0 "register_operand" "")
5737	(zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
5738  "TARGET_SHMEDIA && reload_completed"
5739  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
5740   (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
5741{
5742  if (GET_CODE (operands[1]) == TRUNCATE)
5743    operands[1] = XEXP (operands[1], 0);
5744})
5745
5746;; ??? when a truncated input to a zero_extend is reloaded, reload will
5747;; reload the entire truncate expression.
5748(define_insn_and_split "*loaddi_trunc"
5749  [(set (match_operand 0 "any_register_operand" "=r")
5750	(truncate (match_operand:DI 1 "memory_operand" "m")))]
5751  "TARGET_SHMEDIA && reload_completed"
5752  "#"
5753  "TARGET_SHMEDIA && reload_completed"
5754  [(set (match_dup 0) (match_dup 1))]
5755{
5756  operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5757})
5758
5759(define_insn "zero_extendqidi2"
5760  [(set (match_operand:DI 0 "register_operand" "=r,r")
5761	(zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5762  "TARGET_SHMEDIA"
5763  "@
5764	andi	%1, 255, %0
5765	ld%M1.ub	%m1, %0"
5766  [(set_attr "type" "arith_media,load_media")
5767   (set (attr "highpart")
5768	(cond [(match_test "sh_contains_memref_p (insn)")
5769	       (const_string "user")]
5770	      (const_string "ignore")))])
5771
5772(define_expand "zero_extend<mode>si2"
5773  [(set (match_operand:SI 0 "arith_reg_dest")
5774	(zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
5775
5776(define_insn_and_split "*zero_extend<mode>si2_compact"
5777  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5778	(zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
5779  "TARGET_SH1"
5780  "extu.<bw>	%1,%0"
5781  "&& can_create_pseudo_p ()"
5782  [(set (match_dup 0) (match_dup 2))]
5783{
5784  /* Sometimes combine fails to combine a T bit or negated T bit store to a
5785     reg with a following zero extension.  In the split pass after combine,
5786     try to figure out how the extended reg was set.  If it originated from
5787     the T bit we can replace the zero extension with a reg move, which will
5788     be eliminated.  Notice that this also helps the *cbranch_t splitter when
5789     it tries to post-combine tests and conditional branches, as it does not
5790     check for zero extensions.  */
5791  operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
5792  if (operands[2] == NULL_RTX)
5793    FAIL;
5794}
5795  [(set_attr "type" "arith")])
5796
5797(define_insn "*zero_extendhisi2_media"
5798  [(set (match_operand:SI 0 "register_operand" "=r,r")
5799	(zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5800  "TARGET_SHMEDIA"
5801  "@
5802	#
5803	ld%M1.uw	%m1, %0"
5804  [(set_attr "type" "arith_media,load_media")
5805   (set (attr "highpart")
5806	(cond [(match_test "sh_contains_memref_p (insn)")
5807	       (const_string "user")]
5808	      (const_string "ignore")))])
5809
5810(define_split
5811  [(set (match_operand:SI 0 "register_operand" "")
5812	(zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
5813  "TARGET_SHMEDIA && reload_completed"
5814  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5815   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5816{
5817  rtx op1 = operands[1];
5818
5819  if (GET_CODE (op1) == TRUNCATE)
5820    op1 = XEXP (op1, 0);
5821  operands[2]
5822    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
5823			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
5824})
5825
5826(define_insn "*zero_extendqisi2_media"
5827  [(set (match_operand:SI 0 "register_operand" "=r,r")
5828	(zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5829  "TARGET_SHMEDIA"
5830  "@
5831	andi	%1, 255, %0
5832	ld%M1.ub	%m1, %0"
5833  [(set_attr "type" "arith_media,load_media")
5834   (set (attr "highpart")
5835	(cond [(match_test "sh_contains_memref_p (insn)")
5836	       (const_string "user")]
5837	      (const_string "ignore")))])
5838
5839(define_insn "zero_extendqihi2"
5840  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
5841	(zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
5842  "TARGET_SH1"
5843  "extu.b	%1,%0"
5844  [(set_attr "type" "arith")])
5845
5846;; SH2A supports two zero extending load instructions: movu.b and movu.w.
5847;; They could also be used for simple memory addresses like @Rn by setting
5848;; the displacement value to zero.  However, doing so too early results in
5849;; missed opportunities for other optimizations such as post-inc or index
5850;; addressing loads.
5851;; Although the 'zero_extend_movu_operand' predicate does not allow simple
5852;; register addresses (an address without a displacement, index, post-inc),
5853;; zero-displacement addresses might be generated during reload, wich are
5854;; simplified to simple register addresses in turn.  Thus, we have to
5855;; provide the Sdd and Sra alternatives in the patterns.
5856(define_insn "*zero_extend<mode>si2_disp_mem"
5857  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5858	(zero_extend:SI
5859	  (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
5860  "TARGET_SH2A"
5861  "@
5862	movu.<bw>	%1,%0
5863	movu.<bw>	@(0,%t1),%0"
5864  [(set_attr "type" "load")
5865   (set_attr "length" "4")])
5866
5867;; Convert the zero extending loads in sequences such as:
5868;;	movu.b	@(1,r5),r0	movu.w	@(2,r5),r0
5869;;	mov.b	r0,@(1,r4)	mov.b	r0,@(1,r4)
5870;;
5871;; back to sign extending loads like:
5872;;	mov.b	@(1,r5),r0	mov.w	@(2,r5),r0
5873;;	mov.b	r0,@(1,r4)	mov.b	r0,@(1,r4)
5874;;
5875;; if the extension type is irrelevant.  The sign extending mov.{b|w} insn
5876;; is only 2 bytes in size if the displacement is {K04|K05}.
5877;; If the displacement is greater it doesn't matter, so we convert anyways.
5878(define_peephole2
5879  [(set (match_operand:SI 0 "arith_reg_dest" "")
5880	(zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
5881   (set (match_operand 2 "general_operand" "")
5882	(match_operand 3 "arith_reg_operand" ""))]
5883  "TARGET_SH2A
5884   && REGNO (operands[0]) == REGNO (operands[3])
5885   && peep2_reg_dead_p (2, operands[0])
5886   && GET_MODE_SIZE (GET_MODE (operands[2]))
5887      <= GET_MODE_SIZE (GET_MODE (operands[1]))"
5888  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
5889   (set (match_dup 2) (match_dup 3))])
5890
5891;; Fold sequences such as
5892;;	mov.b	@r3,r7
5893;;	extu.b	r7,r7
5894;; into
5895;;	movu.b	@(0,r3),r7
5896;; This does not reduce the code size but the number of instructions is
5897;; halved, which results in faster code.
5898(define_peephole2
5899  [(set (match_operand:SI 0 "arith_reg_dest" "")
5900	(sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
5901   (set (match_operand:SI 2 "arith_reg_dest" "")
5902	(zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
5903  "TARGET_SH2A
5904   && GET_MODE (operands[1]) == GET_MODE (operands[3])
5905   && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
5906   && REGNO (operands[0]) == REGNO (operands[3])
5907   && (REGNO (operands[2]) == REGNO (operands[0])
5908       || peep2_reg_dead_p (2, operands[0]))"
5909  [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
5910{
5911  operands[4]
5912    = replace_equiv_address (operands[1],
5913			     gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
5914					   const0_rtx));
5915})
5916
5917;; -------------------------------------------------------------------------
5918;; Sign extension instructions
5919;; -------------------------------------------------------------------------
5920
5921;; ??? This should be a define expand.
5922;; ??? Or perhaps it should be dropped?
5923
5924;; convert_move generates good code for SH[1-4].
5925(define_insn "extendsidi2"
5926  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
5927	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
5928  "TARGET_SHMEDIA"
5929  "@
5930	add.l	%1, r63, %0
5931	ld%M1.l	%m1, %0
5932	fmov.sl	%1, %0"
5933  [(set_attr "type" "arith_media,load_media,fpconv_media")
5934   (set (attr "highpart")
5935	(cond [(match_test "sh_contains_memref_p (insn)")
5936	       (const_string "user")]
5937	      (const_string "extend")))])
5938
5939(define_insn "extendhidi2"
5940  [(set (match_operand:DI 0 "register_operand" "=r,r")
5941	(sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5942  "TARGET_SHMEDIA"
5943  "@
5944	#
5945	ld%M1.w	%m1, %0"
5946  [(set_attr "type" "*,load_media")
5947   (set (attr "highpart")
5948	(cond [(match_test "sh_contains_memref_p (insn)")
5949	       (const_string "user")]
5950	      (const_string "ignore")))])
5951
5952(define_split
5953  [(set (match_operand:DI 0 "register_operand" "")
5954	(sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
5955  "TARGET_SHMEDIA && reload_completed"
5956  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
5957   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
5958{
5959  if (GET_CODE (operands[1]) == TRUNCATE)
5960    operands[1] = XEXP (operands[1], 0);
5961})
5962
5963(define_insn "extendqidi2"
5964  [(set (match_operand:DI 0 "register_operand" "=r,r")
5965	(sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5966  "TARGET_SHMEDIA"
5967  "@
5968	#
5969	ld%M1.b	%m1, %0"
5970  [(set_attr "type" "*,load_media")
5971   (set (attr "highpart")
5972	(cond [(match_test "sh_contains_memref_p (insn)")
5973	       (const_string "user")]
5974	      (const_string "ignore")))])
5975
5976(define_split
5977  [(set (match_operand:DI 0 "register_operand" "")
5978	(sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
5979  "TARGET_SHMEDIA && reload_completed"
5980  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
5981   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
5982{
5983  if (GET_CODE (operands[1]) == TRUNCATE)
5984    operands[1] = XEXP (operands[1], 0);
5985})
5986
5987(define_expand "extend<mode>si2"
5988  [(set (match_operand:SI 0 "arith_reg_dest")
5989	(sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
5990
5991(define_insn "*extendhisi2_media"
5992  [(set (match_operand:SI 0 "register_operand" "=r,r")
5993	(sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5994  "TARGET_SHMEDIA"
5995  "@
5996	#
5997	ld%M1.w	%m1, %0"
5998  [(set_attr "type" "arith_media,load_media")
5999   (set (attr "highpart")
6000	(cond [(match_test "sh_contains_memref_p (insn)")
6001	       (const_string "user")]
6002	      (const_string "ignore")))])
6003
6004(define_split
6005  [(set (match_operand:SI 0 "register_operand" "")
6006	(sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6007  "TARGET_SHMEDIA && reload_completed"
6008  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6009   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
6010{
6011  rtx op1 = operands[1];
6012  if (GET_CODE (op1) == TRUNCATE)
6013    op1 = XEXP (op1, 0);
6014  operands[2]
6015    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6016			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
6017})
6018
6019(define_insn_and_split "*extend<mode>si2_compact_reg"
6020  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6021	(sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6022  "TARGET_SH1"
6023  "exts.<bw>	%1,%0"
6024  "&& can_create_pseudo_p ()"
6025  [(set (match_dup 0) (match_dup 2))]
6026{
6027  /* Sometimes combine fails to combine a T bit or negated T bit store to a
6028     reg with a following sign extension.  In the split pass after combine,
6029     try to figure the extended reg was set.  If it originated from the T
6030     bit we can replace the sign extension with a reg move, which will be
6031     eliminated.  */
6032  operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6033  if (operands[2] == NULL_RTX)
6034    FAIL;
6035}
6036  [(set_attr "type" "arith")])
6037
6038;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6039;; See movqi insns.
6040(define_insn "*extend<mode>si2_compact_mem_disp"
6041  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6042	(sign_extend:SI
6043	  (mem:QIHI
6044	    (plus:SI
6045	      (match_operand:SI 1 "arith_reg_operand" "%r,r")
6046	      (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
6047  "TARGET_SH1 && ! TARGET_SH2A
6048   && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6049  "@
6050	mov.<bw>	@(%O2,%1),%0
6051	mov.<bw>	@%1,%0"
6052  [(set_attr "type" "load")])
6053
6054(define_insn "*extend<mode>si2_compact_mem_disp"
6055  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6056	(sign_extend:SI
6057	  (mem:QIHI
6058	    (plus:SI
6059	      (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6060	      (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
6061  "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6062  "@
6063	mov.<bw>	@(%O2,%1),%0
6064	mov.<bw>	@%1,%0
6065	mov.<bw>	@(%O2,%1),%0"
6066  [(set_attr "type" "load")
6067   (set_attr "length" "2,2,4")])
6068
6069;; The *_snd patterns will take care of other QImode/HImode addressing
6070;; modes than displacement addressing.  They must be defined _after_ the
6071;; displacement addressing patterns.  Otherwise the displacement addressing
6072;; patterns will not be picked.
6073(define_insn "*extend<mode>si2_compact_snd"
6074  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6075	(sign_extend:SI
6076	  (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
6077  "TARGET_SH1"
6078  "mov.<bw>	%1,%0"
6079  [(set_attr "type" "load")])
6080
6081(define_insn "*extendqisi2_media"
6082  [(set (match_operand:SI 0 "register_operand" "=r,r")
6083	(sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6084  "TARGET_SHMEDIA"
6085  "@
6086	#
6087	ld%M1.b	%m1, %0"
6088  [(set_attr "type" "arith_media,load_media")
6089   (set (attr "highpart")
6090	(cond [(match_test "sh_contains_memref_p (insn)")
6091	       (const_string "user")]
6092	      (const_string "ignore")))])
6093
6094(define_split
6095  [(set (match_operand:SI 0 "register_operand" "")
6096	(sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
6097  "TARGET_SHMEDIA && reload_completed"
6098  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6099   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6100{
6101  rtx op1 = operands[1];
6102  if (GET_CODE (op1) == TRUNCATE)
6103    op1 = XEXP (op1, 0);
6104  operands[2]
6105    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6106			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
6107})
6108
6109(define_expand "extendqihi2"
6110  [(set (match_operand:HI 0 "arith_reg_dest")
6111	(sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))]
6112  "TARGET_SH1")
6113
6114(define_insn "*extendqihi2_compact_reg"
6115  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6116	(sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6117  "TARGET_SH1"
6118  "exts.b	%1,%0"
6119  [(set_attr "type" "arith")])
6120
6121;; It would seem useful to combine the truncXi patterns into the movXi
6122;; patterns, but unary operators are ignored when matching constraints,
6123;; so we need separate patterns.
6124(define_insn "truncdisi2"
6125  [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
6126	(truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6127  "TARGET_SHMEDIA"
6128  "@
6129	add.l	%1, r63, %0
6130	st%M0.l	%m0, %1
6131	fst%M0.s	%m0, %T1
6132	fmov.ls	%1, %0
6133	fmov.sl	%T1, %0
6134	fmov.s	%T1, %0"
6135  [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,
6136		     fpconv_media,fmove_media")
6137   (set (attr "highpart")
6138	(cond [(match_test "sh_contains_memref_p (insn)")
6139	       (const_string "user")]
6140	      (const_string "extend")))])
6141
6142(define_insn "truncdihi2"
6143  [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
6144	(truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6145  "TARGET_SHMEDIA"
6146{
6147  static const char* alt[] =
6148  {
6149       "shlli	%1,48,%0"	"\n"
6150    "	shlri	%0,48,%0",
6151
6152       "st%M0.w	%m0, %1"
6153  };
6154  return alt[which_alternative];
6155}
6156  [(set_attr "type"   "arith_media,store_media")
6157   (set_attr "length" "8,4")
6158   (set (attr "highpart")
6159	(cond [(match_test "sh_contains_memref_p (insn)")
6160	       (const_string "user")]
6161	      (const_string "extend")))])
6162
6163; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6164; Because we use zero extension, we can't provide signed QImode compares
6165; using a simple compare or conditional branch insn.
6166(define_insn "truncdiqi2"
6167  [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6168	(truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6169  "TARGET_SHMEDIA"
6170  "@
6171	andi	%1, 255, %0
6172	st%M0.b	%m0, %1"
6173  [(set_attr "type"   "arith_media,store")
6174   (set (attr "highpart")
6175	(cond [(match_test "sh_contains_memref_p (insn)")
6176	       (const_string "user")]
6177	      (const_string "extend")))])
6178
6179;; -------------------------------------------------------------------------
6180;; Move instructions
6181;; -------------------------------------------------------------------------
6182
6183;; define push and pop so it is easy for sh.c
6184;; We can't use push and pop on SHcompact because the stack must always
6185;; be 8-byte aligned.
6186(define_expand "push"
6187  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6188	(match_operand:SI 0 "register_operand" "r,l,x"))]
6189  "TARGET_SH1 && ! TARGET_SH5"
6190  "")
6191
6192(define_expand "pop"
6193  [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6194	(mem:SI (post_inc:SI (reg:SI SP_REG))))]
6195  "TARGET_SH1 && ! TARGET_SH5"
6196  "")
6197
6198(define_expand "push_e"
6199  [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6200		   (match_operand:SF 0 "" ""))
6201	      (use (reg:PSI FPSCR_REG))
6202	      (clobber (scratch:SI))])]
6203  "TARGET_SH1 && ! TARGET_SH5"
6204  "")
6205
6206(define_insn "push_fpul"
6207  [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6208  "TARGET_SH2E && ! TARGET_SH5"
6209  "sts.l	fpul,@-r15"
6210  [(set_attr "type" "fstore")
6211   (set_attr "late_fp_use" "yes")
6212   (set_attr "hit_stack" "yes")])
6213
6214;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6215;; so use that.
6216(define_expand "push_4"
6217  [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6218		   (match_operand:DF 0 "" ""))
6219	      (use (reg:PSI FPSCR_REG))
6220	      (clobber (scratch:SI))])]
6221  "TARGET_SH1 && ! TARGET_SH5"
6222  "")
6223
6224(define_expand "pop_e"
6225  [(parallel [(set (match_operand:SF 0 "" "")
6226	      (mem:SF (post_inc:SI (reg:SI SP_REG))))
6227	      (use (reg:PSI FPSCR_REG))
6228	      (clobber (scratch:SI))])]
6229  "TARGET_SH1 && ! TARGET_SH5"
6230  "")
6231
6232(define_insn "pop_fpul"
6233  [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6234  "TARGET_SH2E && ! TARGET_SH5"
6235  "lds.l	@r15+,fpul"
6236  [(set_attr "type" "load")
6237   (set_attr "hit_stack" "yes")])
6238
6239(define_expand "pop_4"
6240  [(parallel [(set (match_operand:DF 0 "" "")
6241		   (mem:DF (post_inc:SI (reg:SI SP_REG))))
6242	      (use (reg:PSI FPSCR_REG))
6243	      (clobber (scratch:SI))])]
6244  "TARGET_SH1 && ! TARGET_SH5"
6245  "")
6246
6247(define_expand "push_fpscr"
6248  [(const_int 0)]
6249  "TARGET_SH2E"
6250{
6251  rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
6252						 gen_rtx_PRE_DEC (Pmode,
6253							  stack_pointer_rtx)),
6254					get_fpscr_rtx ()));
6255  add_reg_note (insn, REG_INC, stack_pointer_rtx);
6256  DONE;
6257})
6258
6259(define_expand "pop_fpscr"
6260  [(const_int 0)]
6261  "TARGET_SH2E"
6262{
6263  rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
6264					gen_frame_mem (PSImode,
6265						 gen_rtx_POST_INC (Pmode,
6266							  stack_pointer_rtx))));
6267  add_reg_note (insn, REG_INC, stack_pointer_rtx);
6268  DONE;
6269})
6270
6271;; The clrt and sett patterns can happen as the result of optimization and
6272;; insn expansion.
6273;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6274;; In this case they might not disappear completely, because the T reg is
6275;; a fixed hard reg.
6276;; When DImode operations that use the T reg as carry/borrow are split into
6277;; individual SImode operations, the T reg is usually cleared before the
6278;; first SImode insn.
6279(define_insn "clrt"
6280  [(set (reg:SI T_REG) (const_int 0))]
6281  "TARGET_SH1"
6282  "clrt"
6283  [(set_attr "type" "mt_group")])
6284
6285(define_insn "sett"
6286  [(set (reg:SI T_REG) (const_int 1))]
6287  "TARGET_SH1"
6288  "sett"
6289  [(set_attr "type" "mt_group")])
6290
6291;; Use the combine pass to transform sequences such as
6292;;	mov	r5,r0
6293;;	add	#1,r0
6294;;	shll2	r0
6295;;	mov.l	@(r0,r4),r0
6296;; into
6297;;	shll2	r5
6298;;	add	r4,r5
6299;;	mov.l	@(4,r5),r0
6300;;
6301;; See also PR 39423.
6302;; Notice that these patterns have a T_REG clobber, because the shift
6303;; sequence that will be split out might clobber the T_REG.  Ideally, the
6304;; clobber would be added conditionally, depending on the result of
6305;; sh_ashlsi_clobbers_t_reg_p.  When splitting out the shifts we must go
6306;; through the ashlsi3 expander in order to get the right shift insn --
6307;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
6308;; FIXME: Combine never tries this kind of patterns for DImode.
6309(define_insn_and_split "*movsi_index_disp_load"
6310  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6311	(match_operand:SI 1 "mem_index_disp_operand" "m"))
6312   (clobber (reg:SI T_REG))]
6313  "TARGET_SH1"
6314  "#"
6315  "&& can_create_pseudo_p ()"
6316  [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6317   (set (match_dup 0) (match_dup 7))]
6318{
6319  rtx mem = operands[1];
6320  rtx plus0_rtx = XEXP (mem, 0);
6321  rtx plus1_rtx = XEXP (plus0_rtx, 0);
6322  rtx mult_rtx = XEXP (plus1_rtx, 0);
6323
6324  operands[1] = XEXP (mult_rtx, 0);
6325  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6326  operands[3] = XEXP (plus1_rtx, 1);
6327  operands[4] = XEXP (plus0_rtx, 1);
6328  operands[5] = gen_reg_rtx (SImode);
6329  operands[6] = gen_reg_rtx (SImode);
6330  operands[7] =
6331    replace_equiv_address (mem,
6332			   gen_rtx_PLUS (SImode, operands[6], operands[4]));
6333
6334  emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
6335})
6336
6337(define_insn_and_split "*movhi_index_disp_load"
6338  [(set (match_operand:SI 0 "arith_reg_dest")
6339	(SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
6340   (clobber (reg:SI T_REG))]
6341  "TARGET_SH1"
6342  "#"
6343  "&& can_create_pseudo_p ()"
6344  [(const_int 0)]
6345{
6346  rtx mem = operands[1];
6347  rtx plus0_rtx = XEXP (mem, 0);
6348  rtx plus1_rtx = XEXP (plus0_rtx, 0);
6349  rtx mult_rtx = XEXP (plus1_rtx, 0);
6350
6351  rtx op_1 = XEXP (mult_rtx, 0);
6352  rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6353  rtx op_3 = XEXP (plus1_rtx, 1);
6354  rtx op_4 = XEXP (plus0_rtx, 1);
6355  rtx op_5 = gen_reg_rtx (SImode);
6356  rtx op_6 = gen_reg_rtx (SImode);
6357  rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6358
6359  emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6360  emit_insn (gen_addsi3 (op_6, op_5, op_3));
6361
6362  if (<CODE> == SIGN_EXTEND)
6363    {
6364      emit_insn (gen_extendhisi2 (operands[0], op_7));
6365      DONE;
6366    }
6367  else if (<CODE> == ZERO_EXTEND)
6368    {
6369      /* On SH2A the movu.w insn can be used for zero extending loads.  */
6370      if (TARGET_SH2A)
6371	emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
6372      else
6373	{
6374	  emit_insn (gen_extendhisi2 (operands[0], op_7));
6375	  emit_insn (gen_zero_extendhisi2 (operands[0],
6376				           gen_lowpart (HImode, operands[0])));
6377	}
6378      DONE;
6379    }
6380  else
6381    FAIL;
6382})
6383
6384(define_insn_and_split "*mov<mode>_index_disp_store"
6385  [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
6386	(match_operand:HISI 1 "arith_reg_operand" "r"))
6387   (clobber (reg:SI T_REG))]
6388  "TARGET_SH1"
6389  "#"
6390  "&& can_create_pseudo_p ()"
6391  [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6392   (set (match_dup 7) (match_dup 1))]
6393{
6394  rtx mem = operands[0];
6395  rtx plus0_rtx = XEXP (mem, 0);
6396  rtx plus1_rtx = XEXP (plus0_rtx, 0);
6397  rtx mult_rtx = XEXP (plus1_rtx, 0);
6398
6399  operands[0] = XEXP (mult_rtx, 0);
6400  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6401  operands[3] = XEXP (plus1_rtx, 1);
6402  operands[4] = XEXP (plus0_rtx, 1);
6403  operands[5] = gen_reg_rtx (SImode);
6404  operands[6] = gen_reg_rtx (SImode);
6405  operands[7] =
6406    replace_equiv_address (mem,
6407			   gen_rtx_PLUS (SImode, operands[6], operands[4]));
6408
6409  emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
6410})
6411
6412;; t/r must come after r/r, lest reload will try to reload stuff like
6413;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
6414;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
6415(define_insn "movsi_i"
6416  [(set (match_operand:SI 0 "general_movdst_operand"
6417	    "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
6418	(match_operand:SI 1 "general_movsrc_operand"
6419	 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
6420  "TARGET_SH1
6421   && ! TARGET_SH2E
6422   && ! TARGET_SH2A
6423   && (register_operand (operands[0], SImode)
6424       || register_operand (operands[1], SImode))"
6425  "@
6426	mov.l	%1,%0
6427	mov	%1,%0
6428	mov	%1,%0
6429	mov.l	%1,%0
6430	sts	%1,%0
6431	sts	%1,%0
6432	mov.l	%1,%0
6433	sts.l	%1,%0
6434	sts.l	%1,%0
6435	lds	%1,%0
6436	lds	%1,%0
6437	lds.l	%1,%0
6438	lds.l	%1,%0
6439	fake	%1,%0"
6440  [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,
6441		     pstore,gp_mac,prset,mem_mac,pload,pcload_si")
6442   (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
6443
6444;; t/r must come after r/r, lest reload will try to reload stuff like
6445;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
6446;; ??? This allows moves from macl to fpul to be recognized, but these moves
6447;; will require a reload.
6448;; ??? We can't include f/f because we need the proper FPSCR setting when
6449;; TARGET_FMOVD is in effect, and mode switching is done before reload.
6450(define_insn "movsi_ie"
6451  [(set (match_operand:SI 0 "general_movdst_operand"
6452	    "=r,r,r,r,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
6453	(match_operand:SI 1 "general_movsrc_operand"
6454	 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
6455  "(TARGET_SH2E || TARGET_SH2A)
6456   && (register_operand (operands[0], SImode)
6457       || register_operand (operands[1], SImode))"
6458  "@
6459	mov.l	%1,%0
6460	mov	%1,%0
6461	mov	%1,%0
6462	movi20	%1,%0
6463	movi20s	%1,%0
6464	mov.l	%1,%0
6465	sts	%1,%0
6466	sts	%1,%0
6467	mov.l	%1,%0
6468	sts.l	%1,%0
6469	sts.l	%1,%0
6470	lds	%1,%0
6471	lds	%1,%0
6472	lds.l	%1,%0
6473	lds.l	%1,%0
6474	lds.l	%1,%0
6475	sts.l	%1,%0
6476	fake	%1,%0
6477	lds	%1,%0
6478	sts	%1,%0
6479	fsts	fpul,%0
6480	flds	%1,fpul
6481	fmov	%1,%0
6482	! move optimized away"
6483  [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,
6484		     mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,
6485		     pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
6486   (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
6487   (set_attr_alternative "length"
6488     [(const_int 2)
6489      (const_int 2)
6490      (const_int 2)
6491      (const_int 4)
6492      (const_int 4)
6493      (if_then_else
6494	(match_test "TARGET_SH2A")
6495	(const_int 4) (const_int 2))
6496      (const_int 2)
6497      (const_int 2)
6498      (if_then_else
6499	(match_test "TARGET_SH2A")
6500	(const_int 4) (const_int 2))
6501      (const_int 2)
6502      (const_int 2)
6503      (const_int 2)
6504      (const_int 2)
6505      (const_int 2)
6506      (const_int 2)
6507      (const_int 2)
6508      (const_int 2)
6509      (const_int 2)
6510      (const_int 2)
6511      (const_int 2)
6512      (const_int 2)
6513      (const_int 2)
6514      (const_int 2)
6515      (const_int 0)])])
6516
6517(define_insn "movsi_i_lowpart"
6518  [(set (strict_low_part
6519	  (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
6520	(match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
6521   "TARGET_SH1
6522    && (register_operand (operands[0], SImode)
6523        || register_operand (operands[1], SImode))"
6524  "@
6525	mov.l	%1,%0
6526	mov	%1,%0
6527	mov	%1,%0
6528	mov.l	%1,%0
6529	sts	%1,%0
6530	sts	%1,%0
6531	mov.l	%1,%0
6532	fake	%1,%0"
6533  [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
6534
6535(define_insn_and_split "load_ra"
6536  [(set (match_operand:SI 0 "general_movdst_operand" "")
6537	(unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
6538  "TARGET_SH1"
6539  "#"
6540  "&& ! currently_expanding_to_rtl"
6541  [(set (match_dup 0) (match_dup 1))]
6542{
6543  if (TARGET_SHCOMPACT && crtl->saves_all_registers)
6544    operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
6545})
6546
6547;; The '?'s in the following constraints may not reflect the time taken
6548;; to perform the move. They are there to discourage the use of floating-
6549;; point registers for storing integer values.
6550(define_insn "*movsi_media"
6551  [(set (match_operand:SI 0 "general_movdst_operand"
6552	        "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
6553	(match_operand:SI 1 "general_movsrc_operand"
6554	 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
6555  "TARGET_SHMEDIA_FPU
6556   && (register_operand (operands[0], SImode)
6557       || sh_register_operand (operands[1], SImode)
6558       || GET_CODE (operands[1]) == TRUNCATE)"
6559  "@
6560	add.l	%1, r63, %0
6561	movi	%1, %0
6562	#
6563	ld%M1.l	%m1, %0
6564	st%M0.l	%m0, %N1
6565	fld%M1.s	%m1, %0
6566	fst%M0.s	%m0, %1
6567	fmov.ls	%N1, %0
6568	fmov.sl	%1, %0
6569	fmov.s	%1, %0
6570	ptabs	%1, %0
6571	gettr	%1, %0
6572	pt	%1, %0"
6573  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,
6574		       fload_media,fstore_media,fload_media,fpconv_media,
6575		       fmove_media,ptabs_media,gettr_media,pt_media")
6576   (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
6577   (set (attr "highpart")
6578	(cond [(match_test "sh_contains_memref_p (insn)")
6579	       (const_string "user")]
6580	      (const_string "ignore")))])
6581
6582(define_insn "*movsi_media_nofpu"
6583  [(set (match_operand:SI 0 "general_movdst_operand"
6584	        "=r,r,r,r,m,*b,r,*b")
6585	(match_operand:SI 1 "general_movsrc_operand"
6586	 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
6587  "TARGET_SHMEDIA
6588   && (register_operand (operands[0], SImode)
6589       || sh_register_operand (operands[1], SImode)
6590       || GET_CODE (operands[1]) == TRUNCATE)"
6591  "@
6592	add.l	%1, r63, %0
6593	movi	%1, %0
6594	#
6595	ld%M1.l	%m1, %0
6596	st%M0.l	%m0, %N1
6597	ptabs	%1, %0
6598	gettr	%1, %0
6599	pt	%1, %0"
6600  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
6601		     ptabs_media,gettr_media,pt_media")
6602   (set_attr "length" "4,4,8,4,4,4,4,12")
6603   (set (attr "highpart")
6604	(cond [(match_test "sh_contains_memref_p (insn)")
6605	       (const_string "user")]
6606	      (const_string "ignore")))])
6607
6608(define_expand "movsi_const"
6609  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6610	(const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6611			      (const_int 16)] UNSPEC_EXTRACT_S16)))
6612   (set (match_dup 0)
6613	(ior:SI (ashift:SI (match_dup 0) (const_int 16))
6614		(const:SI (unspec:SI [(match_dup 1)
6615				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
6616  "TARGET_SHMEDIA && reload_completed
6617   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6618{
6619  if (GET_CODE (operands[1]) == LABEL_REF
6620      && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
6621    LABEL_NUSES (XEXP (operands[1], 0)) += 2;
6622  else if (GOTOFF_P (operands[1]))
6623    {
6624      rtx unspec = XEXP (operands[1], 0);
6625
6626      if (! UNSPEC_GOTOFF_P (unspec))
6627	{
6628	  unspec = XEXP (unspec, 0);
6629	  if (! UNSPEC_GOTOFF_P (unspec))
6630	    abort ();
6631	}
6632      if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
6633	  && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
6634	LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
6635    }
6636})
6637
6638(define_expand "movsi_const_16bit"
6639  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6640	(const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6641			      (const_int 0)] UNSPEC_EXTRACT_S16)))]
6642  "TARGET_SHMEDIA && flag_pic && reload_completed
6643   && GET_CODE (operands[1]) == SYMBOL_REF"
6644  "")
6645
6646(define_split
6647  [(set (match_operand:SI 0 "arith_reg_dest" "")
6648	(match_operand:SI 1 "immediate_operand" ""))]
6649  "TARGET_SHMEDIA && reload_completed
6650   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6651  [(const_int 0)]
6652{
6653  rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
6654
6655  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
6656
6657  DONE;
6658})
6659
6660(define_split
6661  [(set (match_operand:SI 0 "register_operand" "")
6662	(match_operand:SI 1 "immediate_operand" ""))]
6663  "TARGET_SHMEDIA && reload_completed
6664   && ((CONST_INT_P (operands[1])
6665	&& ! satisfies_constraint_I16 (operands[1]))
6666       || GET_CODE (operands[1]) == CONST_DOUBLE)"
6667  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6668
6669(define_expand "movsi"
6670  [(set (match_operand:SI 0 "general_movdst_operand" "")
6671	(match_operand:SI 1 "general_movsrc_operand" ""))]
6672  ""
6673{
6674  prepare_move_operands (operands, SImode);
6675})
6676
6677(define_expand "ic_invalidate_line"
6678  [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
6679				(match_dup 1)] UNSPEC_ICACHE)
6680	      (clobber (scratch:SI))])]
6681  "TARGET_HARD_SH4 || TARGET_SH5"
6682{
6683  if (TARGET_SHMEDIA)
6684    {
6685      emit_insn (gen_ic_invalidate_line_media (operands[0]));
6686      DONE;
6687    }
6688  else if (TARGET_SHCOMPACT)
6689    {
6690      operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
6691      operands[1] = force_reg (Pmode, operands[1]);
6692      emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
6693      DONE;
6694    }
6695  else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
6696    {
6697      emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
6698      DONE;
6699    }
6700  operands[0] = force_reg (Pmode, operands[0]);
6701  operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
6702							       Pmode)));
6703})
6704
6705;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
6706;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
6707;; the requirement *1*00 for associative address writes.  The alignment of
6708;; %0 implies that its least significant bit is cleared,
6709;; thus we clear the V bit of a matching entry if there is one.
6710(define_insn "ic_invalidate_line_i"
6711  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
6712		     (match_operand:SI 1 "register_operand" "r")]
6713		     UNSPEC_ICACHE)
6714   (clobber (match_scratch:SI 2 "=&r"))]
6715  "TARGET_HARD_SH4"
6716{
6717  return       "ocbwb	@%0"	"\n"
6718	 "	extu.w	%0,%2"	"\n"
6719	 "	or	%1,%2"	"\n"
6720	 "	mov.l	%0,@%2";
6721}
6722  [(set_attr "length" "8")
6723   (set_attr "type" "cwb")])
6724
6725(define_insn "ic_invalidate_line_sh4a"
6726  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
6727		    UNSPEC_ICACHE)]
6728  "TARGET_SH4A_ARCH || TARGET_SH4_300"
6729{
6730  return       "ocbwb	@%0"	"\n"
6731	 "	synco"		"\n"
6732	 "	icbi	@%0";
6733}
6734  [(set_attr "length" "16")	;; FIXME: Why 16 and not 6?  Looks like typo.
6735   (set_attr "type" "cwb")])
6736
6737;; ??? could make arg 0 an offsettable memory operand to allow to save
6738;; an add in the code that calculates the address.
6739(define_insn "ic_invalidate_line_media"
6740  [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
6741		    UNSPEC_ICACHE)]
6742  "TARGET_SHMEDIA"
6743{
6744  return       "ocbwb	%0,0"	"\n"
6745	 "	synco"		"\n"
6746	 "	icbi	%0,0"	"\n"
6747	 "	synci";
6748}
6749  [(set_attr "length" "16")
6750   (set_attr "type" "invalidate_line_media")])
6751
6752(define_insn "ic_invalidate_line_compact"
6753  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6754		     (match_operand:SI 1 "register_operand" "r")]
6755		    UNSPEC_ICACHE)
6756   (clobber (reg:SI PR_REG))]
6757  "TARGET_SHCOMPACT"
6758  "jsr @%1%#"
6759  [(set_attr "type" "sfunc")
6760   (set_attr "needs_delay_slot" "yes")])
6761
6762(define_expand "initialize_trampoline"
6763  [(match_operand:SI 0 "" "")
6764   (match_operand:SI 1 "" "")
6765   (match_operand:SI 2 "" "")]
6766  "TARGET_SHCOMPACT"
6767{
6768  rtx sfun, tramp;
6769
6770  tramp = force_reg (Pmode, operands[0]);
6771  sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
6772					    SFUNC_STATIC));
6773  emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
6774  emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
6775
6776  emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
6777  DONE;
6778})
6779
6780(define_insn "initialize_trampoline_compact"
6781  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6782		     (match_operand:SI 1 "register_operand" "r")
6783		     (reg:SI R2_REG) (reg:SI R3_REG)]
6784		    UNSPEC_INIT_TRAMP)
6785
6786   (clobber (reg:SI PR_REG))]
6787  "TARGET_SHCOMPACT"
6788  "jsr @%1%#"
6789  [(set_attr "type" "sfunc")
6790   (set_attr "needs_delay_slot" "yes")])
6791
6792(define_expand "movhi"
6793  [(set (match_operand:HI 0 "general_movdst_operand" "")
6794	(match_operand:HI 1 "general_movsrc_operand" ""))]
6795  ""
6796{
6797  prepare_move_operands (operands, HImode);
6798})
6799
6800(define_expand "movqi"
6801  [(set (match_operand:QI 0 "general_operand" "")
6802	(match_operand:QI 1 "general_operand" ""))]
6803  ""
6804{
6805  prepare_move_operands (operands, QImode);
6806})
6807
6808;; Specifying the displacement addressing load / store patterns separately
6809;; before the generic movqi / movhi pattern allows controlling the order
6810;; in which load / store insns are selected in a more fine grained way.
6811;; FIXME: The non-SH2A and SH2A variants should be combined by adding
6812;; "enabled" attribute as it is done in other targets.
6813(define_insn "*mov<mode>_store_mem_disp04"
6814  [(set (mem:QIHI
6815	  (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
6816		   (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
6817	(match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
6818  "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
6819  "@
6820	mov.<bw>	%2,@(%O1,%0)
6821	mov.<bw>	%2,@%0"
6822  [(set_attr "type" "store")])
6823
6824(define_insn "*mov<mode>_store_mem_disp12"
6825  [(set (mem:QIHI
6826	  (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
6827		   (match_operand:SI 1 "const_int_operand" "<disp12>")))
6828	(match_operand:QIHI 2 "arith_reg_operand" "r"))]
6829  "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
6830  "mov.<bw>	%2,@(%O1,%0)"
6831  [(set_attr "type" "store")
6832   (set_attr "length" "4")])
6833
6834(define_insn "*mov<mode>_load_mem_disp04"
6835  [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
6836	(mem:QIHI
6837	  (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
6838		   (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
6839  "TARGET_SH1 && ! TARGET_SH2A
6840   && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6841  "@
6842	mov.<bw>	@(%O2,%1),%0
6843	mov.<bw>	@%1,%0"
6844  [(set_attr "type" "load")])
6845
6846(define_insn "*mov<mode>_load_mem_disp12"
6847  [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
6848	(mem:QIHI
6849	  (plus:SI
6850	    (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6851	    (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
6852  "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6853  "@
6854	mov.<bw>	@(%O2,%1),%0
6855	mov.<bw>	@%1,%0
6856	mov.<bw>	@(%O2,%1),%0"
6857  [(set_attr "type" "load")
6858   (set_attr "length" "2,2,4")])
6859
6860;; The order of the constraint alternatives is important here.
6861;; Q/r has to come first, otherwise PC relative loads might wrongly get
6862;; placed into delay slots.  Since there is no QImode PC relative load, the
6863;; Q constraint and general_movsrc_operand will reject it for QImode.
6864;; The Snd alternatives should come before Sdd in order to avoid a preference
6865;; of using r0 als the register operand for addressing modes other than
6866;; displacement addressing.
6867;; The Sdd alternatives allow only r0 as register operand, even though on
6868;; SH2A any register could be allowed by switching to a 32 bit insn.
6869;; Generally sticking to the r0 is preferrable, since it generates smaller
6870;; code.  Obvious r0 reloads can then be eliminated with a peephole on SH2A.
6871(define_insn "*mov<mode>"
6872  [(set (match_operand:QIHI 0 "general_movdst_operand"
6873			      "=r,r,r,Snd,r,  Sdd,z,  r,l")
6874	(match_operand:QIHI 1 "general_movsrc_operand"
6875			       "Q,r,i,r,  Snd,z,  Sdd,l,r"))]
6876  "TARGET_SH1
6877   && (arith_reg_operand (operands[0], <MODE>mode)
6878       || arith_reg_operand (operands[1], <MODE>mode))"
6879  "@
6880	mov.<bw>	%1,%0
6881	mov	%1,%0
6882	mov	%1,%0
6883	mov.<bw>	%1,%0
6884	mov.<bw>	%1,%0
6885	mov.<bw>	%1,%0
6886	mov.<bw>	%1,%0
6887	sts	%1,%0
6888	lds	%1,%0"
6889  [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset")
6890   (set (attr "length")
6891	(cond [(and (match_operand 0 "displacement_mem_operand")
6892		    (not (match_operand 0 "short_displacement_mem_operand")))
6893	       (const_int 4)
6894	       (and (match_operand 1 "displacement_mem_operand")
6895		    (not (match_operand 1 "short_displacement_mem_operand")))
6896	       (const_int 4)]
6897	      (const_int 2)))])
6898
6899(define_insn "*movqi_media"
6900  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
6901	(match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
6902  "TARGET_SHMEDIA
6903   && (arith_reg_operand (operands[0], QImode)
6904       || extend_reg_or_0_operand (operands[1], QImode))"
6905  "@
6906	add.l	%1, r63, %0
6907	movi	%1, %0
6908	ld%M1.ub	%m1, %0
6909	st%M0.b	%m0, %N1"
6910  [(set_attr "type" "arith_media,arith_media,load_media,store_media")
6911   (set (attr "highpart")
6912	(cond [(match_test "sh_contains_memref_p (insn)")
6913	       (const_string "user")]
6914	      (const_string "ignore")))])
6915
6916(define_expand "reload_inqi"
6917  [(set (match_operand:SI 2 "" "=&r")
6918	(match_operand:QI 1 "inqhi_operand" ""))
6919   (set (match_operand:QI 0 "arith_reg_operand" "=r")
6920	(truncate:QI (match_dup 3)))]
6921  "TARGET_SHMEDIA"
6922{
6923  rtx inner = XEXP (operands[1], 0);
6924  int regno = REGNO (inner);
6925
6926  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
6927  operands[1] = gen_rtx_REG (SImode, regno);
6928  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
6929})
6930
6931(define_insn "*movhi_media"
6932  [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
6933	(match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
6934  "TARGET_SHMEDIA
6935   && (arith_reg_operand (operands[0], HImode)
6936       || arith_reg_or_0_operand (operands[1], HImode))"
6937  "@
6938	add.l	%1, r63, %0
6939	movi	%1, %0
6940	#
6941	ld%M1.w	%m1, %0
6942	st%M0.w	%m0, %N1"
6943  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
6944   (set (attr "highpart")
6945	(cond [(match_test "sh_contains_memref_p (insn)")
6946	       (const_string "user")]
6947	      (const_string "ignore")))])
6948
6949(define_split
6950  [(set (match_operand:HI 0 "register_operand" "")
6951	(match_operand:HI 1 "immediate_operand" ""))]
6952  "TARGET_SHMEDIA && reload_completed
6953   && ! satisfies_constraint_I16 (operands[1])"
6954  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6955
6956(define_expand "reload_inhi"
6957  [(set (match_operand:SI 2 "" "=&r")
6958	(match_operand:HI 1 "inqhi_operand" ""))
6959   (set (match_operand:HI 0 "arith_reg_operand" "=r")
6960	(truncate:HI (match_dup 3)))]
6961  "TARGET_SHMEDIA"
6962{
6963  rtx inner = XEXP (operands[1], 0);
6964  int regno = REGNO (inner);
6965
6966  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
6967  operands[1] = gen_rtx_REG (SImode, regno);
6968  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
6969})
6970
6971;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
6972;; compiled with -m2 -ml -O3 -funroll-loops
6973(define_insn "*movdi_i"
6974  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
6975	(match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
6976  "TARGET_SH1
6977   && (arith_reg_operand (operands[0], DImode)
6978       || arith_reg_operand (operands[1], DImode))"
6979{
6980  return output_movedouble (insn, operands, DImode);
6981}
6982  [(set_attr "length" "4")
6983   (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
6984
6985;; If the output is a register and the input is memory or a register, we have
6986;; to be careful and see which word needs to be loaded first.
6987(define_split
6988  [(set (match_operand:DI 0 "general_movdst_operand" "")
6989	(match_operand:DI 1 "general_movsrc_operand" ""))]
6990  "TARGET_SH1 && reload_completed"
6991  [(set (match_dup 2) (match_dup 3))
6992   (set (match_dup 4) (match_dup 5))]
6993{
6994  int regno;
6995
6996  if ((MEM_P (operands[0])
6997       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6998      || (MEM_P (operands[1])
6999	  && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7000    FAIL;
7001
7002  switch (GET_CODE (operands[0]))
7003    {
7004    case REG:
7005      regno = REGNO (operands[0]);
7006      break;
7007    case SUBREG:
7008      regno = subreg_regno (operands[0]);
7009      break;
7010    case MEM:
7011      regno = -1;
7012      break;
7013    default:
7014      gcc_unreachable ();
7015    }
7016
7017  if (regno == -1
7018      || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7019    {
7020      operands[2] = operand_subword (operands[0], 0, 0, DImode);
7021      operands[3] = operand_subword (operands[1], 0, 0, DImode);
7022      operands[4] = operand_subword (operands[0], 1, 0, DImode);
7023      operands[5] = operand_subword (operands[1], 1, 0, DImode);
7024    }
7025  else
7026    {
7027      operands[2] = operand_subword (operands[0], 1, 0, DImode);
7028      operands[3] = operand_subword (operands[1], 1, 0, DImode);
7029      operands[4] = operand_subword (operands[0], 0, 0, DImode);
7030      operands[5] = operand_subword (operands[1], 0, 0, DImode);
7031    }
7032
7033  if (operands[2] == 0 || operands[3] == 0
7034      || operands[4] == 0 || operands[5] == 0)
7035    FAIL;
7036})
7037
7038;; The '?'s in the following constraints may not reflect the time taken
7039;; to perform the move. They are there to discourage the use of floating-
7040;; point registers for storing integer values.
7041(define_insn "*movdi_media"
7042  [(set (match_operand:DI 0 "general_movdst_operand"
7043	         "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
7044	(match_operand:DI 1 "general_movsrc_operand"
7045	 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7046  "TARGET_SHMEDIA_FPU
7047   && (register_operand (operands[0], DImode)
7048       || sh_register_operand (operands[1], DImode))"
7049  "@
7050	add	%1, r63, %0
7051	movi	%1, %0
7052	#
7053	ld%M1.q	%m1, %0
7054	st%M0.q	%m0, %N1
7055	fld%M1.d	%m1, %0
7056	fst%M0.d	%m0, %1
7057	fmov.qd	%N1, %0
7058	fmov.dq	%1, %0
7059	fmov.d	%1, %0
7060	ptabs	%1, %0
7061	gettr	%1, %0
7062	pt	%1, %0"
7063  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7064		     fload_media,fstore_media,fload_media,dfpconv_media,
7065		     fmove_media,ptabs_media,gettr_media,pt_media")
7066   (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7067
7068(define_insn "*movdi_media_nofpu"
7069  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
7070	(match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
7071  "TARGET_SHMEDIA
7072   && (register_operand (operands[0], DImode)
7073       || sh_register_operand (operands[1], DImode))"
7074  "@
7075	add	%1, r63, %0
7076	movi	%1, %0
7077	#
7078	ld%M1.q	%m1, %0
7079	st%M0.q	%m0, %N1
7080	ptabs	%1, %0
7081	gettr	%1, %0
7082	pt	%1, %0"
7083  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7084		     ptabs_media,gettr_media,pt_media")
7085   (set_attr "length" "4,4,16,4,4,4,4,*")])
7086
7087(define_insn "*movdi_media_I16"
7088  [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7089	(match_operand:DI 1 "const_int_operand" "I16"))]
7090  "TARGET_SHMEDIA && reload_completed"
7091  "movi	%1, %0"
7092  [(set_attr "type" "arith_media")
7093   (set_attr "length" "4")])
7094
7095(define_split
7096  [(set (match_operand:DI 0 "arith_reg_dest" "")
7097	(match_operand:DI 1 "immediate_operand" ""))]
7098  "TARGET_SHMEDIA && reload_completed
7099   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7100  [(set (match_dup 0) (match_dup 1))]
7101{
7102  rtx insn;
7103
7104  if (TARGET_SHMEDIA64)
7105    insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7106  else
7107    insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7108
7109  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7110
7111  DONE;
7112})
7113
7114(define_expand "movdi_const"
7115  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7116	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7117		  	      (const_int 48)] UNSPEC_EXTRACT_S16)))
7118   (set (match_dup 0)
7119	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7120		(const:DI (unspec:DI [(match_dup 1)
7121				      (const_int 32)] UNSPEC_EXTRACT_U16))))
7122   (set (match_dup 0)
7123	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7124		(const:DI (unspec:DI [(match_dup 1)
7125				      (const_int 16)] UNSPEC_EXTRACT_U16))))
7126   (set (match_dup 0)
7127	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7128		(const:DI (unspec:DI [(match_dup 1)
7129				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
7130  "TARGET_SHMEDIA64 && reload_completed
7131   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7132{
7133  sh_mark_label (operands[1], 4);
7134})
7135
7136(define_expand "movdi_const_32bit"
7137  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7138	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7139			      (const_int 16)] UNSPEC_EXTRACT_S16)))
7140   (set (match_dup 0)
7141	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7142		(const:DI (unspec:DI [(match_dup 1)
7143				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
7144  "TARGET_SHMEDIA32 && reload_completed
7145   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7146{
7147  sh_mark_label (operands[1], 2);
7148})
7149
7150(define_expand "movdi_const_16bit"
7151  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7152	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7153			      (const_int 0)] UNSPEC_EXTRACT_S16)))]
7154  "TARGET_SHMEDIA && flag_pic && reload_completed
7155   && GET_CODE (operands[1]) == SYMBOL_REF"
7156  "")
7157
7158(define_split
7159  [(set (match_operand:DI 0 "ext_dest_operand" "")
7160	(match_operand:DI 1 "immediate_operand" ""))]
7161  "TARGET_SHMEDIA && reload_completed
7162   && CONST_INT_P (operands[1])
7163   && ! satisfies_constraint_I16 (operands[1])"
7164  [(set (match_dup 0) (match_dup 2))
7165   (match_dup 1)]
7166{
7167  unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7168  unsigned HOST_WIDE_INT low = val;
7169  unsigned HOST_WIDE_INT high = val;
7170  unsigned HOST_WIDE_INT sign;
7171  unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7172
7173  /* Zero-extend the 16 least-significant bits.  */
7174  low &= 0xffff;
7175
7176  /* Arithmetic shift right the word by 16 bits.  */
7177  high >>= 16;
7178  if (GET_CODE (operands[0]) == SUBREG
7179      && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7180    {
7181      high &= 0xffff;
7182      high ^= 0x8000;
7183      high -= 0x8000;
7184    }
7185  else
7186    {
7187      sign = 1;
7188      sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7189      high ^= sign;
7190      high -= sign;
7191    }
7192  do
7193    {
7194      /* If we can't generate the constant with a two-insn movi / shori
7195	 sequence, try some other strategies.  */
7196      if (! CONST_OK_FOR_I16 (high))
7197	{
7198	  /* Try constant load / left shift.  We know VAL != 0.  */
7199	  val2 = val ^ (val-1);
7200	  if (val2 > 0x1ffff)
7201	    {
7202	      int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7203
7204	      if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7205		  || (! CONST_OK_FOR_I16 (high >> 16)
7206		      && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7207		{
7208		  val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7209		  operands[1] = gen_ashldi3_media (operands[0], operands[0],
7210						   GEN_INT (trailing_zeroes));
7211		  break;
7212		}
7213	    }
7214	  /* Try constant load / right shift.  */
7215	  val2 = (val >> 15) + 1;
7216	  if (val2 == (val2 & -val2))
7217	    {
7218	      int shift = 49 - exact_log2 (val2);
7219
7220	      val2 = trunc_int_for_mode (val << shift, DImode);
7221	      if (CONST_OK_FOR_I16 (val2))
7222		{
7223		  operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7224						   GEN_INT (shift));
7225		  break;
7226		}
7227	    }
7228	  /* Try mperm.w .  */
7229	  val2 = val & 0xffff;
7230	  if ((val >> 16 & 0xffff) == val2
7231	      && (val >> 32 & 0xffff) == val2
7232	      && (val >> 48 & 0xffff) == val2)
7233	    {
7234	      val2 = (HOST_WIDE_INT) val >> 48;
7235	      operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7236	      operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7237	      break;
7238	    }
7239	  /* Try movi / mshflo.l  */
7240	  val2 = (HOST_WIDE_INT) val >> 32;
7241	  if (val2 == ((unsigned HOST_WIDE_INT)
7242			trunc_int_for_mode (val, SImode)))
7243	    {
7244	      operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7245					     operands[0]);
7246	      break;
7247	    }
7248	  /* Try movi / mshflo.l w/ r63.  */
7249	  val2 = val + ((HOST_WIDE_INT) -1 << 32);
7250	  if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7251	    {
7252	      operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7253					     const0_rtx);
7254	      break;
7255	    }
7256	}
7257      val2 = high;
7258      operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7259    }
7260  while (0);
7261  operands[2] = GEN_INT (val2);
7262})
7263
7264(define_split
7265  [(set (match_operand:DI 0 "ext_dest_operand" "")
7266	(match_operand:DI 1 "immediate_operand" ""))]
7267  "TARGET_SHMEDIA && reload_completed
7268   && GET_CODE (operands[1]) == CONST_DOUBLE"
7269  [(set (match_dup 0) (match_dup 2))
7270  (set (match_dup 0)
7271       (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7272{
7273  unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7274  unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7275  unsigned HOST_WIDE_INT val = low;
7276  unsigned HOST_WIDE_INT sign;
7277
7278  /* Zero-extend the 16 least-significant bits.  */
7279  val &= 0xffff;
7280  operands[1] = GEN_INT (val);
7281
7282  /* Arithmetic shift right the double-word by 16 bits.  */
7283  low >>= 16;
7284  low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7285  high >>= 16;
7286  sign = 1;
7287  sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7288  high ^= sign;
7289  high -= sign;
7290
7291  /* This will only be true if high is a sign-extension of low, i.e.,
7292     it must be either 0 or (unsigned)-1, and be zero iff the
7293     most-significant bit of low is set.  */
7294  if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7295    operands[2] = GEN_INT (low);
7296  else
7297    operands[2] = immed_double_const (low, high, DImode);
7298})
7299
7300(define_insn "shori_media"
7301  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
7302	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7303			   (const_int 16))
7304		(match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
7305  "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
7306  "@
7307	shori	%u2, %0
7308	#"
7309  [(set_attr "type" "arith_media,*")])
7310
7311(define_insn "*shori_media_si"
7312  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7313	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7314			   (const_int 16))
7315		(match_operand:SI 2 "immediate_operand" "K16Csu")))]
7316  "TARGET_SHMEDIA"
7317  "shori	%u2, %0")
7318
7319(define_expand "movdi"
7320  [(set (match_operand:DI 0 "general_movdst_operand" "")
7321	(match_operand:DI 1 "general_movsrc_operand" ""))]
7322  ""
7323{
7324  prepare_move_operands (operands, DImode);
7325})
7326
7327(define_insn "movdf_media"
7328  [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7329	(match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7330  "TARGET_SHMEDIA_FPU
7331   && (register_operand (operands[0], DFmode)
7332       || sh_register_operand (operands[1], DFmode))"
7333  "@
7334	fmov.d	%1, %0
7335	fmov.qd	%N1, %0
7336	fmov.dq	%1, %0
7337	add	%1, r63, %0
7338	#
7339	fld%M1.d	%m1, %0
7340	fst%M0.d	%m0, %1
7341	ld%M1.q	%m1, %0
7342	st%M0.q	%m0, %N1"
7343  [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,
7344		     fload_media,fstore_media,load_media,store_media")])
7345
7346(define_insn "movdf_media_nofpu"
7347  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7348	(match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
7349  "TARGET_SHMEDIA
7350   && (register_operand (operands[0], DFmode)
7351       || sh_register_operand (operands[1], DFmode))"
7352  "@
7353	add	%1, r63, %0
7354	#
7355	ld%M1.q	%m1, %0
7356	st%M0.q	%m0, %N1"
7357  [(set_attr "type" "arith_media,*,load_media,store_media")])
7358
7359(define_split
7360  [(set (match_operand:DF 0 "arith_reg_dest" "")
7361	(match_operand:DF 1 "immediate_operand" ""))]
7362  "TARGET_SHMEDIA && reload_completed"
7363  [(set (match_dup 3) (match_dup 2))]
7364{
7365  int endian = WORDS_BIG_ENDIAN ? 1 : 0;
7366  long values[2];
7367  REAL_VALUE_TYPE value;
7368
7369  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
7370  REAL_VALUE_TO_TARGET_DOUBLE (value, values);
7371
7372  if (HOST_BITS_PER_WIDE_INT >= 64)
7373    operands[2] = immed_double_const ((unsigned long) values[endian]
7374				      | ((HOST_WIDE_INT) values[1 - endian]
7375					 << 32), 0, DImode);
7376  else
7377    {
7378      gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
7379      operands[2] = immed_double_const (values[endian], values[1 - endian],
7380	  			        DImode);
7381    }
7382
7383  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
7384})
7385
7386;; FIXME: This should be a define_insn_and_split.
7387(define_insn "movdf_k"
7388  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7389	(match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
7390  "TARGET_SH1
7391   && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
7392       /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
7393       || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
7394       || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
7395   && (arith_reg_operand (operands[0], DFmode)
7396       || arith_reg_operand (operands[1], DFmode))"
7397{
7398  return output_movedouble (insn, operands, DFmode);
7399}
7400  [(set_attr "length" "4")
7401   (set_attr "type" "move,pcload,load,store")])
7402
7403;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
7404;; However, the d/F/c/z alternative cannot be split directly; it is converted
7405;; with special code in machine_dependent_reorg into a load of the R0_REG and
7406;; the d/m/c/X alternative, which is split later into single-precision
7407;; instructions.  And when not optimizing, no splits are done before fixing
7408;; up pcloads, so we need usable length information for that.
7409(define_insn "movdf_i4"
7410  [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
7411	(match_operand:DF 1 "general_movsrc_operand"  "d,r,F,m,d,FQ,m,r,d,r"))
7412   (use (match_operand:PSI 2 "fpscr_operand"          "c,c,c,c,c,c,c,c,c,c"))
7413   (clobber (match_scratch:SI 3                      "=X,X,&z,X,X,X,X,X,X,X"))]
7414  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7415   && (arith_reg_operand (operands[0], DFmode)
7416       || arith_reg_operand (operands[1], DFmode))"
7417  {
7418    switch (which_alternative)
7419    {
7420    case 0:
7421      if (TARGET_FMOVD)
7422	return "fmov	%1,%0";
7423      else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
7424	return         "fmov	%R1,%R0"	"\n"
7425	       "	fmov	%S1,%S0";
7426      else
7427	return         "fmov	%S1,%S0"	"\n"
7428	       "	fmov	%R1,%R0";
7429    case 3:
7430    case 4:
7431      return "fmov.d	%1,%0";
7432    default:
7433      return "#";
7434    }
7435  }
7436  [(set_attr_alternative "length"
7437     [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
7438      (const_int 4)
7439      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7440      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7441      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7442      (const_int 4)
7443      (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
7444      ;; We can't use 4-byte push/pop on SHcompact, so we have to
7445      ;; increment or decrement r15 explicitly.
7446      (if_then_else
7447       (match_test "TARGET_SHCOMPACT")
7448       (const_int 10) (const_int 8))
7449      (if_then_else
7450       (match_test "TARGET_SHCOMPACT")
7451       (const_int 10) (const_int 8))])
7452   (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
7453   (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
7454   (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
7455					   (const_string "double")
7456					   (const_string "none")))])
7457
7458;; Moving DFmode between fp/general registers through memory
7459;; (the top of the stack) is faster than moving through fpul even for
7460;; little endian.  Because the type of an instruction is important for its
7461;; scheduling,  it is beneficial to split these operations, rather than
7462;; emitting them in one single chunk, even if this will expose a stack
7463;; use that will prevent scheduling of other stack accesses beyond this
7464;; instruction.
7465(define_split
7466  [(set (match_operand:DF 0 "register_operand" "")
7467	(match_operand:DF 1 "register_operand" ""))
7468   (use (match_operand:PSI 2 "fpscr_operand" ""))
7469   (clobber (match_scratch:SI 3 "=X"))]
7470  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
7471   && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
7472  [(const_int 0)]
7473{
7474  rtx insn, tos;
7475
7476  if (TARGET_SH5 && true_regnum (operands[1]) < 16)
7477    {
7478      emit_move_insn (stack_pointer_rtx,
7479		      plus_constant (Pmode, stack_pointer_rtx, -8));
7480      tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7481    }
7482  else
7483    tos = gen_tmp_stack_mem (DFmode,
7484			     gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
7485  insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
7486  if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
7487    add_reg_note (insn, REG_INC, stack_pointer_rtx);
7488  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7489    tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7490  else
7491    tos = gen_tmp_stack_mem (DFmode,
7492			     gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
7493  insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
7494  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7495    emit_move_insn (stack_pointer_rtx,
7496		    plus_constant (Pmode, stack_pointer_rtx, 8));
7497  else
7498    add_reg_note (insn, REG_INC, stack_pointer_rtx);
7499  DONE;
7500})
7501
7502;; local-alloc sometimes allocates scratch registers even when not required,
7503;; so we must be prepared to handle these.
7504
7505;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
7506(define_split
7507  [(set (match_operand:DF 0 "general_movdst_operand" "")
7508	(match_operand:DF 1 "general_movsrc_operand"  ""))
7509   (use (match_operand:PSI 2 "fpscr_operand" ""))
7510   (clobber (match_scratch:SI 3 ""))]
7511  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7512   && reload_completed
7513   && true_regnum (operands[0]) < 16
7514   && true_regnum (operands[1]) < 16"
7515  [(set (match_dup 0) (match_dup 1))]
7516{
7517  /* If this was a reg <-> mem operation with base + index reg addressing,
7518     we have to handle this in a special way.  */
7519  rtx mem = operands[0];
7520  int store_p = 1;
7521  if (! memory_operand (mem, DFmode))
7522    {
7523      mem = operands[1];
7524      store_p = 0;
7525    }
7526  if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
7527    mem = SUBREG_REG (mem);
7528  if (MEM_P (mem))
7529    {
7530      rtx addr = XEXP (mem, 0);
7531      if (GET_CODE (addr) == PLUS
7532	  && REG_P (XEXP (addr, 0))
7533	  && REG_P (XEXP (addr, 1)))
7534	{
7535	  int offset;
7536	  rtx reg0 = gen_rtx_REG (Pmode, 0);
7537	  rtx regop = operands[store_p], word0 ,word1;
7538
7539	  if (GET_CODE (regop) == SUBREG)
7540	    alter_subreg (&regop, true);
7541	  if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
7542	    offset = 2;
7543	  else
7544	    offset = 4;
7545	  mem = copy_rtx (mem);
7546	  PUT_MODE (mem, SImode);
7547	  word0 = gen_rtx_SUBREG (SImode, regop, 0);
7548	  alter_subreg (&word0, true);
7549	  word1 = gen_rtx_SUBREG (SImode, regop, 4);
7550	  alter_subreg (&word1, true);
7551	  if (store_p || ! refers_to_regno_p (REGNO (word0),
7552					      REGNO (word0) + 1, addr, 0))
7553	    {
7554	      emit_insn (store_p
7555			 ? gen_movsi_ie (mem, word0)
7556			 : gen_movsi_ie (word0, mem));
7557	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7558	      mem = copy_rtx (mem);
7559	      emit_insn (store_p
7560			 ? gen_movsi_ie (mem, word1)
7561			 : gen_movsi_ie (word1, mem));
7562	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7563	    }
7564	  else
7565	    {
7566	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7567	      emit_insn (gen_movsi_ie (word1, mem));
7568	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7569	      mem = copy_rtx (mem);
7570	      emit_insn (gen_movsi_ie (word0, mem));
7571	    }
7572	  DONE;
7573	}
7574    }
7575})
7576
7577;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
7578(define_split
7579  [(set (match_operand:DF 0 "register_operand" "")
7580	(match_operand:DF 1 "memory_operand"  ""))
7581   (use (match_operand:PSI 2 "fpscr_operand" ""))
7582   (clobber (reg:SI R0_REG))]
7583  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
7584  [(parallel [(set (match_dup 0) (match_dup 1))
7585	      (use (match_dup 2))
7586	      (clobber (scratch:SI))])]
7587  "")
7588
7589(define_expand "reload_indf__frn"
7590  [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
7591		   (match_operand:DF 1 "immediate_operand" "FQ"))
7592	      (use (reg:PSI FPSCR_REG))
7593	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7594  "TARGET_SH1"
7595  "")
7596
7597(define_expand "reload_outdf__RnFRm"
7598  [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
7599		   (match_operand:DF 1 "register_operand" "af,r"))
7600	      (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
7601  "TARGET_SH1"
7602  "")
7603
7604;; Simplify no-op moves.
7605(define_split
7606  [(set (match_operand:SF 0 "register_operand" "")
7607	(match_operand:SF 1 "register_operand" ""))
7608   (use (match_operand:PSI 2 "fpscr_operand" ""))
7609   (clobber (match_scratch:SI 3 ""))]
7610  "TARGET_SH2E && reload_completed
7611   && true_regnum (operands[0]) == true_regnum (operands[1])"
7612  [(set (match_dup 0) (match_dup 0))]
7613  "")
7614
7615;; fmovd substitute post-reload splits
7616(define_split
7617  [(set (match_operand:DF 0 "register_operand" "")
7618	(match_operand:DF 1 "register_operand" ""))
7619   (use (match_operand:PSI 2 "fpscr_operand" ""))
7620   (clobber (match_scratch:SI 3 ""))]
7621  "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
7622   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7623   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7624  [(const_int 0)]
7625{
7626  int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
7627  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
7628			   gen_rtx_REG (SFmode, src), operands[2]));
7629  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
7630			   gen_rtx_REG (SFmode, src + 1), operands[2]));
7631  DONE;
7632})
7633
7634(define_split
7635  [(set (match_operand:DF 0 "register_operand" "")
7636	(mem:DF (match_operand:SI 1 "register_operand" "")))
7637   (use (match_operand:PSI 2 "fpscr_operand" ""))
7638   (clobber (match_scratch:SI 3 ""))]
7639  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7640   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7641   && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
7642  [(const_int 0)]
7643{
7644  int regno = true_regnum (operands[0]);
7645  rtx insn;
7646  rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
7647  rtx mem2
7648    = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
7649  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7650					   regno + !! TARGET_LITTLE_ENDIAN),
7651				  mem2, operands[2]));
7652  add_reg_note (insn, REG_INC, operands[1]);
7653  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7654					       regno + ! TARGET_LITTLE_ENDIAN),
7655				  change_address (mem, SFmode, NULL_RTX),
7656				  operands[2]));
7657  DONE;
7658})
7659
7660(define_split
7661  [(set (match_operand:DF 0 "register_operand" "")
7662	(match_operand:DF 1 "memory_operand" ""))
7663   (use (match_operand:PSI 2 "fpscr_operand" ""))
7664   (clobber (match_scratch:SI 3 ""))]
7665  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7666   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
7667  [(const_int 0)]
7668{
7669  int regno = true_regnum (operands[0]);
7670  rtx addr, insn;
7671  rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
7672  rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
7673  rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
7674
7675  operands[1] = copy_rtx (mem2);
7676  addr = XEXP (mem2, 0);
7677
7678  switch (GET_CODE (addr))
7679    {
7680    case REG:
7681      /* This is complicated.  If the register is an arithmetic register
7682	 we can just fall through to the REG+DISP case below.  Otherwise
7683	 we have to use a combination of POST_INC and REG addressing...  */
7684      if (! arith_reg_operand (operands[1], SFmode))
7685	{
7686	  XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
7687	  insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
7688	  add_reg_note (insn, REG_INC, XEXP (addr, 0));
7689	  
7690	  emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7691
7692	  /* If we have modified the stack pointer, the value that we have
7693	     read with post-increment might be modified by an interrupt,
7694	     so write it back.  */
7695	  if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
7696	    emit_insn (gen_push_e (reg0));
7697	  else
7698	    emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0),
7699				   GEN_INT (-4)));
7700	  break;
7701	}
7702      /* Fall through.  */
7703
7704    case PLUS:
7705      emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7706      operands[1] = copy_rtx (operands[1]);
7707      XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
7708      emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7709      break;
7710
7711    case POST_INC:
7712      insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7713      add_reg_note (insn, REG_INC, XEXP (addr, 0));
7714
7715      insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7716      add_reg_note (insn, REG_INC, XEXP (addr, 0));
7717      break;
7718
7719    default:
7720      debug_rtx (addr);
7721      gcc_unreachable ();
7722    }
7723
7724  DONE;
7725})
7726
7727(define_split
7728  [(set (match_operand:DF 0 "memory_operand" "")
7729	(match_operand:DF 1 "register_operand" ""))
7730   (use (match_operand:PSI 2 "fpscr_operand" ""))
7731   (clobber (match_scratch:SI 3 ""))]
7732  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7733   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7734  [(const_int 0)]
7735{
7736  int regno = true_regnum (operands[1]);
7737  rtx insn, addr;
7738  rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
7739  rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
7740
7741  operands[0] = copy_rtx (operands[0]);
7742  PUT_MODE (operands[0], SFmode);
7743  addr = XEXP (operands[0], 0);
7744
7745  switch (GET_CODE (addr))
7746    {
7747    case REG:
7748      /* This is complicated.  If the register is an arithmetic register
7749	 we can just fall through to the REG+DISP case below.  Otherwise
7750	 we have to use a combination of REG and PRE_DEC addressing...  */
7751      if (! arith_reg_operand (operands[0], SFmode))
7752	{
7753	  emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
7754	  emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7755
7756	  operands[0] = copy_rtx (operands[0]);
7757	  XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
7758	  
7759	  insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7760	  add_reg_note (insn, REG_INC, XEXP (addr, 0));
7761	  break;
7762	}
7763      /* Fall through.  */
7764
7765    case PLUS:
7766      /* Since REG+DISP addressing has already been decided upon by gcc
7767	 we can rely upon it having chosen an arithmetic register as the
7768	 register component of the address.  Just emit the lower numbered
7769	 register first, to the lower address, then the higher numbered
7770	 register to the higher address.  */
7771      emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7772
7773      operands[0] = copy_rtx (operands[0]);
7774      XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
7775
7776      emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7777      break;
7778
7779    case PRE_DEC:
7780      /* This is easy.  Output the word to go to the higher address
7781         first (ie the word in the higher numbered register) then the
7782	 word to go to the lower address.  */
7783
7784      insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7785      add_reg_note (insn, REG_INC, XEXP (addr, 0));
7786
7787      insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7788      add_reg_note (insn, REG_INC, XEXP (addr, 0));
7789      break;
7790
7791    default:
7792      /* FAIL; */
7793      debug_rtx (addr);
7794      gcc_unreachable ();
7795    }
7796
7797  DONE;
7798})
7799
7800;; If the output is a register and the input is memory or a register, we have
7801;; to be careful and see which word needs to be loaded first.
7802(define_split
7803  [(set (match_operand:DF 0 "general_movdst_operand" "")
7804	(match_operand:DF 1 "general_movsrc_operand" ""))]
7805  "TARGET_SH1 && reload_completed"
7806  [(set (match_dup 2) (match_dup 3))
7807   (set (match_dup 4) (match_dup 5))]
7808{
7809  int regno;
7810
7811  if ((MEM_P (operands[0])
7812       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7813      || (MEM_P (operands[1])
7814	  && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7815    FAIL;
7816
7817  switch (GET_CODE (operands[0]))
7818    {
7819    case REG:
7820      regno = REGNO (operands[0]);
7821      break;
7822    case SUBREG:
7823      regno = subreg_regno (operands[0]);
7824      break;
7825    case MEM:
7826      regno = -1;
7827      break;
7828    default:
7829      gcc_unreachable ();
7830    }
7831
7832  if (regno == -1
7833      || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7834    {
7835      operands[2] = operand_subword (operands[0], 0, 0, DFmode);
7836      operands[3] = operand_subword (operands[1], 0, 0, DFmode);
7837      operands[4] = operand_subword (operands[0], 1, 0, DFmode);
7838      operands[5] = operand_subword (operands[1], 1, 0, DFmode);
7839    }
7840  else
7841    {
7842      operands[2] = operand_subword (operands[0], 1, 0, DFmode);
7843      operands[3] = operand_subword (operands[1], 1, 0, DFmode);
7844      operands[4] = operand_subword (operands[0], 0, 0, DFmode);
7845      operands[5] = operand_subword (operands[1], 0, 0, DFmode);
7846    }
7847
7848  if (operands[2] == 0 || operands[3] == 0
7849      || operands[4] == 0 || operands[5] == 0)
7850    FAIL;
7851})
7852
7853(define_expand "movdf"
7854  [(set (match_operand:DF 0 "general_movdst_operand" "")
7855	(match_operand:DF 1 "general_movsrc_operand" ""))]
7856  ""
7857{
7858  prepare_move_operands (operands, DFmode);
7859  if (TARGET_SHMEDIA)
7860    {
7861      if (TARGET_SHMEDIA_FPU)
7862	emit_insn (gen_movdf_media (operands[0], operands[1]));
7863      else
7864	emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
7865      DONE;
7866    }
7867  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
7868    {
7869      emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
7870      DONE;
7871    }
7872})
7873
7874;;This is incompatible with the way gcc uses subregs.
7875;;(define_insn "movv2sf_i"
7876;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
7877;;	(match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
7878;;  "TARGET_SHMEDIA_FPU
7879;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
7880;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
7881;;  "@
7882;;	#
7883;;	fld%M1.p	%m1, %0
7884;;	fst%M0.p	%m0, %1"
7885;;  [(set_attr "type" "*,fload_media,fstore_media")])
7886(define_insn_and_split "movv2sf_i"
7887  [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
7888	(match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
7889  "TARGET_SHMEDIA_FPU"
7890  "#"
7891  "TARGET_SHMEDIA_FPU && reload_completed"
7892  [(set (match_dup 0) (match_dup 1))]
7893{
7894  operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
7895  operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
7896})
7897
7898(define_expand "movv2sf"
7899  [(set (match_operand:V2SF 0 "general_movdst_operand" "")
7900	(match_operand:V2SF 1 "nonimmediate_operand" ""))]
7901  "TARGET_SHMEDIA_FPU"
7902{
7903  prepare_move_operands (operands, V2SFmode);
7904})
7905
7906(define_expand "addv2sf3"
7907  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7908   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7909   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7910  "TARGET_SHMEDIA_FPU"
7911{
7912  sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
7913  DONE;
7914})
7915
7916(define_expand "subv2sf3"
7917  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7918   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7919   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7920  "TARGET_SHMEDIA_FPU"
7921{
7922  sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
7923  DONE;
7924})
7925
7926(define_expand "mulv2sf3"
7927  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7928   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7929   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7930  "TARGET_SHMEDIA_FPU"
7931{
7932  sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
7933  DONE;
7934})
7935
7936(define_expand "divv2sf3"
7937  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7938   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7939   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7940  "TARGET_SHMEDIA_FPU"
7941{
7942  sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
7943  DONE;
7944})
7945
7946(define_insn_and_split "*movv4sf_i"
7947  [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
7948	(match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
7949  "TARGET_SHMEDIA_FPU"
7950  "#"
7951  "&& reload_completed"
7952  [(const_int 0)]
7953{
7954  for (int i = 0; i < 4/2; i++)
7955    {
7956      rtx x, y;
7957
7958      if (MEM_P (operands[0]))
7959	x = adjust_address (operands[0], V2SFmode,
7960			    i * GET_MODE_SIZE (V2SFmode));
7961      else
7962	x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
7963
7964      if (MEM_P (operands[1]))
7965	y = adjust_address (operands[1], V2SFmode,
7966			    i * GET_MODE_SIZE (V2SFmode));
7967      else
7968	y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
7969
7970      emit_insn (gen_movv2sf_i (x, y));
7971    }
7972
7973  DONE;
7974}
7975  [(set_attr "length" "8")])
7976
7977(define_expand "movv4sf"
7978  [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
7979	(match_operand:V4SF 1 "general_operand" ""))]
7980  "TARGET_SHMEDIA_FPU"
7981{
7982  prepare_move_operands (operands, V4SFmode);
7983})
7984
7985(define_insn_and_split "*movv16sf_i"
7986  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
7987	(match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
7988  "TARGET_SHMEDIA_FPU"
7989  "#"
7990  "&& reload_completed"
7991  [(const_int 0)]
7992{
7993  for (int i = 0; i < 16/2; i++)
7994    {
7995      rtx x, y;
7996
7997      if (MEM_P (operands[0]))
7998	x = adjust_address (operands[0], V2SFmode,
7999			    i * GET_MODE_SIZE (V2SFmode));
8000      else
8001	{
8002	  x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
8003	  alter_subreg (&x, true);
8004	}
8005
8006      if (MEM_P (operands[1]))
8007	y = adjust_address (operands[1], V2SFmode,
8008			    i * GET_MODE_SIZE (V2SFmode));
8009      else
8010	{
8011	  y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
8012	  alter_subreg (&y, true);
8013	}
8014
8015      emit_insn (gen_movv2sf_i (x, y));
8016    }
8017
8018  DONE;
8019}
8020  [(set_attr "length" "32")])
8021
8022(define_expand "movv16sf"
8023  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8024	(match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8025  "TARGET_SHMEDIA_FPU"
8026{
8027  prepare_move_operands (operands, V16SFmode);
8028})
8029
8030(define_insn "movsf_media"
8031  [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8032	(match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8033  "TARGET_SHMEDIA_FPU
8034   && (register_operand (operands[0], SFmode)
8035       || sh_register_operand (operands[1], SFmode))"
8036  "@
8037	fmov.s	%1, %0
8038	fmov.ls	%N1, %0
8039	fmov.sl	%1, %0
8040	add.l	%1, r63, %0
8041	#
8042	fld%M1.s	%m1, %0
8043	fst%M0.s	%m0, %1
8044	ld%M1.l	%m1, %0
8045	st%M0.l	%m0, %N1"
8046  [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8047   (set (attr "highpart")
8048	(cond [(match_test "sh_contains_memref_p (insn)")
8049	       (const_string "user")]
8050	      (const_string "ignore")))])
8051
8052(define_insn "movsf_media_nofpu"
8053  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
8054	(match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8055  "TARGET_SHMEDIA
8056   && (register_operand (operands[0], SFmode)
8057       || sh_register_operand (operands[1], SFmode))"
8058  "@
8059	add.l	%1, r63, %0
8060	#
8061	ld%M1.l	%m1, %0
8062	st%M0.l	%m0, %N1"
8063  [(set_attr "type" "arith_media,*,load_media,store_media")
8064   (set (attr "highpart")
8065	(cond [(match_test "sh_contains_memref_p (insn)")
8066	       (const_string "user")]
8067	      (const_string "ignore")))])
8068
8069(define_split
8070  [(set (match_operand:SF 0 "arith_reg_dest" "")
8071	(match_operand:SF 1 "immediate_operand" ""))]
8072  "TARGET_SHMEDIA && reload_completed
8073   && ! FP_REGISTER_P (true_regnum (operands[0]))"
8074  [(set (match_dup 3) (match_dup 2))]
8075{
8076  long values;
8077  REAL_VALUE_TYPE value;
8078
8079  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
8080  REAL_VALUE_TO_TARGET_SINGLE (value, values);
8081  operands[2] = GEN_INT (values);
8082
8083  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8084})
8085
8086(define_insn "movsf_i"
8087  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
8088	(match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
8089  "TARGET_SH1
8090   && (! TARGET_SH2E
8091       /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
8092       || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8093       || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8094   && (arith_reg_operand (operands[0], SFmode)
8095       || arith_reg_operand (operands[1], SFmode))"
8096  "@
8097	mov	%1,%0
8098	mov	#0,%0
8099	mov.l	%1,%0
8100	mov.l	%1,%0
8101	mov.l	%1,%0
8102	lds	%1,%0
8103	sts	%1,%0"
8104  [(set_attr "type" "move,move,pcload,load,store,move,move")])
8105
8106;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8107;; update_flow_info would not know where to put REG_EQUAL notes
8108;; when the destination changes mode.
8109(define_insn "movsf_ie"
8110  [(set (match_operand:SF 0 "general_movdst_operand"
8111	 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8112	(match_operand:SF 1 "general_movsrc_operand"
8113	  "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8114   (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"))
8115   (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
8116  "TARGET_SH2E
8117   && (arith_reg_operand (operands[0], SFmode)
8118       || arith_reg_operand (operands[1], SFmode)
8119       || arith_reg_operand (operands[3], SImode)
8120       || (fpul_operand (operands[0], SFmode)
8121	   && memory_operand (operands[1], SFmode)
8122	   && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
8123       || (fpul_operand (operands[1], SFmode)
8124	   && memory_operand (operands[0], SFmode)
8125	   && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
8126  "@
8127	fmov	%1,%0
8128	mov	%1,%0
8129	fldi0	%0
8130	fldi1	%0
8131	#
8132	fmov.s	%1,%0
8133	fmov.s	%1,%0
8134	mov.l	%1,%0
8135	mov.l	%1,%0
8136	mov.l	%1,%0
8137	fsts	fpul,%0
8138	flds	%1,fpul
8139	lds.l	%1,%0
8140	#
8141	sts	%1,%0
8142	lds	%1,%0
8143	sts.l	%1,%0
8144	lds.l	%1,%0
8145	! move optimized away"
8146  [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8147		     store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8148   (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8149   (set_attr_alternative "length"
8150     [(const_int 2)
8151      (const_int 2)
8152      (const_int 2)
8153      (const_int 2)
8154      (const_int 4)
8155      (if_then_else
8156	(match_test "TARGET_SH2A")
8157	(const_int 4) (const_int 2))
8158      (if_then_else
8159	(match_test "TARGET_SH2A")
8160	(const_int 4) (const_int 2))
8161      (const_int 2)
8162      (if_then_else
8163	(match_test "TARGET_SH2A")
8164	(const_int 4) (const_int 2))
8165      (if_then_else
8166	(match_test "TARGET_SH2A")
8167	(const_int 4) (const_int 2))
8168      (const_int 2)
8169      (const_int 2)
8170      (const_int 2)
8171      (const_int 4)
8172      (const_int 2)
8173      (const_int 2)
8174      (const_int 2)
8175      (const_int 2)
8176      (const_int 0)])
8177   (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8178					   (const_string "single")
8179					   (const_string "single")))])
8180
8181(define_split
8182  [(set (match_operand:SF 0 "register_operand" "")
8183	(match_operand:SF 1 "register_operand" ""))
8184   (use (match_operand:PSI 2 "fpscr_operand" ""))
8185   (clobber (reg:SI FPUL_REG))]
8186  "TARGET_SH1"
8187  [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
8188	      (use (match_dup 2))
8189	      (clobber (scratch:SI))])
8190   (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
8191	      (use (match_dup 2))
8192	      (clobber (scratch:SI))])]
8193  "")
8194
8195(define_expand "movsf"
8196  [(set (match_operand:SF 0 "general_movdst_operand" "")
8197        (match_operand:SF 1 "general_movsrc_operand" ""))]
8198  ""
8199{
8200  prepare_move_operands (operands, SFmode);
8201  if (TARGET_SHMEDIA)
8202    {
8203      if (TARGET_SHMEDIA_FPU)
8204	emit_insn (gen_movsf_media (operands[0], operands[1]));
8205      else
8206	emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8207      DONE;
8208    }
8209  if (TARGET_SH2E)
8210    {
8211      emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
8212      DONE;
8213    }
8214})
8215
8216(define_insn "mov_nop"
8217  [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
8218  "TARGET_SH2E"
8219  ""
8220  [(set_attr "length" "0")
8221   (set_attr "type" "nil")])
8222
8223(define_expand "reload_insf__frn"
8224  [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
8225		   (match_operand:SF 1 "immediate_operand" "FQ"))
8226	      (use (reg:PSI FPSCR_REG))
8227	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8228  "TARGET_SH1"
8229  "")
8230
8231(define_expand "reload_insi__i_fpul"
8232  [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
8233		   (match_operand:SI 1 "immediate_operand" "i"))
8234	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8235  "TARGET_SH1"
8236  "")
8237
8238(define_expand "ptabs"
8239  [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
8240  "TARGET_SHMEDIA"
8241{
8242  if (!TARGET_PT_FIXED)
8243    {
8244      rtx eq = operands[1];
8245
8246      /* ??? For canonical RTL we really should remove any CONST from EQ
8247	 before wrapping it in the AND, and finally wrap the EQ into a
8248	 const if is constant.  However, for reload we must expose the
8249	 input register or symbolic constant, and we can't have
8250	 different insn structures outside of the operands for different
8251	 alternatives of the same pattern.  */
8252      eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
8253		       GEN_INT (3));
8254      operands[1]
8255	= (gen_rtx_IF_THEN_ELSE
8256	    (PDImode,
8257	     eq,
8258	     gen_rtx_MEM (PDImode, operands[1]),
8259	     gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
8260			    PDImode, operands[1])));
8261    }
8262})
8263
8264;; expanded by ptabs expander.
8265(define_insn "*extendsipdi_media"
8266  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8267	(if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
8268							  "r,Csy")
8269				      (const_int 3))
8270			      (const_int 3))
8271			  (mem:PDI (match_dup 1))
8272			  (sign_extend:PDI (match_dup 1))))]
8273  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8274  "@
8275	ptabs	%1, %0
8276	pt	%1, %0"
8277  [(set_attr "type"   "ptabs_media,pt_media")
8278   (set_attr "length" "4,*")])
8279
8280(define_insn "*truncdipdi_media"
8281  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8282	(if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
8283							  "r,Csy")
8284				      (const_int 3))
8285			      (const_int 3))
8286			  (mem:PDI (match_dup 1))
8287			  (truncate:PDI (match_dup 1))))]
8288  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8289  "@
8290	ptabs	%1, %0
8291	pt	%1, %0"
8292  [(set_attr "type"   "ptabs_media,pt_media")
8293   (set_attr "length" "4,*")])
8294
8295(define_insn "*movsi_y"
8296  [(set (match_operand:SI 0 "register_operand" "=y,y")
8297	(match_operand:SI 1 "immediate_operand" "Qi,I08"))
8298   (clobber (match_scratch:SI 2 "=&z,r"))]
8299  "TARGET_SH2E
8300   && (reload_in_progress || reload_completed)"
8301  "#"
8302  [(set_attr "length" "4")
8303   (set_attr "type" "pcload,move")])
8304
8305(define_split
8306  [(set (match_operand:SI 0 "register_operand" "")
8307	(match_operand:SI 1 "immediate_operand" ""))
8308   (clobber (match_operand:SI 2 "register_operand" ""))]
8309  "TARGET_SH1"
8310  [(set (match_dup 2) (match_dup 1))
8311   (set (match_dup 0) (match_dup 2))]
8312  "")
8313
8314;; ------------------------------------------------------------------------
8315;; Define the real conditional branch instructions.
8316;; ------------------------------------------------------------------------
8317
8318(define_expand "branch_true"
8319  [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
8320			   (label_ref (match_operand 0))
8321			   (pc)))]
8322  "TARGET_SH1")
8323
8324(define_expand "branch_false"
8325  [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8326			   (label_ref (match_operand 0))
8327			   (pc)))]
8328  "TARGET_SH1")
8329
8330(define_insn_and_split "*cbranch_t"
8331  [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
8332			   (label_ref (match_operand 0))
8333			   (pc)))]
8334  "TARGET_SH1"
8335{
8336  return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
8337}
8338  "&& 1"
8339  [(set (pc) (if_then_else (eq (reg:SI T_REG) (match_dup 2))
8340			   (label_ref (match_dup 0))
8341			   (pc)))]
8342{
8343  /* Try to find missed test and branch combine opportunities which result
8344     in redundant T bit tests before conditional branches.
8345     This is done not only after combine (and before reload) but in every
8346     split pass, because some opportunities are formed also after combine.
8347     FIXME: Probably this would not be needed if CCmode was used
8348     together with TARGET_FIXED_CONDITION_CODE_REGS.  */
8349
8350  const int treg_value = sh_eval_treg_value (operands[1]);
8351  operands[2] = NULL_RTX;
8352
8353  /* Scan the insns backwards for an insn that sets the T bit by testing a
8354     reg against zero like:
8355	(set (reg T_REG) (eq (reg) (const_int 0)))  */
8356  rtx testing_insn = NULL_RTX;
8357  rtx tested_reg = NULL_RTX;
8358
8359  set_of_reg s0 = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn,
8360				      prev_nonnote_insn_bb);
8361  if (s0.set_src != NULL_RTX
8362      && GET_CODE (s0.set_src) == EQ
8363      && REG_P (XEXP (s0.set_src, 0))
8364      && satisfies_constraint_Z (XEXP (s0.set_src, 1)))
8365    {
8366      testing_insn = s0.insn;
8367      tested_reg = XEXP (s0.set_src, 0);
8368    }
8369  else
8370    FAIL;
8371
8372  /* Continue scanning the insns backwards and try to find the insn that
8373     sets the tested reg which we found above.  If the reg is set by storing
8374     the T bit or the negated T bit we can eliminate the test insn before
8375     the branch.  Notice that the branch condition has to be inverted if the
8376     test is eliminated.  */
8377
8378  /* If the T bit is used between the testing insn and the brach insn
8379     leave it alone.  */
8380  if (reg_used_between_p (get_t_reg_rtx (), testing_insn, curr_insn))
8381    FAIL;
8382
8383  while (true)
8384    {
8385      set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn,
8386					  prev_nonnote_insn);
8387
8388      if (s1.set_src == NULL_RTX)
8389	break;
8390
8391      if (t_reg_operand (s1.set_src, VOIDmode))
8392	operands[2] = GEN_INT (treg_value ^ 1);
8393      else if (negt_reg_operand (s1.set_src, VOIDmode))
8394	operands[2] = GEN_INT (treg_value);
8395      else if (REG_P (s1.set_src))
8396	{
8397	   /* If it's a reg-reg copy follow the copied reg.  This can
8398	      happen e.g. when T bit store zero-extensions are
8399	      eliminated.  */
8400	  tested_reg = s1.set_src;
8401	  s0.insn = s1.insn;
8402	  continue;
8403	}
8404
8405      /* It's only safe to remove the testing insn if the T bit is not
8406	 modified between the testing insn and the insn that stores the
8407	 T bit.  Notice that some T bit stores such as negc also modify
8408	 the T bit.  */
8409      if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn)
8410	  || modified_in_p (get_t_reg_rtx (), s1.insn)
8411	  || !no_labels_between_p (s1.insn, testing_insn))
8412	operands[2] = NULL_RTX;
8413      else
8414	{
8415	  /* If the insn that sets the tested reg has a REG_DEAD note on
8416	     the T bit remove that note since we're extending the usage
8417	     of the T bit.  */
8418	  rtx n = find_regno_note (s1.insn, REG_DEAD, T_REG);
8419	  if (n != NULL_RTX)
8420	    remove_note (s1.insn, n);
8421	}
8422
8423      break;
8424    }
8425
8426  if (operands[2] == NULL_RTX)
8427    FAIL;
8428
8429  set_insn_deleted (testing_insn);
8430}
8431  [(set_attr "type" "cbranch")])
8432
8433;; Patterns to prevent reorg from re-combining a condbranch with a branch
8434;; which destination is too far away.
8435;; The const_int_operand is distinct for each branch target; it avoids
8436;; unwanted matches with redundant_insn.
8437(define_insn "block_branch_redirect"
8438  [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
8439  "TARGET_SH1"
8440  ""
8441  [(set_attr "length" "0")])
8442
8443;; This one has the additional purpose to record a possible scratch register
8444;; for the following branch.
8445;; ??? Unfortunately, just setting the scratch register is not good enough,
8446;; because the insn then might be deemed dead and deleted.  And we can't
8447;; make the use in the jump insn explicit because that would disable
8448;; delay slot scheduling from the target.
8449(define_insn "indirect_jump_scratch"
8450  [(set (match_operand:SI 0 "register_operand" "=r")
8451	(unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
8452   (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
8453  "TARGET_SH1"
8454  ""
8455  [(set_attr "length" "0")])
8456
8457;; This one is used to preemt an insn from beyond the bra / braf / jmp
8458;; being pulled into the delay slot of a condbranch that has been made to
8459;; jump around the unconditional jump because it was out of range.
8460(define_insn "stuff_delay_slot"
8461  [(set (pc)
8462	(unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
8463		 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
8464  "TARGET_SH1"
8465  ""
8466  [(set_attr "length" "0")
8467   (set_attr "cond_delay_slot" "yes")])
8468
8469;; Conditional branch insns
8470
8471(define_expand "cbranchint4_media"
8472  [(set (pc)
8473	(if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
8474		       [(match_operand 1 "" "")
8475			(match_operand 2 "" "")])
8476		      (match_operand 3 "" "")
8477		      (pc)))]
8478  "TARGET_SHMEDIA"
8479{
8480  enum machine_mode mode = GET_MODE (operands[1]);
8481  if (mode == VOIDmode)
8482    mode = GET_MODE (operands[2]);
8483  if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
8484    {
8485      operands[1] = force_reg (mode, operands[1]);
8486      if (CONSTANT_P (operands[2])
8487          && (! satisfies_constraint_I06 (operands[2])))
8488        operands[2] = force_reg (mode, operands[2]);
8489    }
8490  else
8491    {
8492      if (operands[1] != const0_rtx)
8493        operands[1] = force_reg (mode, operands[1]);
8494      if (operands[2] != const0_rtx)
8495        operands[2] = force_reg (mode, operands[2]);
8496    }
8497  switch (GET_CODE (operands[0]))
8498    {
8499    case LEU:
8500    case LE:
8501    case LTU:
8502    case LT:
8503      operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
8504				    VOIDmode, operands[2], operands[1]);
8505      operands[1] = XEXP (operands[0], 0);
8506      operands[2] = XEXP (operands[0], 1);
8507      break;
8508    default:
8509      operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
8510				    VOIDmode, operands[1], operands[2]);
8511      break;
8512    }
8513  operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8514})
8515
8516(define_expand "cbranchfp4_media"
8517  [(set (pc)
8518	(if_then_else (match_operator 0 "sh_float_comparison_operator"
8519		       [(match_operand 1 "" "")
8520			(match_operand 2 "" "")])
8521		      (match_operand 3 "" "")
8522		      (pc)))]
8523  "TARGET_SHMEDIA"
8524{
8525  rtx tmp = gen_reg_rtx (SImode);
8526  rtx cmp;
8527  if (GET_CODE (operands[0]) == NE)
8528    cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
8529  else
8530    cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
8531			  operands[1], operands[2]);
8532
8533  emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
8534
8535  if (GET_CODE (cmp) == GET_CODE (operands[0]))
8536    operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
8537  else
8538    operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
8539  operands[1] = tmp;
8540  operands[2] = const0_rtx;
8541  operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8542})
8543
8544(define_insn "*beq_media_i"
8545  [(set (pc)
8546	(if_then_else (match_operator 3 "equality_comparison_operator"
8547			[(match_operand:DI 1 "arith_reg_operand" "r,r")
8548			 (match_operand:DI 2 "arith_operand" "r,I06")])
8549		      (match_operand 0 "target_operand" "b,b")
8550		      (pc)))]
8551  "TARGET_SHMEDIA"
8552  "@
8553	b%o3%'	%1, %2, %0%>
8554	b%o3i%'	%1, %2, %0%>"
8555  [(set_attr "type" "cbranch_media")])
8556
8557(define_insn "*beq_media_i32"
8558  [(set (pc)
8559	(if_then_else (match_operator 3 "equality_comparison_operator"
8560			[(match_operand:SI 1 "arith_reg_operand" "r,r")
8561			 (match_operand:SI 2 "arith_operand" "r,I06")])
8562		      (match_operand 0 "target_operand" "b,b")
8563		      (pc)))]
8564  "TARGET_SHMEDIA"
8565  "@
8566	b%o3%'	%1, %2, %0%>
8567	b%o3i%'	%1, %2, %0%>"
8568  [(set_attr "type" "cbranch_media")])
8569
8570(define_insn "*bgt_media_i"
8571  [(set (pc)
8572	(if_then_else (match_operator 3 "greater_comparison_operator"
8573			[(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8574			 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8575		      (match_operand 0 "target_operand" "b")
8576		      (pc)))]
8577  "TARGET_SHMEDIA"
8578  "b%o3%'	%N1, %N2, %0%>"
8579  [(set_attr "type" "cbranch_media")])
8580
8581(define_insn "*bgt_media_i32"
8582  [(set (pc)
8583	(if_then_else (match_operator 3 "greater_comparison_operator"
8584			[(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8585			 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8586		      (match_operand 0 "target_operand" "b")
8587		      (pc)))]
8588  "TARGET_SHMEDIA"
8589  "b%o3%'	%N1, %N2, %0%>"
8590  [(set_attr "type" "cbranch_media")])
8591
8592;; These are only needed to make invert_jump() happy - otherwise, jump
8593;; optimization will be silently disabled.
8594(define_insn "*blt_media_i"
8595  [(set (pc)
8596	(if_then_else (match_operator 3 "less_comparison_operator"
8597			[(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8598			 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8599		      (match_operand 0 "target_operand" "b")
8600		      (pc)))]
8601  "TARGET_SHMEDIA"
8602  "b%o3%'	%N2, %N1, %0%>"
8603  [(set_attr "type" "cbranch_media")])
8604
8605(define_insn "*blt_media_i32"
8606  [(set (pc)
8607	(if_then_else (match_operator 3 "less_comparison_operator"
8608			[(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8609			 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8610		      (match_operand 0 "target_operand" "b")
8611		      (pc)))]
8612  "TARGET_SHMEDIA"
8613  "b%o3%'	%N2, %N1, %0%>"
8614  [(set_attr "type" "cbranch_media")])
8615
8616;; combiner splitter for test-and-branch on single bit in register.  This
8617;; is endian dependent because the non-paradoxical subreg looks different
8618;; on big endian.
8619(define_split
8620  [(set (pc)
8621	(if_then_else
8622	  (match_operator 3 "equality_comparison_operator"
8623	    [(subreg:SI
8624	       (zero_extract:DI
8625		 (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0)
8626		 (const_int 1)
8627		 (match_operand 2 "const_int_operand" "")) 0)
8628	     (const_int 0)])
8629	  (match_operand 0 "target_operand" "")
8630	  (pc)))
8631   (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
8632  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
8633  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
8634   (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
8635{
8636  operands[5] = GEN_INT (31 - INTVAL (operands[2]));
8637  operands[6] = (GET_CODE (operands[3]) == EQ
8638		 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
8639		 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
8640})
8641
8642; operand 0 is the loop count pseudo register
8643; operand 1 is the number of loop iterations or 0 if it is unknown
8644; operand 2 is the maximum number of loop iterations
8645; operand 3 is the number of levels of enclosed loops
8646; operand 4 is the label to jump to at the top of the loop
8647(define_expand "doloop_end"
8648  [(parallel [(set (pc)
8649		   (if_then_else (ne:SI (match_operand:SI 0 "" "")
8650				        (const_int 1))
8651				 (label_ref (match_operand 4 "" ""))
8652				 (pc)))
8653	      (set (match_dup 0)
8654		   (plus:SI (match_dup 0) (const_int -1)))
8655	      (clobber (reg:SI T_REG))])
8656   (match_operand 5 "" "")]
8657  "TARGET_SH2"
8658{
8659  if (GET_MODE (operands[0]) != SImode)
8660    FAIL;
8661  emit_jump_insn (gen_doloop_end_split (operands[0], operands[4], operands[0]));
8662  DONE;
8663})
8664
8665(define_insn_and_split "doloop_end_split"
8666  [(set (pc)
8667	(if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
8668			     (const_int 1))
8669		      (label_ref (match_operand 1 "" ""))
8670		      (pc)))
8671   (set (match_operand:SI 0 "arith_reg_dest" "=r")
8672	(plus (match_dup 2) (const_int -1)))
8673   (clobber (reg:SI T_REG))]
8674  "TARGET_SH2"
8675  "#"
8676  ""
8677  [(parallel [(set (reg:SI T_REG)
8678		   (eq:SI (match_dup 2) (const_int 1)))
8679	      (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
8680   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8681			   (label_ref (match_dup 1))
8682			   (pc)))]
8683  ""
8684  [(set_attr "type" "cbranch")])
8685
8686;; ------------------------------------------------------------------------
8687;; Jump and linkage insns
8688;; ------------------------------------------------------------------------
8689
8690(define_insn "jump_compact"
8691  [(set (pc)
8692	(label_ref (match_operand 0 "" "")))]
8693  "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
8694{
8695  /* The length is 16 if the delay slot is unfilled.  */
8696  if (get_attr_length(insn) > 4)
8697    return output_far_jump(insn, operands[0]);
8698  else
8699    return "bra	%l0%#";
8700}
8701  [(set_attr "type" "jump")
8702   (set_attr "needs_delay_slot" "yes")])
8703
8704;; ??? It would be much saner to explicitly use the scratch register
8705;; in the jump insn, and have indirect_jump_scratch only set it,
8706;; but fill_simple_delay_slots would refuse to do delay slot filling
8707;; from the target then, as it uses simplejump_p.
8708;;(define_insn "jump_compact_far"
8709;;  [(set (pc)
8710;;	(label_ref (match_operand 0 "" "")))
8711;;   (use (match_operand 1 "register_operand" "r")]
8712;;  "TARGET_SH1"
8713;;  "* return output_far_jump(insn, operands[0], operands[1]);"
8714;;  [(set_attr "type" "jump")
8715;;   (set_attr "needs_delay_slot" "yes")])
8716
8717(define_insn "jump_media"
8718  [(set (pc)
8719	(match_operand 0 "target_operand" "b"))]
8720  "TARGET_SHMEDIA"
8721  "blink	%0, r63%>"
8722  [(set_attr "type" "jump_media")])
8723
8724(define_expand "jump"
8725  [(set (pc)
8726	(label_ref (match_operand 0 "" "")))]
8727  ""
8728{
8729  if (TARGET_SH1)
8730    emit_jump_insn (gen_jump_compact (operands[0]));
8731  else if (TARGET_SHMEDIA)
8732    {
8733      if (reload_in_progress || reload_completed)
8734	FAIL;
8735      emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0])));
8736    }
8737  DONE;
8738})
8739
8740(define_insn "force_mode_for_call"
8741  [(use (reg:PSI FPSCR_REG))]
8742  "TARGET_SHCOMPACT"
8743  ""
8744  [(set_attr "length" "0")
8745   (set (attr "fp_mode")
8746	(if_then_else (eq_attr "fpu_single" "yes")
8747		      (const_string "single") (const_string "double")))])
8748
8749(define_insn "calli"
8750  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8751	 (match_operand 1 "" ""))
8752   (use (reg:PSI FPSCR_REG))
8753   (clobber (reg:SI PR_REG))]
8754  "TARGET_SH1"
8755{
8756  if (TARGET_SH2A && (dbr_sequence_length () == 0))
8757    return "jsr/n	@%0";
8758  else
8759    return "jsr	@%0%#";
8760}
8761  [(set_attr "type" "call")
8762   (set (attr "fp_mode")
8763	(if_then_else (eq_attr "fpu_single" "yes")
8764		      (const_string "single") (const_string "double")))
8765   (set_attr "needs_delay_slot" "yes")
8766   (set_attr "fp_set" "unknown")])
8767
8768;; This is TBR relative jump instruction for SH2A architecture.
8769;; Its use is enabled by assigning an attribute "function_vector"
8770;; and the vector number to a function during its declaration.
8771(define_insn "calli_tbr_rel"
8772  [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
8773	 (match_operand 1 "" ""))
8774   (use (reg:PSI FPSCR_REG))
8775   (clobber (reg:SI PR_REG))]
8776  "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
8777{
8778  unsigned HOST_WIDE_INT vect_num;
8779  vect_num = sh2a_get_function_vector_number (operands[0]);
8780  operands[2] = GEN_INT (vect_num * 4);
8781
8782  return "jsr/n	@@(%O2,tbr)";
8783}
8784  [(set_attr "type" "call")
8785   (set (attr "fp_mode")
8786	(if_then_else (eq_attr "fpu_single" "yes")
8787		      (const_string "single") (const_string "double")))
8788   (set_attr "needs_delay_slot" "no")
8789   (set_attr "fp_set" "unknown")])
8790
8791;; This is a pc-rel call, using bsrf, for use with PIC.
8792(define_insn "calli_pcrel"
8793  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8794	 (match_operand 1 "" ""))
8795   (use (reg:PSI FPSCR_REG))
8796   (use (reg:SI PIC_REG))
8797   (use (match_operand 2 "" ""))
8798   (clobber (reg:SI PR_REG))]
8799  "TARGET_SH2"
8800{
8801  return       "bsrf	%0"	"\n"
8802	 "%O2:%#";
8803}
8804  [(set_attr "type" "call")
8805   (set (attr "fp_mode")
8806	(if_then_else (eq_attr "fpu_single" "yes")
8807		      (const_string "single") (const_string "double")))
8808   (set_attr "needs_delay_slot" "yes")
8809   (set_attr "fp_set" "unknown")])
8810
8811(define_insn_and_split "call_pcrel"
8812  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
8813	 (match_operand 1 "" ""))
8814   (use (reg:PSI FPSCR_REG))
8815   (use (reg:SI PIC_REG))
8816   (clobber (reg:SI PR_REG))
8817   (clobber (match_scratch:SI 2 "=r"))]
8818  "TARGET_SH2"
8819  "#"
8820  "reload_completed"
8821  [(const_int 0)]
8822{
8823  rtx lab = PATTERN (gen_call_site ());
8824
8825  if (SYMBOL_REF_LOCAL_P (operands[0]))
8826    emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
8827  else
8828    emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
8829  emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
8830  DONE;
8831}
8832  [(set_attr "type" "call")
8833   (set (attr "fp_mode")
8834	(if_then_else (eq_attr "fpu_single" "yes")
8835		      (const_string "single") (const_string "double")))
8836   (set_attr "needs_delay_slot" "yes")
8837   (set_attr "fp_set" "unknown")])
8838
8839(define_insn "call_compact"
8840  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8841	 (match_operand 1 "" ""))
8842   (match_operand 2 "immediate_operand" "n")
8843   (use (reg:SI R0_REG))
8844   (use (reg:SI R1_REG))
8845   (use (reg:PSI FPSCR_REG))
8846   (clobber (reg:SI PR_REG))]
8847  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8848  "jsr	@%0%#"
8849  [(set_attr "type" "call")
8850   (set (attr "fp_mode")
8851	(if_then_else (eq_attr "fpu_single" "yes")
8852		      (const_string "single") (const_string "double")))
8853   (set_attr "needs_delay_slot" "yes")])
8854
8855(define_insn "call_compact_rettramp"
8856  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8857	 (match_operand 1 "" ""))
8858   (match_operand 2 "immediate_operand" "n")
8859   (use (reg:SI R0_REG))
8860   (use (reg:SI R1_REG))
8861   (use (reg:PSI FPSCR_REG))
8862   (clobber (reg:SI R10_REG))
8863   (clobber (reg:SI PR_REG))]
8864  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8865  "jsr	@%0%#"
8866  [(set_attr "type" "call")
8867   (set (attr "fp_mode")
8868	(if_then_else (eq_attr "fpu_single" "yes")
8869		      (const_string "single") (const_string "double")))
8870   (set_attr "needs_delay_slot" "yes")])
8871
8872(define_insn "call_media"
8873  [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
8874	 (match_operand 1 "" ""))
8875   (clobber (reg:DI PR_MEDIA_REG))]
8876  "TARGET_SHMEDIA"
8877  "blink	%0, r18"
8878  [(set_attr "type" "jump_media")])
8879
8880(define_insn "call_valuei"
8881  [(set (match_operand 0 "" "=rf")
8882	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8883	      (match_operand 2 "" "")))
8884   (use (reg:PSI FPSCR_REG))
8885   (clobber (reg:SI PR_REG))]
8886  "TARGET_SH1"
8887{
8888  if (TARGET_SH2A && (dbr_sequence_length () == 0))
8889    return "jsr/n	@%1";
8890  else
8891    return "jsr	@%1%#";
8892}
8893  [(set_attr "type" "call")
8894   (set (attr "fp_mode")
8895	(if_then_else (eq_attr "fpu_single" "yes")
8896		      (const_string "single") (const_string "double")))
8897   (set_attr "needs_delay_slot" "yes")
8898   (set_attr "fp_set" "unknown")])
8899
8900;; This is TBR relative jump instruction for SH2A architecture.
8901;; Its use is enabled by assigning an attribute "function_vector"
8902;; and the vector number to a function during its declaration.
8903(define_insn "call_valuei_tbr_rel"
8904  [(set (match_operand 0 "" "=rf")
8905	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8906	      (match_operand 2 "" "")))
8907   (use (reg:PSI FPSCR_REG))
8908   (clobber (reg:SI PR_REG))]
8909  "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
8910{
8911  unsigned HOST_WIDE_INT vect_num;
8912  vect_num = sh2a_get_function_vector_number (operands[1]);
8913  operands[3] = GEN_INT (vect_num * 4);
8914
8915  return "jsr/n	@@(%O3,tbr)";
8916}
8917  [(set_attr "type" "call")
8918   (set (attr "fp_mode")
8919	(if_then_else (eq_attr "fpu_single" "yes")
8920		      (const_string "single") (const_string "double")))
8921   (set_attr "needs_delay_slot" "no")
8922   (set_attr "fp_set" "unknown")])
8923
8924(define_insn "call_valuei_pcrel"
8925  [(set (match_operand 0 "" "=rf")
8926	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8927	      (match_operand 2 "" "")))
8928   (use (reg:PSI FPSCR_REG))
8929   (use (reg:SI PIC_REG))
8930   (use (match_operand 3 "" ""))
8931   (clobber (reg:SI PR_REG))]
8932  "TARGET_SH2"
8933{
8934  return       "bsrf	%1"	"\n"
8935	 "%O3:%#";
8936}
8937  [(set_attr "type" "call")
8938   (set (attr "fp_mode")
8939	(if_then_else (eq_attr "fpu_single" "yes")
8940		      (const_string "single") (const_string "double")))
8941   (set_attr "needs_delay_slot" "yes")
8942   (set_attr "fp_set" "unknown")])
8943
8944(define_insn_and_split "call_value_pcrel"
8945  [(set (match_operand 0 "" "=rf")
8946	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8947	      (match_operand 2 "" "")))
8948   (use (reg:PSI FPSCR_REG))
8949   (use (reg:SI PIC_REG))
8950   (clobber (reg:SI PR_REG))
8951   (clobber (match_scratch:SI 3 "=r"))]
8952  "TARGET_SH2"
8953  "#"
8954  "reload_completed"
8955  [(const_int 0)]
8956{
8957  rtx lab = PATTERN (gen_call_site ());
8958
8959  if (SYMBOL_REF_LOCAL_P (operands[1]))
8960    emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
8961  else
8962    emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
8963  emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
8964					 operands[2], copy_rtx (lab)));
8965  DONE;
8966}
8967  [(set_attr "type" "call")
8968   (set (attr "fp_mode")
8969	(if_then_else (eq_attr "fpu_single" "yes")
8970		      (const_string "single") (const_string "double")))
8971   (set_attr "needs_delay_slot" "yes")
8972   (set_attr "fp_set" "unknown")])
8973
8974(define_insn "call_value_compact"
8975  [(set (match_operand 0 "" "=rf")
8976	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8977	      (match_operand 2 "" "")))
8978   (match_operand 3 "immediate_operand" "n")
8979   (use (reg:SI R0_REG))
8980   (use (reg:SI R1_REG))
8981   (use (reg:PSI FPSCR_REG))
8982   (clobber (reg:SI PR_REG))]
8983  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8984  "jsr	@%1%#"
8985  [(set_attr "type" "call")
8986   (set (attr "fp_mode")
8987	(if_then_else (eq_attr "fpu_single" "yes")
8988		      (const_string "single") (const_string "double")))
8989   (set_attr "needs_delay_slot" "yes")])
8990
8991(define_insn "call_value_compact_rettramp"
8992  [(set (match_operand 0 "" "=rf")
8993	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8994	      (match_operand 2 "" "")))
8995   (match_operand 3 "immediate_operand" "n")
8996   (use (reg:SI R0_REG))
8997   (use (reg:SI R1_REG))
8998   (use (reg:PSI FPSCR_REG))
8999   (clobber (reg:SI R10_REG))
9000   (clobber (reg:SI PR_REG))]
9001  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9002  "jsr	@%1%#"
9003  [(set_attr "type" "call")
9004   (set (attr "fp_mode")
9005	(if_then_else (eq_attr "fpu_single" "yes")
9006		      (const_string "single") (const_string "double")))
9007   (set_attr "needs_delay_slot" "yes")])
9008
9009(define_insn "call_value_media"
9010  [(set (match_operand 0 "" "=rf")
9011	(call (mem:DI (match_operand 1 "target_reg_operand" "b"))
9012	      (match_operand 2 "" "")))
9013   (clobber (reg:DI PR_MEDIA_REG))]
9014  "TARGET_SHMEDIA"
9015  "blink	%1, r18"
9016  [(set_attr "type" "jump_media")])
9017
9018(define_expand "call"
9019  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9020			    (match_operand 1 "" ""))
9021	      (match_operand 2 "" "")
9022	      (use (reg:PSI FPSCR_REG))
9023	      (clobber (reg:SI PR_REG))])]
9024  ""
9025{
9026  if (TARGET_SHMEDIA)
9027    {
9028      operands[0] = shmedia_prepare_call_address (operands[0], 0);
9029      emit_call_insn (gen_call_media (operands[0], operands[1]));
9030      DONE;
9031    }
9032  else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9033    {
9034      rtx cookie_rtx = operands[2];
9035      long cookie = INTVAL (cookie_rtx);
9036      rtx func = XEXP (operands[0], 0);
9037      rtx r0, r1;
9038
9039      if (flag_pic)
9040	{
9041	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9042	    {
9043	      rtx reg = gen_reg_rtx (Pmode);
9044
9045	      emit_insn (gen_symGOTPLT2reg (reg, func));
9046	      func = reg;
9047	    }
9048	  else
9049	    func = legitimize_pic_address (func, Pmode, 0);
9050	}
9051
9052      r0 = gen_rtx_REG (SImode, R0_REG);
9053      r1 = gen_rtx_REG (SImode, R1_REG);
9054
9055      /* Since such a call function may use all call-clobbered
9056	 registers, we force a mode switch earlier, so that we don't
9057	 run out of registers when adjusting fpscr for the call.  */
9058      emit_insn (gen_force_mode_for_call ());
9059
9060      operands[0]
9061	= function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9062      operands[0] = force_reg (SImode, operands[0]);
9063
9064      emit_move_insn (r0, func);
9065      emit_move_insn (r1, cookie_rtx);
9066
9067      if (cookie & CALL_COOKIE_RET_TRAMP (1))
9068	emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9069						   operands[2]));
9070      else
9071	emit_call_insn (gen_call_compact (operands[0], operands[1],
9072					  operands[2]));
9073
9074      DONE;
9075    }
9076  else if (TARGET_SHCOMPACT && flag_pic
9077	   && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9078	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9079    {
9080      rtx reg = gen_reg_rtx (Pmode);
9081
9082      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9083      XEXP (operands[0], 0) = reg;
9084    }
9085  if (!flag_pic && TARGET_SH2A
9086      && MEM_P (operands[0])
9087      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9088    {
9089      if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9090	{
9091	  emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9092					     operands[1]));
9093	  DONE;
9094	}
9095    }
9096  if (flag_pic && TARGET_SH2
9097      && MEM_P (operands[0])
9098      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9099    {
9100      emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
9101      DONE;
9102    }
9103  else
9104  {
9105    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9106    operands[1] = operands[2];
9107  }
9108
9109  emit_call_insn (gen_calli (operands[0], operands[1]));
9110  DONE;
9111})
9112
9113(define_insn "call_pop_compact"
9114  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9115	 (match_operand 1 "" ""))
9116   (match_operand 2 "immediate_operand" "n")
9117   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9118				 (match_operand 3 "immediate_operand" "n")))
9119   (use (reg:SI R0_REG))
9120   (use (reg:SI R1_REG))
9121   (use (reg:PSI FPSCR_REG))
9122   (clobber (reg:SI PR_REG))]
9123  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9124  "jsr	@%0%#"
9125  [(set_attr "type" "call")
9126   (set (attr "fp_mode")
9127	(if_then_else (eq_attr "fpu_single" "yes")
9128		      (const_string "single") (const_string "double")))
9129   (set_attr "needs_delay_slot" "yes")])
9130
9131(define_insn "call_pop_compact_rettramp"
9132  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9133	 (match_operand 1 "" ""))
9134   (match_operand 2 "immediate_operand" "n")
9135   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9136				 (match_operand 3 "immediate_operand" "n")))
9137   (use (reg:SI R0_REG))
9138   (use (reg:SI R1_REG))
9139   (use (reg:PSI FPSCR_REG))
9140   (clobber (reg:SI R10_REG))
9141   (clobber (reg:SI PR_REG))]
9142  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9143  "jsr	@%0%#"
9144  [(set_attr "type" "call")
9145   (set (attr "fp_mode")
9146	(if_then_else (eq_attr "fpu_single" "yes")
9147		      (const_string "single") (const_string "double")))
9148   (set_attr "needs_delay_slot" "yes")])
9149
9150(define_expand "call_pop"
9151  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9152		    (match_operand 1 "" ""))
9153	     (match_operand 2 "" "")
9154	     (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9155					   (match_operand 3 "" "")))])]
9156  "TARGET_SHCOMPACT"
9157{
9158  rtx cookie_rtx;
9159  long cookie;
9160  rtx func;
9161  rtx r0, r1;
9162
9163  gcc_assert (operands[2] && INTVAL (operands[2]));
9164  cookie_rtx = operands[2];
9165  cookie = INTVAL (cookie_rtx);
9166  func = XEXP (operands[0], 0);
9167
9168  if (flag_pic)
9169    {
9170      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9171	{
9172	  rtx reg = gen_reg_rtx (Pmode);
9173	  emit_insn (gen_symGOTPLT2reg (reg, func));
9174	  func = reg;
9175	}
9176      else
9177	func = legitimize_pic_address (func, Pmode, 0);
9178    }
9179
9180  r0 = gen_rtx_REG (SImode, R0_REG);
9181  r1 = gen_rtx_REG (SImode, R1_REG);
9182
9183  /* Since such a call function may use all call-clobbered
9184     registers, we force a mode switch earlier, so that we don't
9185     run out of registers when adjusting fpscr for the call.  */
9186  emit_insn (gen_force_mode_for_call ());
9187
9188  operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9189				 SFUNC_GOT);
9190  operands[0] = force_reg (SImode, operands[0]);
9191
9192  emit_move_insn (r0, func);
9193  emit_move_insn (r1, cookie_rtx);
9194
9195  if (cookie & CALL_COOKIE_RET_TRAMP (1))
9196    emit_call_insn (gen_call_pop_compact_rettramp
9197	   	     (operands[0], operands[1], operands[2], operands[3]));
9198  else
9199    emit_call_insn (gen_call_pop_compact
9200	  	     (operands[0], operands[1], operands[2], operands[3]));
9201
9202  DONE;
9203})
9204
9205(define_expand "call_value"
9206  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9207		   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9208				 (match_operand 2 "" "")))
9209	      (match_operand 3 "" "")
9210	      (use (reg:PSI FPSCR_REG))
9211	      (clobber (reg:SI PR_REG))])]
9212  ""
9213{
9214  if (TARGET_SHMEDIA)
9215    {
9216      operands[1] = shmedia_prepare_call_address (operands[1], 0);
9217      emit_call_insn (gen_call_value_media (operands[0], operands[1],
9218					    operands[2]));
9219      DONE;
9220    }
9221  else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9222    {
9223      rtx cookie_rtx = operands[3];
9224      long cookie = INTVAL (cookie_rtx);
9225      rtx func = XEXP (operands[1], 0);
9226      rtx r0, r1;
9227
9228      if (flag_pic)
9229	{
9230	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9231	    {
9232	      rtx reg = gen_reg_rtx (Pmode);
9233
9234	      emit_insn (gen_symGOTPLT2reg (reg, func));
9235	      func = reg;
9236	    }
9237	  else
9238	    func = legitimize_pic_address (func, Pmode, 0);
9239	}
9240
9241      r0 = gen_rtx_REG (SImode, R0_REG);
9242      r1 = gen_rtx_REG (SImode, R1_REG);
9243
9244      /* Since such a call function may use all call-clobbered
9245	 registers, we force a mode switch earlier, so that we don't
9246	 run out of registers when adjusting fpscr for the call.  */
9247      emit_insn (gen_force_mode_for_call ());
9248
9249      operands[1]
9250	= function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9251      operands[1] = force_reg (SImode, operands[1]);
9252
9253      emit_move_insn (r0, func);
9254      emit_move_insn (r1, cookie_rtx);
9255
9256      if (cookie & CALL_COOKIE_RET_TRAMP (1))
9257	emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9258							 operands[1],
9259							 operands[2],
9260							 operands[3]));
9261      else
9262	emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9263						operands[2], operands[3]));
9264
9265      DONE;
9266    }
9267  else if (TARGET_SHCOMPACT && flag_pic
9268	   && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9269	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9270    {
9271      rtx reg = gen_reg_rtx (Pmode);
9272
9273      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9274      XEXP (operands[1], 0) = reg;
9275    }
9276  if (!flag_pic && TARGET_SH2A
9277      && MEM_P (operands[1])
9278      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9279    {
9280      if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9281	{
9282	  emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9283				 XEXP (operands[1], 0), operands[2]));
9284	  DONE;
9285	}
9286    }
9287  if (flag_pic && TARGET_SH2
9288      && MEM_P (operands[1])
9289      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9290    {
9291      emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
9292					    operands[2]));
9293      DONE;
9294    }
9295  else
9296    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9297
9298  emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
9299  DONE;
9300})
9301
9302(define_insn "sibcalli"
9303  [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
9304	 (match_operand 1 "" ""))
9305   (use (reg:PSI FPSCR_REG))
9306   (return)]
9307  "TARGET_SH1"
9308  "jmp	@%0%#"
9309  [(set_attr "needs_delay_slot" "yes")
9310   (set (attr "fp_mode")
9311	(if_then_else (eq_attr "fpu_single" "yes")
9312		      (const_string "single") (const_string "double")))
9313   (set_attr "type" "jump_ind")])
9314
9315(define_insn "sibcalli_pcrel"
9316  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
9317	 (match_operand 1 "" ""))
9318   (use (match_operand 2 "" ""))
9319   (use (reg:PSI FPSCR_REG))
9320   (return)]
9321  "TARGET_SH2"
9322{
9323  return       "braf	%0"	"\n"
9324	 "%O2:%#";
9325}
9326  [(set_attr "needs_delay_slot" "yes")
9327   (set (attr "fp_mode")
9328	(if_then_else (eq_attr "fpu_single" "yes")
9329		      (const_string "single") (const_string "double")))
9330   (set_attr "type" "jump_ind")])
9331
9332;; This uses an unspec to describe that the symbol_ref is very close.
9333(define_insn "sibcalli_thunk"
9334  [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
9335			     UNSPEC_THUNK))
9336	 (match_operand 1 "" ""))
9337   (use (reg:PSI FPSCR_REG))
9338   (return)]
9339  "TARGET_SH1"
9340  "bra	%O0"
9341  [(set_attr "needs_delay_slot" "yes")
9342   (set (attr "fp_mode")
9343	(if_then_else (eq_attr "fpu_single" "yes")
9344		      (const_string "single") (const_string "double")))
9345   (set_attr "type" "jump")
9346   (set_attr "length" "2")])
9347
9348(define_insn_and_split "sibcall_pcrel"
9349  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9350	 (match_operand 1 "" ""))
9351   (use (reg:PSI FPSCR_REG))
9352   (clobber (match_scratch:SI 2 "=k"))
9353   (return)]
9354  "TARGET_SH2"
9355  "#"
9356  "reload_completed"
9357  [(const_int 0)]
9358{
9359  rtx lab = PATTERN (gen_call_site ());
9360  rtx call_insn;
9361
9362  emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9363  call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
9364						  copy_rtx (lab)));
9365  SIBLING_CALL_P (call_insn) = 1;
9366  DONE;
9367}
9368  [(set_attr "needs_delay_slot" "yes")
9369   (set (attr "fp_mode")
9370	(if_then_else (eq_attr "fpu_single" "yes")
9371		      (const_string "single") (const_string "double")))
9372   (set_attr "type" "jump_ind")])
9373
9374(define_insn "sibcall_compact"
9375  [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
9376	 (match_operand 1 "" ""))
9377   (return)
9378   (use (match_operand:SI 2 "register_operand" "z,x"))
9379   (use (reg:SI R1_REG))
9380   (use (reg:PSI FPSCR_REG))
9381   ;; We want to make sure the `x' above will only match MACH_REG
9382   ;; because sibcall_epilogue may clobber MACL_REG.
9383   (clobber (reg:SI MACL_REG))]
9384  "TARGET_SHCOMPACT"
9385{
9386  static const char* alt[] =
9387  {
9388       "jmp	@%0%#",
9389
9390       "jmp	@%0"	"\n"
9391    "	sts	%2,r0"
9392  };
9393  return alt[which_alternative];
9394}
9395  [(set_attr "needs_delay_slot" "yes,no")
9396   (set_attr "length" "2,4")
9397   (set (attr "fp_mode") (const_string "single"))
9398   (set_attr "type" "jump_ind")])
9399
9400(define_insn "sibcall_media"
9401  [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
9402	 (match_operand 1 "" ""))
9403   (use (reg:SI PR_MEDIA_REG))
9404   (return)]
9405  "TARGET_SHMEDIA"
9406  "blink	%0, r63"
9407  [(set_attr "type" "jump_media")])
9408
9409(define_expand "sibcall"
9410  [(parallel
9411    [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9412	   (match_operand 1 "" ""))
9413     (match_operand 2 "" "")
9414     (use (reg:PSI FPSCR_REG))
9415     (return)])]
9416  ""
9417{
9418  if (TARGET_SHMEDIA)
9419    {
9420      operands[0] = shmedia_prepare_call_address (operands[0], 1);
9421      emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
9422      DONE;
9423    }
9424  else if (TARGET_SHCOMPACT && operands[2]
9425	   && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9426    {
9427      rtx cookie_rtx = operands[2];
9428      long cookie = INTVAL (cookie_rtx);
9429      rtx func = XEXP (operands[0], 0);
9430      rtx mach, r1;
9431
9432      if (flag_pic)
9433	{
9434	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9435	    {
9436	      rtx reg = gen_reg_rtx (Pmode);
9437
9438	      emit_insn (gen_symGOT2reg (reg, func));
9439	      func = reg;
9440	    }
9441	  else
9442	    func = legitimize_pic_address (func, Pmode, 0);
9443	}
9444
9445      /* FIXME: if we could tell whether all argument registers are
9446	 already taken, we could decide whether to force the use of
9447	 MACH_REG or to stick to R0_REG.  Unfortunately, there's no
9448	 simple way to tell.  We could use the CALL_COOKIE, but we
9449	 can't currently tell a register used for regular argument
9450	 passing from one that is unused.  If we leave it up to reload
9451	 to decide which register to use, it seems to always choose
9452	 R0_REG, which leaves no available registers in SIBCALL_REGS
9453	 to hold the address of the trampoline.  */
9454      mach = gen_rtx_REG (SImode, MACH_REG);
9455      r1 = gen_rtx_REG (SImode, R1_REG);
9456
9457      /* Since such a call function may use all call-clobbered
9458	 registers, we force a mode switch earlier, so that we don't
9459	 run out of registers when adjusting fpscr for the call.  */
9460      emit_insn (gen_force_mode_for_call ());
9461
9462      operands[0]
9463	= function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9464      operands[0] = force_reg (SImode, operands[0]);
9465
9466      /* We don't need a return trampoline, since the callee will
9467	 return directly to the upper caller.  */
9468      if (cookie & CALL_COOKIE_RET_TRAMP (1))
9469	{
9470	  cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9471	  cookie_rtx = GEN_INT (cookie);
9472	}
9473
9474      emit_move_insn (mach, func);
9475      emit_move_insn (r1, cookie_rtx);
9476
9477      emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
9478      DONE;
9479    }
9480  else if (TARGET_SHCOMPACT && flag_pic
9481	   && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9482	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9483    {
9484      rtx reg = gen_reg_rtx (Pmode);
9485
9486      emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
9487      XEXP (operands[0], 0) = reg;
9488    }
9489  if (flag_pic && TARGET_SH2
9490      && MEM_P (operands[0])
9491      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9492      /* The PLT needs the PIC register, but the epilogue would have
9493	 to restore it, so we can only use PC-relative PIC calls for
9494	 static functions.  */
9495      && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9496    {
9497      emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
9498      DONE;
9499    }
9500  else
9501    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9502
9503  emit_call_insn (gen_sibcalli (operands[0], operands[1]));
9504  DONE;
9505})
9506
9507(define_insn "sibcall_valuei"
9508  [(set (match_operand 0 "" "=rf")
9509	(call (mem:SI (match_operand:SI 1 "register_operand" "k"))
9510	      (match_operand 2 "" "")))
9511   (use (reg:PSI FPSCR_REG))
9512   (return)]
9513  "TARGET_SH1"
9514  "jmp	@%1%#"
9515  [(set_attr "needs_delay_slot" "yes")
9516   (set (attr "fp_mode")
9517	(if_then_else (eq_attr "fpu_single" "yes")
9518		      (const_string "single") (const_string "double")))
9519   (set_attr "type" "jump_ind")])
9520
9521(define_insn "sibcall_valuei_pcrel"
9522  [(set (match_operand 0 "" "=rf")
9523	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
9524	      (match_operand 2 "" "")))
9525   (use (match_operand 3 "" ""))
9526   (use (reg:PSI FPSCR_REG))
9527   (return)]
9528  "TARGET_SH2"
9529{
9530  return       "braf	%1"	"\n"
9531	 "%O3:%#";
9532}
9533  [(set_attr "needs_delay_slot" "yes")
9534   (set (attr "fp_mode")
9535	(if_then_else (eq_attr "fpu_single" "yes")
9536		      (const_string "single") (const_string "double")))
9537   (set_attr "type" "jump_ind")])
9538
9539(define_insn_and_split "sibcall_value_pcrel"
9540  [(set (match_operand 0 "" "=rf")
9541	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9542	      (match_operand 2 "" "")))
9543   (use (reg:PSI FPSCR_REG))
9544   (clobber (match_scratch:SI 3 "=k"))
9545   (return)]
9546  "TARGET_SH2"
9547  "#"
9548  "reload_completed"
9549  [(const_int 0)]
9550{
9551  rtx lab = PATTERN (gen_call_site ());
9552  rtx call_insn;
9553
9554  emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9555  call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
9556							operands[3],
9557							operands[2],
9558							copy_rtx (lab)));
9559  SIBLING_CALL_P (call_insn) = 1;
9560  DONE;
9561}
9562  [(set_attr "needs_delay_slot" "yes")
9563   (set (attr "fp_mode")
9564	(if_then_else (eq_attr "fpu_single" "yes")
9565		      (const_string "single") (const_string "double")))
9566   (set_attr "type" "jump_ind")])
9567
9568(define_insn "sibcall_value_compact"
9569  [(set (match_operand 0 "" "=rf,rf")
9570	(call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
9571	      (match_operand 2 "" "")))
9572   (return)
9573   (use (match_operand:SI 3 "register_operand" "z,x"))
9574   (use (reg:SI R1_REG))
9575   (use (reg:PSI FPSCR_REG))
9576   ;; We want to make sure the `x' above will only match MACH_REG
9577   ;; because sibcall_epilogue may clobber MACL_REG.
9578   (clobber (reg:SI MACL_REG))]
9579  "TARGET_SHCOMPACT"
9580{
9581  static const char* alt[] =
9582  {
9583       "jmp	@%1%#",
9584
9585       "jmp	@%1"	"\n"
9586    "	sts	%3,r0"
9587  };
9588  return alt[which_alternative];
9589}
9590  [(set_attr "needs_delay_slot" "yes,no")
9591   (set_attr "length" "2,4")
9592   (set (attr "fp_mode") (const_string "single"))
9593   (set_attr "type" "jump_ind")])
9594
9595(define_insn "sibcall_value_media"
9596  [(set (match_operand 0 "" "=rf")
9597	(call (mem:DI (match_operand 1 "target_reg_operand" "k"))
9598	      (match_operand 2 "" "")))
9599   (use (reg:SI PR_MEDIA_REG))
9600   (return)]
9601  "TARGET_SHMEDIA"
9602  "blink	%1, r63"
9603  [(set_attr "type" "jump_media")])
9604
9605(define_expand "sibcall_value"
9606  [(parallel
9607    [(set (match_operand 0 "arith_reg_operand" "")
9608	  (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9609	  	(match_operand 2 "" "")))
9610     (match_operand 3 "" "")
9611     (use (reg:PSI FPSCR_REG))
9612     (return)])]
9613  ""
9614{
9615  if (TARGET_SHMEDIA)
9616    {
9617      operands[1] = shmedia_prepare_call_address (operands[1], 1);
9618      emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
9619					       operands[2]));
9620      DONE;
9621    }
9622  else if (TARGET_SHCOMPACT && operands[3]
9623	   && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9624    {
9625      rtx cookie_rtx = operands[3];
9626      long cookie = INTVAL (cookie_rtx);
9627      rtx func = XEXP (operands[1], 0);
9628      rtx mach, r1;
9629
9630      if (flag_pic)
9631	{
9632	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9633	    {
9634	      rtx reg = gen_reg_rtx (Pmode);
9635
9636	      emit_insn (gen_symGOT2reg (reg, func));
9637	      func = reg;
9638	    }
9639	  else
9640	    func = legitimize_pic_address (func, Pmode, 0);
9641	}
9642
9643      /* FIXME: if we could tell whether all argument registers are
9644	 already taken, we could decide whether to force the use of
9645	 MACH_REG or to stick to R0_REG.  Unfortunately, there's no
9646	 simple way to tell.  We could use the CALL_COOKIE, but we
9647	 can't currently tell a register used for regular argument
9648	 passing from one that is unused.  If we leave it up to reload
9649	 to decide which register to use, it seems to always choose
9650	 R0_REG, which leaves no available registers in SIBCALL_REGS
9651	 to hold the address of the trampoline.  */
9652      mach = gen_rtx_REG (SImode, MACH_REG);
9653      r1 = gen_rtx_REG (SImode, R1_REG);
9654
9655      /* Since such a call function may use all call-clobbered
9656	 registers, we force a mode switch earlier, so that we don't
9657	 run out of registers when adjusting fpscr for the call.  */
9658      emit_insn (gen_force_mode_for_call ());
9659
9660      operands[1]
9661	= function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9662      operands[1] = force_reg (SImode, operands[1]);
9663
9664      /* We don't need a return trampoline, since the callee will
9665	 return directly to the upper caller.  */
9666      if (cookie & CALL_COOKIE_RET_TRAMP (1))
9667	{
9668	  cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9669	  cookie_rtx = GEN_INT (cookie);
9670	}
9671
9672      emit_move_insn (mach, func);
9673      emit_move_insn (r1, cookie_rtx);
9674
9675      emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
9676						 operands[2], mach));
9677      DONE;
9678    }
9679  else if (TARGET_SHCOMPACT && flag_pic
9680	   && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9681	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9682    {
9683      rtx reg = gen_reg_rtx (Pmode);
9684
9685      emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
9686      XEXP (operands[1], 0) = reg;
9687    }
9688  if (flag_pic && TARGET_SH2
9689      && MEM_P (operands[1])
9690      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9691      /* The PLT needs the PIC register, but the epilogue would have
9692	 to restore it, so we can only use PC-relative PIC calls for
9693	 static functions.  */
9694      && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9695    {
9696      emit_call_insn (gen_sibcall_value_pcrel (operands[0],
9697					       XEXP (operands[1], 0),
9698					       operands[2]));
9699      DONE;
9700    }
9701  else
9702    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9703
9704  emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
9705  DONE;
9706})
9707
9708(define_insn "call_value_pop_compact"
9709  [(set (match_operand 0 "" "=rf")
9710	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9711	      (match_operand 2 "" "")))
9712   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9713				 (match_operand 4 "immediate_operand" "n")))
9714   (match_operand 3 "immediate_operand" "n")
9715   (use (reg:SI R0_REG))
9716   (use (reg:SI R1_REG))
9717   (use (reg:PSI FPSCR_REG))
9718   (clobber (reg:SI PR_REG))]
9719  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9720  "jsr	@%1%#"
9721  [(set_attr "type" "call")
9722   (set (attr "fp_mode")
9723	(if_then_else (eq_attr "fpu_single" "yes")
9724		      (const_string "single") (const_string "double")))
9725   (set_attr "needs_delay_slot" "yes")])
9726
9727(define_insn "call_value_pop_compact_rettramp"
9728  [(set (match_operand 0 "" "=rf")
9729	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9730	      (match_operand 2 "" "")))
9731   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9732				 (match_operand 4 "immediate_operand" "n")))
9733   (match_operand 3 "immediate_operand" "n")
9734   (use (reg:SI R0_REG))
9735   (use (reg:SI R1_REG))
9736   (use (reg:PSI FPSCR_REG))
9737   (clobber (reg:SI R10_REG))
9738   (clobber (reg:SI PR_REG))]
9739  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9740  "jsr	@%1%#"
9741  [(set_attr "type" "call")
9742   (set (attr "fp_mode")
9743	(if_then_else (eq_attr "fpu_single" "yes")
9744		      (const_string "single") (const_string "double")))
9745   (set_attr "needs_delay_slot" "yes")])
9746
9747(define_expand "call_value_pop"
9748  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9749		   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9750				 (match_operand 2 "" "")))
9751	      (match_operand 3 "" "")
9752	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9753					    (match_operand 4 "" "")))])]
9754  "TARGET_SHCOMPACT"
9755{
9756  rtx cookie_rtx;
9757  long cookie;
9758  rtx func;
9759  rtx r0, r1;
9760
9761  gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
9762  cookie_rtx = operands[3];
9763  cookie = INTVAL (cookie_rtx);
9764  func = XEXP (operands[1], 0);
9765
9766  if (flag_pic)
9767    {
9768      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9769	{
9770	  rtx reg = gen_reg_rtx (Pmode);
9771
9772	  emit_insn (gen_symGOTPLT2reg (reg, func));
9773	  func = reg;
9774	}
9775      else
9776	func = legitimize_pic_address (func, Pmode, 0);
9777    }
9778
9779  r0 = gen_rtx_REG (SImode, R0_REG);
9780  r1 = gen_rtx_REG (SImode, R1_REG);
9781
9782  /* Since such a call function may use all call-clobbered
9783     registers, we force a mode switch earlier, so that we don't
9784     run out of registers when adjusting fpscr for the call.  */
9785  emit_insn (gen_force_mode_for_call ());
9786
9787  operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9788				 SFUNC_GOT);
9789  operands[1] = force_reg (SImode, operands[1]);
9790
9791  emit_move_insn (r0, func);
9792  emit_move_insn (r1, cookie_rtx);
9793
9794  if (cookie & CALL_COOKIE_RET_TRAMP (1))
9795    emit_call_insn (gen_call_value_pop_compact_rettramp
9796			(operands[0], operands[1], operands[2],
9797			 operands[3], operands[4]));
9798  else
9799    emit_call_insn (gen_call_value_pop_compact
9800			(operands[0], operands[1], operands[2],
9801			 operands[3], operands[4]));
9802
9803  DONE;
9804})
9805
9806(define_expand "sibcall_epilogue"
9807  [(return)]
9808  ""
9809{
9810  sh_expand_epilogue (true);
9811  if (TARGET_SHCOMPACT)
9812    {
9813      rtx insn, set;
9814
9815      /* If epilogue clobbers r0, preserve it in macl.  */
9816      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
9817	if ((set = single_set (insn))
9818	    && REG_P (SET_DEST (set))
9819	    && REGNO (SET_DEST (set)) == R0_REG)
9820	  {
9821	    rtx r0 = gen_rtx_REG (SImode, R0_REG);
9822	    rtx tmp = gen_rtx_REG (SImode, MACL_REG);
9823
9824	    /* We can't tell at this point whether the sibcall is a
9825	       sibcall_compact and, if it is, whether it uses r0 or
9826	       mach as operand 2, so let the instructions that
9827	       preserve r0 be optimized away if r0 turns out to be
9828	       dead.  */
9829	    emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
9830	    emit_move_insn (r0, tmp);
9831	    break;
9832	  }
9833    }
9834  DONE;
9835})
9836
9837(define_insn "indirect_jump_compact"
9838  [(set (pc)
9839	(match_operand:SI 0 "arith_reg_operand" "r"))]
9840  "TARGET_SH1"
9841  "jmp	@%0%#"
9842  [(set_attr "needs_delay_slot" "yes")
9843   (set_attr "type" "jump_ind")])
9844
9845(define_expand "indirect_jump"
9846  [(set (pc)
9847	(match_operand 0 "register_operand" ""))]
9848  ""
9849{
9850  if (GET_MODE (operands[0]) != Pmode)
9851    operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
9852})
9853
9854;; The use of operand 1 / 2 helps us distinguish case table jumps
9855;; which can be present in structured code from indirect jumps which can not
9856;; be present in structured code.  This allows -fprofile-arcs to work.
9857
9858;; For SH1 processors.
9859(define_insn "casesi_jump_1"
9860  [(set (pc)
9861	(match_operand:SI 0 "register_operand" "r"))
9862   (use (label_ref (match_operand 1 "" "")))]
9863  "TARGET_SH1"
9864  "jmp	@%0%#"
9865  [(set_attr "needs_delay_slot" "yes")
9866   (set_attr "type" "jump_ind")])
9867
9868;; For all later processors.
9869(define_insn "casesi_jump_2"
9870  [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
9871		      (label_ref (match_operand 1 "" ""))))
9872   (use (label_ref (match_operand 2 "" "")))]
9873  "TARGET_SH2
9874   && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
9875  "braf	%0%#"
9876  [(set_attr "needs_delay_slot" "yes")
9877   (set_attr "type" "jump_ind")])
9878
9879(define_insn "casesi_jump_media"
9880  [(set (pc) (match_operand 0 "target_reg_operand" "b"))
9881   (use (label_ref (match_operand 1 "" "")))]
9882  "TARGET_SHMEDIA"
9883  "blink	%0, r63"
9884  [(set_attr "type" "jump_media")])
9885
9886;; Call subroutine returning any type.
9887;; ??? This probably doesn't work.
9888(define_expand "untyped_call"
9889  [(parallel [(call (match_operand 0 "" "")
9890		    (const_int 0))
9891	      (match_operand 1 "" "")
9892	      (match_operand 2 "" "")])]
9893  "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
9894{
9895  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
9896
9897  for (int i = 0; i < XVECLEN (operands[2], 0); i++)
9898    {
9899      rtx set = XVECEXP (operands[2], 0, i);
9900      emit_move_insn (SET_DEST (set), SET_SRC (set));
9901    }
9902
9903  /* The optimizer does not know that the call sets the function value
9904     registers we stored in the result block.  We avoid problems by
9905     claiming that all hard registers are used and clobbered at this
9906     point.  */
9907  emit_insn (gen_blockage ());
9908
9909  DONE;
9910})
9911
9912;; ------------------------------------------------------------------------
9913;; Misc insns
9914;; ------------------------------------------------------------------------
9915
9916(define_insn "dect"
9917  [(set (reg:SI T_REG)
9918	(eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
9919   (set (match_operand:SI 0 "arith_reg_dest" "=r")
9920	(plus:SI (match_dup 1) (const_int -1)))]
9921  "TARGET_SH2"
9922  "dt	%0"
9923  [(set_attr "type" "arith")])
9924
9925(define_insn "nop"
9926  [(const_int 0)]
9927  ""
9928  "nop")
9929
9930;; Load address of a label. This is only generated by the casesi expand,
9931;; and by machine_dependent_reorg (fixing up fp moves).
9932;; This must use unspec, because this only works for labels that are
9933;; within range.
9934(define_insn "mova"
9935  [(set (reg:SI R0_REG)
9936	(unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
9937  "TARGET_SH1"
9938  "mova	%O0,r0"
9939  [(set_attr "in_delay_slot" "no")
9940   (set_attr "type" "arith")])
9941
9942;; machine_dependent_reorg will make this a `mova'.
9943(define_insn "mova_const"
9944  [(set (reg:SI R0_REG)
9945	(unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
9946  "TARGET_SH1"
9947  "#"
9948  [(set_attr "in_delay_slot" "no")
9949   (set_attr "type" "arith")])
9950
9951(define_expand "GOTaddr2picreg"
9952  [(set (reg:SI R0_REG)
9953	(unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
9954		   UNSPEC_MOVA))
9955   (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
9956   (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
9957  ""
9958{
9959  if (TARGET_VXWORKS_RTP)
9960    {
9961      rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
9962      rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
9963      emit_insn (gen_vxworks_picreg (gott_base, gott_index));
9964      DONE;
9965    }
9966
9967  operands[0] = gen_rtx_REG (Pmode, PIC_REG);
9968  operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
9969
9970  if (TARGET_SHMEDIA)
9971    {
9972      rtx tr = gen_rtx_REG (Pmode, TR0_REG);
9973      rtx pic = operands[0];
9974      rtx lab = PATTERN (gen_call_site ());
9975      rtx insn, equiv;
9976
9977      equiv = operands[1];
9978      operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
9979				    UNSPEC_PCREL_SYMOFF);
9980      operands[1] = gen_rtx_CONST (Pmode, operands[1]);
9981
9982      if (Pmode == SImode)
9983	{
9984	  emit_insn (gen_movsi_const (pic, operands[1]));
9985	  emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
9986	}
9987      else
9988	{
9989	  emit_insn (gen_movdi_const (pic, operands[1]));
9990	  emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
9991	}
9992
9993      insn = emit_move_insn (operands[0], tr);
9994
9995      set_unique_reg_note (insn, REG_EQUAL, equiv);
9996
9997      DONE;
9998    }
9999})
10000
10001;; A helper for GOTaddr2picreg to finish up the initialization of the
10002;; PIC register.
10003(define_expand "vxworks_picreg"
10004  [(set (reg:SI PIC_REG)
10005	(const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
10006   (set (reg:SI R0_REG)
10007	(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
10008   (set (reg:SI PIC_REG)
10009	(mem:SI (reg:SI PIC_REG)))
10010   (set (reg:SI PIC_REG)
10011	(mem:SI (plus:SI (reg:SI PIC_REG)
10012			 (reg:SI R0_REG))))]
10013  "TARGET_VXWORKS_RTP")
10014
10015(define_insn "*ptb"
10016  [(set (match_operand 0 "target_reg_operand" "=b")
10017	(const (unspec [(match_operand 1 "" "Csy")]
10018			     UNSPEC_DATALABEL)))]
10019  "TARGET_SHMEDIA && flag_pic
10020   && satisfies_constraint_Csy (operands[1])"
10021  "ptb/u	datalabel %1, %0"
10022  [(set_attr "type" "ptabs_media")
10023   (set_attr "length" "*")])
10024
10025(define_insn "ptrel_si"
10026  [(set (match_operand:SI 0 "target_reg_operand" "=b")
10027	(plus:SI (match_operand:SI 1 "register_operand" "r")
10028	      (pc)))
10029   (match_operand:SI 2 "" "")]
10030  "TARGET_SHMEDIA"
10031  "%O2: ptrel/u	%1, %0"
10032  [(set_attr "type" "ptabs_media")])
10033
10034(define_insn "ptrel_di"
10035  [(set (match_operand:DI 0 "target_reg_operand" "=b")
10036	(plus:DI (match_operand:DI 1 "register_operand" "r")
10037	      (pc)))
10038   (match_operand:DI 2 "" "")]
10039  "TARGET_SHMEDIA"
10040  "%O2: ptrel/u	%1, %0"
10041  [(set_attr "type" "ptabs_media")])
10042
10043(define_expand "builtin_setjmp_receiver"
10044  [(match_operand 0 "" "")]
10045  "flag_pic"
10046{
10047  emit_insn (gen_GOTaddr2picreg ());
10048  DONE;
10049})
10050
10051(define_expand "call_site"
10052  [(unspec [(match_dup 0)] UNSPEC_CALLER)]
10053  "TARGET_SH1"
10054{
10055  static HOST_WIDE_INT i = 0;
10056  operands[0] = GEN_INT (i);
10057  i++;
10058})
10059
10060;; op0 = op1 + r12 but hide it before reload completed.  See the comment
10061;; in symGOT_load expand.
10062(define_insn_and_split "chk_guard_add"
10063  [(set (match_operand:SI 0 "register_operand" "=&r")
10064	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
10065		    (reg:SI PIC_REG)]
10066		   UNSPEC_CHKADD))]
10067  "TARGET_SH1"
10068  "#"
10069  "TARGET_SH1 && reload_completed"
10070  [(set (match_dup 0) (reg:SI PIC_REG))
10071   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
10072  ""
10073  [(set_attr "type" "arith")])
10074
10075(define_expand "sym_label2reg"
10076  [(set (match_operand:SI 0 "" "")
10077	(const:SI (unspec:SI [(match_operand:SI 1 "" "")
10078			      (const (plus:SI (match_operand:SI 2 "" "")
10079					      (const_int 2)))]
10080			     UNSPEC_SYMOFF)))]
10081  "TARGET_SH1" "")
10082
10083(define_expand "symGOT_load"
10084  [(set (match_dup 2) (match_operand 1 "" ""))
10085   (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
10086   (set (match_operand 0 "" "") (mem (match_dup 3)))]
10087  ""
10088{
10089  rtx mem;
10090
10091  operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10092  operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10093
10094  if (TARGET_SHMEDIA)
10095    {
10096      rtx reg = operands[2];
10097
10098      if (Pmode == DImode)
10099	{      
10100	  if (flag_pic > 1)
10101	    emit_insn (gen_movdi_const_32bit (reg, operands[1]));
10102	  else
10103	    emit_insn (gen_movdi_const_16bit (reg, operands[1]));
10104	}
10105      else
10106	{
10107	  if (flag_pic > 1)
10108	    emit_insn (gen_movsi_const (reg, operands[1]));
10109	  else
10110	    emit_insn (gen_movsi_const_16bit (reg, operands[1]));
10111	}
10112    }
10113  else
10114    emit_move_insn (operands[2], operands[1]);
10115
10116  /* When stack protector inserts codes after the result is set to
10117     R0, @(rX, r12) will cause a spill failure for R0.  Use a unspec
10118     insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
10119     when rX is a GOT address for the guard symbol.  Ugly but doesn't
10120     matter because this is a rare situation.  */
10121  if (!TARGET_SHMEDIA
10122      && flag_stack_protect
10123      && GET_CODE (operands[1]) == CONST
10124      && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
10125      && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
10126      && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
10127		 "__stack_chk_guard") == 0)
10128    emit_insn (gen_chk_guard_add (operands[3], operands[2]));
10129  else
10130    emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
10131					       gen_rtx_REG (Pmode, PIC_REG)));
10132
10133  /* N.B. This is not constant for a GOTPLT relocation.  */
10134  mem = gen_rtx_MEM (Pmode, operands[3]);
10135  MEM_NOTRAP_P (mem) = 1;
10136  /* ??? Should we have a special alias set for the GOT?  */
10137  emit_move_insn (operands[0], mem);
10138
10139  DONE;
10140})
10141
10142(define_expand "sym2GOT"
10143  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
10144  ""
10145  "")
10146
10147(define_expand "symGOT2reg"
10148  [(match_operand 0 "" "") (match_operand 1 "" "")]
10149  ""
10150{
10151  rtx gotsym, insn;
10152
10153  gotsym = gen_sym2GOT (operands[1]);
10154  PUT_MODE (gotsym, Pmode);
10155  insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
10156
10157  MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
10158
10159  DONE;
10160})
10161
10162(define_expand "symGOTPLT2reg"
10163  [(match_operand 0 "" "") (match_operand 1 "" "")]
10164  ""
10165{
10166  rtx pltsym = gen_rtx_CONST (Pmode,
10167			      gen_rtx_UNSPEC (Pmode,
10168					      gen_rtvec (1, operands[1]),
10169					      UNSPEC_GOTPLT));
10170  emit_insn (gen_symGOT_load (operands[0], pltsym));
10171  DONE;
10172})
10173
10174(define_expand "sym2GOTOFF"
10175  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10176  ""
10177  "")
10178
10179(define_expand "symGOTOFF2reg"
10180  [(match_operand 0 "" "") (match_operand 1 "" "")]
10181  ""
10182{
10183  rtx gotoffsym, insn;
10184  rtx t = (!can_create_pseudo_p ()
10185	   ? operands[0]
10186	   : gen_reg_rtx (GET_MODE (operands[0])));
10187
10188  gotoffsym = gen_sym2GOTOFF (operands[1]);
10189  PUT_MODE (gotoffsym, Pmode);
10190  emit_move_insn (t, gotoffsym);
10191  insn = emit_move_insn (operands[0],
10192			 gen_rtx_PLUS (Pmode, t,
10193				       gen_rtx_REG (Pmode, PIC_REG)));
10194
10195  set_unique_reg_note (insn, REG_EQUAL, operands[1]);
10196
10197  DONE;
10198})
10199
10200(define_expand "symPLT_label2reg"
10201  [(set (match_operand:SI 0 "" "")
10202	(const:SI
10203	 (unspec:SI
10204	  [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10205	   (const:SI (plus:SI (match_operand:SI 2 "" "")
10206			      (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
10207   ;; Even though the PIC register is not really used by the call
10208   ;; sequence in which this is expanded, the PLT code assumes the PIC
10209   ;; register is set, so we must not skip its initialization.  Since
10210   ;; we only use this expand as part of calling sequences, and never
10211   ;; to take the address of a function, this is the best point to
10212   ;; insert the (use).  Using the PLT to take the address of a
10213   ;; function would be wrong, not only because the PLT entry could
10214   ;; then be called from a function that doesn't initialize the PIC
10215   ;; register to the proper GOT, but also because pointers to the
10216   ;; same function might not compare equal, should they be set by
10217   ;; different shared libraries.
10218   (use (reg:SI PIC_REG))]
10219  "TARGET_SH1"
10220  "")
10221
10222(define_expand "sym2PIC"
10223  [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
10224  ""
10225  "")
10226
10227;; -------------------------------------------------------------------------
10228;; TLS code generation.
10229
10230;; FIXME: The multi-insn asm blocks should be converted to use
10231;; define_insn_and_split.
10232;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10233;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10234;; for details.
10235
10236(define_insn "tls_global_dynamic"
10237  [(set (match_operand:SI 0 "register_operand" "=&z")
10238	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10239				  UNSPEC_TLSGD))
10240	      (const_int 0)))
10241   (use (reg:PSI FPSCR_REG))
10242   (use (reg:SI PIC_REG))
10243   (clobber (reg:SI PR_REG))
10244   (clobber (scratch:SI))]
10245  "TARGET_SH1"
10246{
10247  return       "mov.l	1f,r4"			"\n"
10248	 "	mova	2f,r0"			"\n"
10249	 "	mov.l	2f,r1"			"\n"
10250	 "	add	r0,r1"			"\n"
10251	 "	jsr	@r1"			"\n"
10252	 "	add	r12,r4"			"\n"
10253	 "	bra	3f"			"\n"
10254	 "	nop"				"\n"
10255	 "	.align	2"			"\n"
10256	 "1:	.long	%a1@TLSGD"		"\n"
10257	 "2:	.long	__tls_get_addr@PLT"	"\n"
10258	 "3:";
10259}
10260  [(set_attr "type" "tls_load")
10261   (set_attr "length" "26")])
10262
10263(define_insn "tls_local_dynamic"
10264  [(set (match_operand:SI 0 "register_operand" "=&z")
10265	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10266				  UNSPEC_TLSLDM))
10267	      (const_int 0)))
10268   (use (reg:PSI FPSCR_REG))
10269   (use (reg:SI PIC_REG))
10270   (clobber (reg:SI PR_REG))
10271   (clobber (scratch:SI))]
10272  "TARGET_SH1"
10273{
10274  return       "mov.l	1f,r4"			"\n"
10275	 "	mova	2f,r0"			"\n"
10276	 "	mov.l	2f,r1"			"\n"
10277	 "	add	r0,r1"			"\n"
10278	 "	jsr	@r1"			"\n"
10279	 "	add	r12,r4"			"\n"
10280	 "	bra	3f"			"\n"
10281	 "	nop"				"\n"
10282	 "	.align	2"			"\n"
10283	 "1:	.long	%a1@TLSLDM"		"\n"
10284	 "2:	.long	__tls_get_addr@PLT"	"\n"
10285	 "3:";
10286}
10287  [(set_attr "type" "tls_load")
10288   (set_attr "length" "26")])
10289
10290(define_expand "sym2DTPOFF"
10291  [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
10292  ""
10293  "")
10294
10295(define_expand "symDTPOFF2reg"
10296  [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
10297  ""
10298{
10299  rtx dtpoffsym;
10300  rtx t = (!can_create_pseudo_p ()
10301	   ? operands[0]
10302	   : gen_reg_rtx (GET_MODE (operands[0])));
10303
10304  dtpoffsym = gen_sym2DTPOFF (operands[1]);
10305  PUT_MODE (dtpoffsym, Pmode);
10306  emit_move_insn (t, dtpoffsym);
10307  emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
10308  DONE;
10309})
10310
10311(define_expand "sym2GOTTPOFF"
10312  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
10313  ""
10314  "")
10315
10316(define_insn "tls_initial_exec"
10317  [(set (match_operand:SI 0 "register_operand" "=&r")
10318	(unspec:SI [(match_operand:SI 1 "" "")]
10319		    UNSPEC_TLSIE))
10320   (use (reg:SI GBR_REG))
10321   (use (reg:SI PIC_REG))
10322   (clobber (reg:SI R0_REG))]
10323  ""
10324{
10325  return       "mov.l	1f,r0"		"\n"
10326	 "	stc	gbr,%0"		"\n"
10327	 "	mov.l	@(r0,r12),r0"	"\n"
10328	 "	bra	2f"		"\n"
10329	 "	add	r0,%0"		"\n"
10330	 "	.align	2"		"\n"
10331	 "1:	.long	%a1"		"\n"
10332	 "2:";
10333}
10334  [(set_attr "type" "tls_load")
10335   (set_attr "length" "16")])
10336
10337(define_expand "sym2TPOFF"
10338  [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
10339  ""
10340  "")
10341
10342(define_expand "symTPOFF2reg"
10343  [(match_operand 0 "" "") (match_operand 1 "" "")]
10344  ""
10345{
10346  rtx tpoffsym;
10347
10348  tpoffsym = gen_sym2TPOFF (operands[1]);
10349  PUT_MODE (tpoffsym, Pmode);
10350  emit_move_insn (operands[0], tpoffsym);
10351  DONE;
10352})
10353
10354;;------------------------------------------------------------------------------
10355;; Thread pointer getter and setter.
10356;;
10357;; On SH the thread pointer is kept in the GBR.
10358;; These patterns are usually expanded from the respective built-in functions.
10359(define_expand "get_thread_pointersi"
10360  [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))]
10361  "TARGET_SH1")
10362
10363;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
10364(define_insn "store_gbr"
10365  [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))]
10366  ""
10367  "stc	gbr,%0"
10368  [(set_attr "type" "tls_load")])
10369
10370(define_expand "set_thread_pointersi"
10371  [(set (reg:SI GBR_REG)
10372	(unspec_volatile:SI [(match_operand:SI 0 "register_operand")]
10373	 UNSPECV_GBR))]
10374  "TARGET_SH1")
10375
10376(define_insn "load_gbr"
10377  [(set (reg:SI GBR_REG)
10378	(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
10379	 UNSPECV_GBR))]
10380  "TARGET_SH1"
10381  "ldc	%0,gbr"
10382  [(set_attr "type" "move")])
10383
10384;;------------------------------------------------------------------------------
10385;; Thread pointer relative memory loads and stores.
10386;;
10387;; On SH there are GBR displacement address modes which can be utilized to
10388;; access memory behind the thread pointer.
10389;; Since we do not allow using GBR for general purpose memory accesses, these
10390;; GBR addressing modes are formed by the combine pass.
10391;; This could be done with fewer patterns than below by using a mem predicate
10392;; for the GBR mem, but then reload would try to reload addresses with a
10393;; zero displacement for some strange reason.
10394
10395(define_insn "*mov<mode>_gbr_load"
10396  [(set (match_operand:QIHISI 0 "register_operand" "=z")
10397	(mem:QIHISI (plus:SI (reg:SI GBR_REG)
10398			     (match_operand:QIHISI 1 "gbr_displacement"))))]
10399  "TARGET_SH1"
10400  "mov.<bwl>	@(%O1,gbr),%0"
10401  [(set_attr "type" "load")])
10402
10403(define_insn "*mov<mode>_gbr_load"
10404  [(set (match_operand:QIHISI 0 "register_operand" "=z")
10405	(mem:QIHISI (reg:SI GBR_REG)))]
10406  "TARGET_SH1"
10407  "mov.<bwl>	@(0,gbr),%0"
10408  [(set_attr "type" "load")])
10409
10410(define_insn "*mov<mode>_gbr_load"
10411  [(set (match_operand:SI 0 "register_operand" "=z")
10412	(sign_extend:SI
10413	  (mem:QIHI (plus:SI (reg:SI GBR_REG)
10414			     (match_operand:QIHI 1 "gbr_displacement")))))]
10415  "TARGET_SH1"
10416  "mov.<bw>	@(%O1,gbr),%0"
10417  [(set_attr "type" "load")])
10418
10419(define_insn "*mov<mode>_gbr_load"
10420  [(set (match_operand:SI 0 "register_operand" "=z")
10421	(sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
10422  "TARGET_SH1"
10423  "mov.<bw>	@(0,gbr),%0"
10424  [(set_attr "type" "load")])
10425
10426(define_insn "*mov<mode>_gbr_store"
10427  [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10428			     (match_operand:QIHISI 0 "gbr_displacement")))
10429	(match_operand:QIHISI 1 "register_operand" "z"))]
10430  "TARGET_SH1"
10431  "mov.<bwl>	%1,@(%O0,gbr)"
10432  [(set_attr "type" "store")])
10433
10434(define_insn "*mov<mode>_gbr_store"
10435  [(set (mem:QIHISI (reg:SI GBR_REG))
10436	(match_operand:QIHISI 0 "register_operand" "z"))]
10437  "TARGET_SH1"
10438  "mov.<bwl>	%0,@(0,gbr)"
10439  [(set_attr "type" "store")])
10440
10441;; DImode memory accesses have to be split in two SImode accesses.
10442;; Split them before reload, so that it gets a better chance to figure out
10443;; how to deal with the R0 restriction for the individual SImode accesses.
10444;; Do not match this insn during or after reload because it can't be split
10445;; afterwards.
10446(define_insn_and_split "*movdi_gbr_load"
10447  [(set (match_operand:DI 0 "register_operand")
10448	(match_operand:DI 1 "gbr_address_mem"))]
10449  "TARGET_SH1 && can_create_pseudo_p ()"
10450  "#"
10451  "&& 1"
10452  [(set (match_dup 3) (match_dup 5))
10453   (set (match_dup 4) (match_dup 6))]
10454{
10455  /* Swap low/high part load order on little endian, so that the result reg
10456     of the second load can be used better.  */
10457  int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
10458  operands[3 + off] = gen_lowpart (SImode, operands[0]);
10459  operands[5 + off] = gen_lowpart (SImode, operands[1]);
10460  operands[4 - off] = gen_highpart (SImode, operands[0]);
10461  operands[6 - off] = gen_highpart (SImode, operands[1]);
10462})
10463
10464(define_insn_and_split "*movdi_gbr_store"
10465  [(set (match_operand:DI 0 "gbr_address_mem")
10466	(match_operand:DI 1 "register_operand"))]
10467  "TARGET_SH1 && can_create_pseudo_p ()"
10468  "#"
10469  "&& 1"
10470  [(set (match_dup 3) (match_dup 5))
10471   (set (match_dup 4) (match_dup 6))]
10472{
10473  /* Swap low/high part store order on big endian, so that stores of function
10474     call results can save a reg copy.  */
10475  int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
10476  operands[3 + off] = gen_lowpart (SImode, operands[0]);
10477  operands[5 + off] = gen_lowpart (SImode, operands[1]);
10478  operands[4 - off] = gen_highpart (SImode, operands[0]);
10479  operands[6 - off] = gen_highpart (SImode, operands[1]);
10480})
10481
10482;; Sometimes memory accesses do not get combined with the store_gbr insn,
10483;; in particular when the displacements are in the range of the regular move
10484;; insns.  Thus, in the first split pass after the combine pass we search
10485;; for missed opportunities and try to fix them up ourselves.
10486;; If an equivalent GBR address can be determined the load / store is split
10487;; into one of the GBR load / store patterns.
10488;; All of that must happen before reload (GBR address modes use R0 as the
10489;; other operand) and there's no point of doing it if the GBR is not
10490;; referenced in a function at all.
10491(define_split
10492  [(set (match_operand:QIHISIDI 0 "register_operand")
10493	(match_operand:QIHISIDI 1 "memory_operand"))]
10494  "TARGET_SH1 && !reload_in_progress && !reload_completed
10495   && df_regs_ever_live_p (GBR_REG)"
10496  [(set (match_dup 0) (match_dup 1))]
10497{
10498  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10499  if (gbr_mem != NULL_RTX)
10500    operands[1] = replace_equiv_address (operands[1], gbr_mem);
10501  else
10502    FAIL;
10503})
10504
10505(define_split
10506  [(set (match_operand:SI 0 "register_operand")
10507	(sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10508  "TARGET_SH1 && !reload_in_progress && !reload_completed
10509   && df_regs_ever_live_p (GBR_REG)"
10510  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
10511{
10512  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10513  if (gbr_mem != NULL_RTX)
10514    operands[1] = replace_equiv_address (operands[1], gbr_mem);
10515  else
10516    FAIL;
10517})
10518
10519;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
10520;; Split those so that a GBR load can be used.
10521(define_split
10522  [(set (match_operand:SI 0 "register_operand")
10523	(zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10524  "TARGET_SH2A && !reload_in_progress && !reload_completed
10525   && df_regs_ever_live_p (GBR_REG)"
10526  [(set (match_dup 2) (match_dup 1))
10527   (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
10528{
10529  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10530  if (gbr_mem != NULL_RTX)
10531    {
10532      operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
10533      operands[1] = replace_equiv_address (operands[1], gbr_mem);
10534    }
10535  else
10536    FAIL;
10537})
10538
10539(define_split
10540  [(set (match_operand:QIHISIDI 0 "memory_operand")
10541	(match_operand:QIHISIDI 1 "register_operand"))]
10542  "TARGET_SH1 && !reload_in_progress && !reload_completed
10543   && df_regs_ever_live_p (GBR_REG)"
10544  [(set (match_dup 0) (match_dup 1))]
10545{
10546  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
10547  if (gbr_mem != NULL_RTX)
10548    operands[0] = replace_equiv_address (operands[0], gbr_mem);
10549  else
10550    FAIL;
10551})
10552
10553;;------------------------------------------------------------------------------
10554;; case instruction for switch statements.
10555
10556;; operand 0 is index
10557;; operand 1 is the minimum bound
10558;; operand 2 is the maximum bound - minimum bound + 1
10559;; operand 3 is CODE_LABEL for the table;
10560;; operand 4 is the CODE_LABEL to go to if index out of range.
10561(define_expand "casesi"
10562  [(match_operand:SI 0 "arith_reg_operand" "")
10563   (match_operand:SI 1 "arith_reg_operand" "")
10564   (match_operand:SI 2 "arith_reg_operand" "")
10565   (match_operand 3 "" "") (match_operand 4 "" "")]
10566  ""
10567{
10568  rtx reg = gen_reg_rtx (SImode);
10569  rtx reg2 = gen_reg_rtx (SImode);
10570  if (TARGET_SHMEDIA)
10571    {
10572      rtx reg = gen_reg_rtx (DImode);
10573      rtx reg2 = gen_reg_rtx (DImode);
10574      rtx reg3 = gen_reg_rtx (Pmode);
10575      rtx reg4 = gen_reg_rtx (Pmode);
10576      rtx reg5 = gen_reg_rtx (Pmode);
10577      rtx load, test;
10578
10579      operands[0] = convert_modes (DImode, SImode, operands[0], 0);
10580      operands[1] = convert_modes (DImode, SImode, operands[1], 0);
10581      operands[2] = convert_modes (DImode, SImode, operands[2], 1);
10582
10583      test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
10584      emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0],
10585				      operands[4]));
10586      emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
10587      test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
10588      emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
10589      emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
10590      emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
10591					       (Pmode, operands[3])));
10592      /* Messy: can we subreg to clean this up? */
10593      if (Pmode == DImode)
10594	load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
10595      else
10596	load = gen_casesi_load_media (reg4,
10597				      gen_rtx_SUBREG (DImode, reg3, 0),
10598				      reg2, operands[3]);
10599      PUT_MODE (SET_SRC (load), Pmode);
10600      emit_insn (load);
10601      /* ??? The following add could be eliminated if we used ptrel.  */
10602      emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
10603      emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
10604      emit_barrier ();
10605      DONE;
10606    }
10607  operands[1] = copy_to_mode_reg (SImode, operands[1]);
10608  operands[2] = copy_to_mode_reg (SImode, operands[2]);
10609  /* If optimizing, casesi_worker depends on the mode of the instruction
10610     before label it 'uses' - operands[3].  */
10611  emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
10612			   reg));
10613  emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
10614  if (TARGET_SH2)
10615    emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
10616  else
10617    emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
10618  /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
10619     operands[3], but to lab.  We will fix this up in
10620     machine_dependent_reorg.  */
10621  emit_barrier ();
10622  DONE;
10623})
10624
10625(define_expand "casesi_0"
10626  [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
10627   (set (match_dup 4) (minus:SI (match_dup 4)
10628				(match_operand:SI 1 "arith_operand" "")))
10629   (set (reg:SI T_REG)
10630	(gtu:SI (match_dup 4)
10631		(match_operand:SI 2 "arith_reg_operand" "")))
10632   (set (pc)
10633	(if_then_else (ne (reg:SI T_REG)
10634			  (const_int 0))
10635		      (label_ref (match_operand 3 "" ""))
10636		      (pc)))]
10637  "TARGET_SH1"
10638  "")
10639
10640;; ??? reload might clobber r0 if we use it explicitly in the RTL before
10641;; reload; using a R0_REGS pseudo reg is likely to give poor code.
10642;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
10643(define_insn "casesi_worker_0"
10644  [(set (match_operand:SI 0 "register_operand" "=r,r")
10645	(unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
10646		 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10647   (clobber (match_scratch:SI 3 "=X,1"))
10648   (clobber (match_scratch:SI 4 "=&z,z"))]
10649  "TARGET_SH1"
10650  "#")
10651
10652(define_split
10653  [(set (match_operand:SI 0 "register_operand" "")
10654	(unspec:SI [(match_operand:SI 1 "register_operand" "")
10655		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10656   (clobber (match_scratch:SI 3 ""))
10657   (clobber (match_scratch:SI 4 ""))]
10658  "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
10659  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10660   (parallel [(set (match_dup 0)
10661	      (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10662			  (label_ref (match_dup 2))] UNSPEC_CASESI))
10663	      (clobber (match_dup 3))])
10664   (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10665{
10666  if (GET_CODE (operands[2]) == CODE_LABEL)
10667    LABEL_NUSES (operands[2])++;
10668})
10669
10670(define_split
10671  [(set (match_operand:SI 0 "register_operand" "")
10672	(unspec:SI [(match_operand:SI 1 "register_operand" "")
10673		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10674   (clobber (match_scratch:SI 3 ""))
10675   (clobber (match_scratch:SI 4 ""))]
10676  "TARGET_SH2 && reload_completed"
10677  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10678   (parallel [(set (match_dup 0)
10679	      (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10680			  (label_ref (match_dup 2))] UNSPEC_CASESI))
10681	      (clobber (match_dup 3))])]
10682{
10683  if (GET_CODE (operands[2]) == CODE_LABEL)
10684    LABEL_NUSES (operands[2])++;
10685})
10686
10687(define_insn "casesi_worker_1"
10688  [(set (match_operand:SI 0 "register_operand" "=r,r")
10689	(unspec:SI [(reg:SI R0_REG)
10690		    (match_operand:SI 1 "register_operand" "0,r")
10691		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10692   (clobber (match_scratch:SI 3 "=X,1"))]
10693  "TARGET_SH1"
10694{
10695  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10696
10697  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10698
10699  switch (GET_MODE (diff_vec))
10700    {
10701    case SImode:
10702      return   "shll2	%1"	"\n"
10703	     "	mov.l	@(r0,%1),%0";
10704    case HImode:
10705      return   "add	%1,%1"	"\n"
10706	     "	mov.w	@(r0,%1),%0";
10707    case QImode:
10708      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10709	return         "mov.b	@(r0,%1),%0"	"\n"
10710	       "	extu.b	%0,%0";
10711      else
10712	return "mov.b	@(r0,%1),%0";
10713
10714    default:
10715      gcc_unreachable ();
10716    }
10717}
10718  [(set_attr "length" "4")])
10719
10720(define_insn "casesi_worker_2"
10721  [(set (match_operand:SI 0 "register_operand" "=r,r")
10722	(unspec:SI [(reg:SI R0_REG)
10723		    (match_operand:SI 1 "register_operand" "0,r")
10724		    (label_ref (match_operand 2 "" ""))
10725		    (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
10726   (clobber (match_operand:SI 4 "" "=X,1"))]
10727  "TARGET_SH2 && reload_completed && flag_pic"
10728{
10729  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10730  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10731
10732  switch (GET_MODE (diff_vec))
10733    {
10734    case SImode:
10735      return   "shll2	%1"		"\n"
10736	     "	add	r0,%1"		"\n"
10737	     "	mova	%O3,r0"		"\n"
10738	     "  mov.l	@(r0,%1),%0";
10739    case HImode:
10740      return   "add	%1,%1"		"\n"
10741	     "	add	r0,%1"		"\n"
10742	     "	mova	%O3,r0"		"\n"
10743	     "	mov.w	@(r0,%1),%0";
10744    case QImode:
10745      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10746	return	       "add	r0,%1"		"\n"
10747		"	mova	%O3,r0"		"\n"
10748		"	mov.b	@(r0,%1),%0"	"\n"
10749		"	extu.b	%0,%0";
10750      else
10751	return	       "add	r0,%1"		"\n"
10752		"	mova	%O3,r0"		"\n"
10753		"	mov.b	@(r0,%1),%0";
10754    default:
10755      gcc_unreachable ();
10756    }
10757}
10758  [(set_attr "length" "8")])
10759
10760(define_insn "casesi_shift_media"
10761  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10762	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
10763		   (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
10764		    UNSPEC_CASESI)))]
10765  "TARGET_SHMEDIA"
10766{
10767  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10768
10769  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10770
10771  switch (GET_MODE (diff_vec))
10772    {
10773    case SImode:
10774      return "shlli	%1, 2, %0";
10775    case HImode:
10776      return "shlli	%1, 1, %0";
10777    case QImode:
10778      if (rtx_equal_p (operands[0], operands[1]))
10779	return "";
10780      return "add	%1, r63, %0";
10781    default:
10782      gcc_unreachable ();
10783    }
10784}
10785  [(set_attr "type" "arith_media")])
10786
10787(define_insn "casesi_load_media"
10788  [(set (match_operand 0 "any_arith_reg_dest" "=r")
10789	(mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
10790		      (match_operand:DI 2 "arith_reg_operand" "r")
10791		      (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
10792  "TARGET_SHMEDIA"
10793{
10794  rtx diff_vec = PATTERN (next_real_insn (operands[3]));
10795
10796  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10797
10798  switch (GET_MODE (diff_vec))
10799    {
10800    case SImode:
10801      return "ldx.l	%1, %2, %0";
10802    case HImode:
10803#if 0
10804      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10805	return "ldx.uw	%1, %2, %0";
10806#endif
10807      return "ldx.w	%1, %2, %0";
10808    case QImode:
10809      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10810	return "ldx.ub	%1, %2, %0";
10811      return "ldx.b	%1, %2, %0";
10812    default:
10813      gcc_unreachable ();
10814    }
10815}
10816  [(set_attr "type" "load_media")])
10817
10818(define_expand "simple_return"
10819  [(simple_return)]
10820 "sh_can_use_simple_return_p ()")
10821
10822(define_expand "return"
10823  [(return)]
10824 "reload_completed && epilogue_completed"
10825{
10826  if (TARGET_SHMEDIA)
10827    {
10828      emit_jump_insn (gen_return_media ());
10829      DONE;
10830    }
10831
10832  if (TARGET_SHCOMPACT
10833      && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
10834    {
10835      emit_jump_insn (gen_shcompact_return_tramp ());
10836      DONE;
10837    }
10838})
10839
10840(define_insn "*<code>_i"
10841  [(any_return)]
10842  "TARGET_SH1 && ! (TARGET_SHCOMPACT
10843		    && (crtl->args.info.call_cookie
10844			& CALL_COOKIE_RET_TRAMP (1)))
10845   && reload_completed
10846   && ! sh_cfun_trap_exit_p ()"
10847{
10848  if (TARGET_SH2A && (dbr_sequence_length () == 0)
10849      && !current_function_interrupt)
10850    return "rts/n";
10851  else
10852    return "%@	%#";
10853}
10854  [(set_attr "type" "return")
10855   (set_attr "needs_delay_slot" "yes")])
10856
10857;; trapa has no delay slot.
10858(define_insn "*return_trapa"
10859  [(return)]
10860  "TARGET_SH1 && !TARGET_SHCOMPACT
10861   && reload_completed"
10862  "%@"
10863  [(set_attr "type" "return")])
10864
10865(define_expand "shcompact_return_tramp"
10866  [(return)]
10867  "TARGET_SHCOMPACT
10868   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10869{
10870  rtx reg = gen_rtx_REG (Pmode, R0_REG);
10871
10872  function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
10873  emit_jump_insn (gen_shcompact_return_tramp_i ());
10874  DONE;
10875})
10876
10877(define_insn "shcompact_return_tramp_i"
10878  [(parallel [(return) (use (reg:SI R0_REG))])]
10879  "TARGET_SHCOMPACT
10880   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10881  "jmp	@r0%#"
10882  [(set_attr "type" "jump_ind")
10883   (set_attr "needs_delay_slot" "yes")])
10884
10885(define_insn "return_media_i"
10886  [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
10887  "TARGET_SHMEDIA && reload_completed"
10888  "blink	%0, r63"
10889  [(set_attr "type" "jump_media")])
10890
10891(define_insn "return_media_rte"
10892  [(return)]
10893  "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
10894  "rte"
10895  [(set_attr "type" "jump_media")])
10896
10897(define_expand "return_media"
10898  [(return)]
10899  "TARGET_SHMEDIA && reload_completed"
10900{
10901  int tr_regno = sh_media_register_for_return ();
10902  rtx tr;
10903
10904  if (current_function_interrupt)
10905    {
10906      emit_jump_insn (gen_return_media_rte ());
10907      DONE;
10908    }
10909  if (tr_regno < 0)
10910    {
10911      rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
10912
10913      gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
10914      tr_regno = TR0_REG;
10915      tr = gen_rtx_REG (Pmode, tr_regno);
10916      emit_move_insn (tr, r18);
10917    }
10918  else
10919    tr = gen_rtx_REG (Pmode, tr_regno);
10920
10921  emit_jump_insn (gen_return_media_i (tr));
10922  DONE;
10923})
10924
10925(define_insn "shcompact_preserve_incoming_args"
10926  [(set (match_operand:SI 0 "register_operand" "+r")
10927	(unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
10928  "TARGET_SHCOMPACT"
10929  ""
10930  [(set_attr "length" "0")])
10931
10932(define_insn "shcompact_incoming_args"
10933  [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
10934   (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
10935   (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
10936   (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
10937   (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
10938   (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
10939   (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
10940   (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
10941   (set (mem:BLK (reg:SI MACL_REG))
10942	(unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
10943   (use (reg:SI R0_REG))
10944   (clobber (reg:SI R0_REG))
10945   (clobber (reg:SI MACL_REG))
10946   (clobber (reg:SI MACH_REG))
10947   (clobber (reg:SI PR_REG))]
10948  "TARGET_SHCOMPACT"
10949  "jsr	@r0%#"
10950  [(set_attr "needs_delay_slot" "yes")])
10951
10952(define_insn "shmedia_save_restore_regs_compact"
10953  [(set (reg:SI SP_REG)
10954	(plus:SI (reg:SI SP_REG)
10955		 (match_operand:SI 0 "immediate_operand" "i")))
10956   (use (reg:SI R0_REG))
10957   (clobber (reg:SI PR_REG))]
10958  "TARGET_SHCOMPACT
10959   && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
10960       || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
10961  "jsr @r0%#"
10962  [(set_attr "needs_delay_slot" "yes")])
10963
10964(define_expand "prologue"
10965  [(const_int 0)]
10966  ""
10967{
10968  sh_expand_prologue ();
10969  DONE;
10970})
10971
10972(define_expand "epilogue"
10973  [(return)]
10974  ""
10975{
10976  sh_expand_epilogue (false);
10977  if (TARGET_SHMEDIA
10978      || (TARGET_SHCOMPACT
10979	  && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
10980    {
10981      emit_jump_insn (gen_return ());
10982      DONE;
10983    }
10984})
10985
10986(define_expand "eh_return"
10987  [(use (match_operand 0 "register_operand" ""))]
10988  ""
10989{
10990  rtx ra = operands[0];
10991
10992  if (TARGET_SHMEDIA64)
10993    emit_insn (gen_eh_set_ra_di (ra));
10994  else
10995    emit_insn (gen_eh_set_ra_si (ra));
10996
10997  DONE;
10998})
10999
11000;; Clobber the return address on the stack.  We can't expand this
11001;; until we know where it will be put in the stack frame.
11002
11003(define_insn "eh_set_ra_si"
11004  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
11005      UNSPECV_EH_RETURN)
11006   (clobber (match_scratch:SI 1 "=&r"))]
11007  "! TARGET_SHMEDIA64"
11008  "#")
11009
11010(define_insn "eh_set_ra_di"
11011  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
11012      UNSPECV_EH_RETURN)
11013   (clobber (match_scratch:DI 1 "=&r"))]
11014  "TARGET_SHMEDIA64"
11015  "#")
11016
11017(define_split
11018  [(unspec_volatile [(match_operand 0 "register_operand" "")]
11019      UNSPECV_EH_RETURN)
11020   (clobber (match_scratch 1 ""))]
11021  "reload_completed"
11022  [(const_int 0)]
11023{
11024  sh_set_return_address (operands[0], operands[1]);
11025  DONE;
11026})
11027
11028(define_insn "blockage"
11029  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
11030  ""
11031  ""
11032  [(set_attr "length" "0")])
11033
11034;; Define movml instructions for SH2A target.  Currently they are
11035;; used to push and pop all banked registers only.
11036
11037(define_insn "movml_push_banked"
11038  [(set (match_operand:SI 0 "register_operand" "=r")
11039	  (plus (match_dup 0) (const_int -32)))
11040   (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
11041   (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
11042   (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
11043   (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
11044   (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
11045   (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
11046   (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
11047   (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
11048  "TARGET_SH2A && REGNO (operands[0]) == 15"
11049  "movml.l	r7,@-r15"
11050  [(set_attr "in_delay_slot" "no")])
11051
11052(define_insn "movml_pop_banked"
11053  [(set (match_operand:SI 0 "register_operand" "=r")
11054	  (plus (match_dup 0) (const_int 32)))
11055   (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
11056   (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
11057   (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
11058   (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
11059   (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
11060   (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
11061   (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
11062   (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
11063  "TARGET_SH2A && REGNO (operands[0]) == 15"
11064  "movml.l	@r15+,r7"
11065  [(set_attr "in_delay_slot" "no")])
11066
11067;; ------------------------------------------------------------------------
11068;; Scc instructions
11069;; ------------------------------------------------------------------------
11070
11071(define_insn "movt"
11072  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11073	(match_operand:SI 1 "t_reg_operand"))]
11074  "TARGET_SH1"
11075  "movt	%0"
11076  [(set_attr "type" "arith")])
11077
11078(define_insn "movrt"
11079  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11080	(xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11081  "TARGET_SH2A"
11082  "movrt	%0"
11083  [(set_attr "type" "arith")])
11084
11085(define_expand "cstore4_media"
11086  [(set (match_operand:SI 0 "register_operand" "=r")
11087	(match_operator:SI 1 "sh_float_comparison_operator"
11088	 [(match_operand 2 "logical_operand" "")
11089	  (match_operand 3 "cmp_operand" "")]))]
11090  "TARGET_SHMEDIA"
11091{
11092  enum machine_mode mode = GET_MODE (operands[2]);
11093  enum rtx_code code = GET_CODE (operands[1]);
11094  bool invert, swap;
11095  if (mode == VOIDmode)
11096    mode = GET_MODE (operands[3]);
11097  if (operands[2] == const0_rtx)
11098    {
11099      if (code == EQ || code == NE)
11100	operands[2] = operands[3], operands[3] = const0_rtx;
11101    }
11102  else
11103    operands[2] = force_reg (mode, operands[2]);
11104  if (operands[3] != const0_rtx)
11105    operands[3] = force_reg (mode, operands[3]);
11106
11107  switch (code)
11108    {
11109    case GEU:
11110    case GE:
11111      swap = invert = !FLOAT_MODE_P (mode);
11112      break;
11113
11114    case LEU:
11115    case LE:
11116      swap = FLOAT_MODE_P (mode), invert = !swap;
11117      break;
11118
11119    case LTU:
11120    case LT:
11121      swap = true, invert = false;
11122      break;
11123
11124    case GTU:
11125    case GT:
11126    case EQ:
11127    case UNORDERED:
11128      swap = invert = false;
11129      break;
11130
11131    case NE:
11132      swap = invert = true;
11133      break;
11134
11135    default:
11136      gcc_unreachable ();
11137  }
11138
11139  if (swap)
11140    {
11141      rtx tem = operands[2];
11142      operands[2] = operands[3];
11143      operands[3] = tem;
11144      code = swap_condition (code);
11145    }
11146
11147  if (invert)
11148    {
11149      rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
11150      code = reverse_condition (code);
11151      operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11152      emit_insn (gen_cstore4_media (tem, operands[1],
11153				    operands[2], operands[3]));
11154      code = EQ;
11155      operands[2] = tem;
11156      operands[3] = const0_rtx;
11157    }
11158
11159  operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11160})
11161
11162(define_expand "cstoresi4"
11163  [(set (match_operand:SI 0 "register_operand" "=r")
11164	(match_operator:SI 1 "comparison_operator"
11165	 [(match_operand:SI 2 "cmpsi_operand" "")
11166	  (match_operand:SI 3 "arith_operand" "")]))]
11167  "TARGET_SH1 || TARGET_SHMEDIA"
11168{
11169  if (TARGET_SHMEDIA)
11170    {
11171      emit_insn (gen_cstore4_media (operands[0], operands[1],
11172				    operands[2], operands[3]));
11173      DONE;
11174    }
11175
11176   if (sh_expand_t_scc (operands))
11177     DONE;
11178
11179   if (! currently_expanding_to_rtl)
11180     FAIL;
11181   
11182   sh_emit_compare_and_set (operands, SImode);
11183   DONE;
11184})
11185
11186(define_expand "cstoredi4"
11187  [(set (match_operand:SI 0 "register_operand" "=r")
11188	(match_operator:SI 1 "comparison_operator"
11189	 [(match_operand:DI 2 "arith_operand" "")
11190	  (match_operand:DI 3 "arith_operand" "")]))]
11191  "TARGET_SH2 || TARGET_SHMEDIA"
11192{
11193  if (TARGET_SHMEDIA)
11194    {
11195      emit_insn (gen_cstore4_media (operands[0], operands[1],
11196				    operands[2], operands[3]));
11197      DONE;
11198    }
11199
11200   if (sh_expand_t_scc (operands))
11201     DONE;
11202
11203   if (! currently_expanding_to_rtl)
11204     FAIL;
11205   
11206   sh_emit_compare_and_set (operands, DImode);
11207   DONE;
11208})
11209
11210;; Move the complement of the T reg to a reg.
11211;; On SH2A the movrt insn can be used.
11212;; On anything else than SH2A this has to be done with multiple instructions.
11213;; One obvious way would be:
11214;;	cmp/eq	...
11215;;	movt	r0
11216;;	xor	#1,r0
11217;;
11218;; However, this puts pressure on r0 in most cases and thus the following is
11219;; more appealing:
11220;;	cmp/eq	...
11221;;	mov	#-1,temp
11222;;	negc	temp,dest
11223;;
11224;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11225;; becomes a one instruction operation.  Moreover, care must be taken that
11226;; the insn can still be combined with inverted compare and branch code
11227;; around it.  On the other hand, if a function returns the complement of
11228;; a previous comparison result in the T bit, the xor #1,r0 approach might
11229;; lead to better code.
11230(define_expand "movnegt"
11231  [(set (match_operand:SI 0 "arith_reg_dest" "")
11232	(xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11233  "TARGET_SH1"
11234{
11235  if (TARGET_SH2A)
11236    emit_insn (gen_movrt (operands[0], operands[1]));
11237  else
11238    {
11239      rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
11240      emit_insn (gen_movrt_negc (operands[0], operands[1], val));
11241    }
11242  DONE;
11243})
11244
11245(define_insn "movrt_negc"
11246  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11247	(xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11248   (set (reg:SI T_REG) (const_int 1))
11249   (use (match_operand:SI 2 "arith_reg_operand" "r"))]
11250  "TARGET_SH1"
11251  "negc	%2,%0"
11252  [(set_attr "type" "arith")])
11253
11254;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
11255;; pattern can be used by the combine pass.  Using a scratch reg for the
11256;; -1 constant results in slightly better register allocations compared to
11257;; generating a pseudo reg before reload.
11258(define_insn_and_split "*movrt_negc"
11259  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11260	(xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11261   (clobber (match_scratch:SI 2 "=r"))
11262   (clobber (reg:SI T_REG))]
11263  "TARGET_SH1 && ! TARGET_SH2A"
11264  "#"
11265  "&& reload_completed"
11266  [(set (match_dup 2) (const_int -1))
11267   (parallel
11268       [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
11269	(set (reg:SI T_REG) (const_int 1))
11270	(use (match_dup 2))])])
11271
11272;; Store the negated T bit in a reg using r0 and xor.  This one doesn't
11273;; clobber the T bit, which is useful when storing the T bit and the
11274;; negated T bit in parallel.  On SH2A the movrt insn can be used for that.
11275;; Usually we don't want this insn to be matched, except for cases where the
11276;; T bit clobber is really not appreciated.  Hence the extra use on T_REG.
11277(define_insn_and_split "movrt_xor"
11278  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11279	(xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11280   (use (reg:SI T_REG))]
11281  "TARGET_SH1 && !TARGET_SH2A"
11282  "#"
11283  "&& reload_completed"
11284  [(set (match_dup 0) (reg:SI T_REG))
11285   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
11286
11287;; Store the T bit and the negated T bit in two regs in parallel.  There is
11288;; no real insn to do that, but specifying this pattern will give combine
11289;; some opportunities.
11290(define_insn_and_split "*movt_movrt"
11291  [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11292		   (match_operand:SI 1 "negt_reg_operand"))
11293	      (set (match_operand:SI 2 "arith_reg_dest")
11294		   (match_operand:SI 3 "t_reg_operand"))])]
11295  "TARGET_SH1"
11296  "#"
11297  "&& 1"
11298  [(const_int 0)]
11299{
11300  rtx i = TARGET_SH2A
11301	  ? gen_movrt (operands[0], get_t_reg_rtx ())
11302	  : gen_movrt_xor (operands[0], get_t_reg_rtx ());
11303  
11304  emit_insn (i);
11305  emit_insn (gen_movt (operands[2], get_t_reg_rtx ()));
11306  DONE;
11307})
11308
11309(define_insn_and_split "*movt_movrt"
11310  [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11311		   (match_operand:SI 1 "t_reg_operand"))
11312	      (set (match_operand:SI 2 "arith_reg_dest")
11313		   (match_operand:SI 3 "negt_reg_operand"))])]
11314  "TARGET_SH1"
11315  "#"
11316  "&& 1"
11317  [(parallel [(set (match_dup 2) (match_dup 3))
11318	      (set (match_dup 0) (match_dup 1))])])
11319
11320;; Use negc to store the T bit in a MSB of a reg in the following way:
11321;;	T = 1: 0x80000000 -> reg
11322;;	T = 0: 0x7FFFFFFF -> reg
11323;; This works because 0 - 0x80000000 = 0x80000000.
11324(define_insn_and_split "*mov_t_msb_neg"
11325  [(set (match_operand:SI 0 "arith_reg_dest")
11326	(minus:SI (const_int -2147483648)  ;; 0x80000000
11327		  (match_operand 1 "t_reg_operand")))
11328   (clobber (reg:SI T_REG))]
11329  "TARGET_SH1"
11330  "#"
11331  "&& can_create_pseudo_p ()"
11332  [(set (match_dup 2) (const_int -2147483648))
11333   (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
11334				 (reg:SI T_REG)))
11335	      (clobber (reg:SI T_REG))])]
11336{
11337  operands[2] = gen_reg_rtx (SImode);
11338})
11339
11340;; These are essentially the same as above, but with the inverted T bit.
11341;; Combine recognizes the split patterns, but does not take them sometimes
11342;; if the T_REG clobber is specified.  Instead it tries to split out the
11343;; T bit negation.  Since these splits are supposed to be taken only by
11344;; combine, it will see the T_REG clobber of the *mov_t_msb_neg insn, so this
11345;; should be fine.
11346(define_split
11347  [(set (match_operand:SI 0 "arith_reg_dest")
11348	(plus:SI (match_operand 1 "negt_reg_operand")
11349		 (const_int 2147483647)))]  ;; 0x7fffffff
11350  "TARGET_SH1 && can_create_pseudo_p ()"
11351  [(parallel [(set (match_dup 0)
11352		   (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11353	      (clobber (reg:SI T_REG))])])
11354
11355(define_split
11356  [(set (match_operand:SI 0 "arith_reg_dest")
11357	(if_then_else:SI (match_operand 1 "t_reg_operand")
11358			 (const_int 2147483647)  ;; 0x7fffffff
11359			 (const_int -2147483648)))]  ;; 0x80000000
11360  "TARGET_SH1 && can_create_pseudo_p ()"
11361  [(parallel [(set (match_dup 0)
11362		   (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11363	      (clobber (reg:SI T_REG))])])
11364
11365;; The *negnegt pattern helps the combine pass to figure out how to fold 
11366;; an explicit double T bit negation.
11367(define_insn_and_split "*negnegt"
11368  [(set (reg:SI T_REG)
11369	(eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
11370  "TARGET_SH1"
11371  "#"
11372  ""
11373  [(const_int 0)])
11374
11375;; Store T bit as all zeros or ones in a reg.
11376(define_insn "mov_neg_si_t"
11377  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11378	(neg:SI (match_operand 1 "t_reg_operand" "")))]
11379  "TARGET_SH1"
11380  "subc	%0,%0"
11381  [(set_attr "type" "arith")])
11382
11383;; Store negated T bit as all zeros or ones in a reg.
11384;; Use the following sequence:
11385;;	subc	Rn,Rn	! Rn = Rn - Rn - T; T = T
11386;;	not	Rn,Rn	! Rn = 0 - Rn
11387(define_split
11388  [(set (match_operand:SI 0 "arith_reg_dest" "")
11389	(neg:SI (match_operand 1 "negt_reg_operand" "")))]
11390  "TARGET_SH1"
11391  [(set (match_dup 0) (neg:SI (reg:SI T_REG)))
11392   (set (match_dup 0) (not:SI (match_dup 0)))])
11393
11394;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
11395(define_insn_and_split "*movtt"
11396  [(set (reg:SI T_REG)
11397	(eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
11398  "TARGET_SH1"
11399  "#"
11400  ""
11401  [(const_int 0)])
11402
11403;; Invert the T bit.
11404;; On SH2A we can use the nott insn.  On anything else this must be done with
11405;; multiple insns like:
11406;;	movt	Rn
11407;;	tst	Rn,Rn
11408(define_insn_and_split "nott"
11409  [(set (reg:SI T_REG)
11410	(xor:SI (match_operand:SI 0 "t_reg_operand" "") (const_int 1)))]
11411  "TARGET_SH1"
11412{
11413  gcc_assert (TARGET_SH2A);
11414  return "nott";
11415}
11416  "! TARGET_SH2A && can_create_pseudo_p ()"
11417  [(set (match_dup 0) (reg:SI T_REG))
11418   (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
11419{
11420  operands[0] = gen_reg_rtx (SImode);
11421})
11422
11423;; Store T bit as MSB in a reg.
11424;; T = 0: 0x00000000 -> reg
11425;; T = 1: 0x80000000 -> reg
11426(define_insn_and_split "*movt_msb"
11427  [(set (match_operand:SI 0 "arith_reg_dest")
11428	(mult:SI (match_operand:SI 1 "t_reg_operand")
11429		 (const_int -2147483648)))  ;; 0xffffffff80000000
11430   (clobber (reg:SI T_REG))]
11431  "TARGET_SH1"
11432  "#"
11433  "&& 1"
11434  [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
11435
11436;; Store inverted T bit as MSB in a reg.
11437;; T = 0: 0x80000000 -> reg
11438;; T = 1: 0x00000000 -> reg
11439;; On SH2A we can get away without clobbering the T_REG.
11440(define_insn_and_split "*negt_msb"
11441  [(set (match_operand:SI 0 "arith_reg_dest")
11442	(match_operand:SI 1 "negt_reg_shl31_operand"))]
11443  "TARGET_SH2A"
11444  "#"
11445  "&& can_create_pseudo_p ()"
11446  [(const_int 0)]
11447{
11448  rtx tmp = gen_reg_rtx (SImode);
11449  emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
11450  emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
11451  DONE;
11452})
11453
11454(define_insn_and_split "*negt_msb"
11455  [(set (match_operand:SI 0 "arith_reg_dest")
11456	(match_operand:SI 1 "negt_reg_shl31_operand"))
11457   (clobber (reg:SI T_REG))]
11458  "TARGET_SH1 && !TARGET_SH2A"
11459  "#"
11460  "&& can_create_pseudo_p ()"
11461  [(const_int 0)]
11462{
11463  rtx tmp = gen_reg_rtx (SImode);
11464  emit_move_insn (tmp, get_t_reg_rtx ());
11465  emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
11466  emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
11467  DONE;
11468})
11469
11470;; The *cset_zero patterns convert optimizations such as
11471;;	"if (test) x = 0;"
11472;; to
11473;;	"x &= -(test == 0);"
11474;; back to conditional branch sequences if zero-displacement branches
11475;; are enabled.
11476;; FIXME: These patterns can be removed when conditional execution patterns
11477;; are implemented, since ifcvt will not perform these optimizations if
11478;; conditional execution is supported.
11479(define_insn "*cset_zero"
11480  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11481	(and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
11482			 (const_int -1))
11483		(match_operand:SI 2 "arith_reg_operand" "0")))]
11484  "TARGET_SH1 && TARGET_ZDCBRANCH"
11485{
11486  return       "bf	0f"	"\n"
11487	 "	mov	#0,%0"	"\n"
11488	 "0:";
11489}
11490  [(set_attr "type" "arith") ;; poor approximation
11491   (set_attr "length" "4")])
11492
11493(define_insn "*cset_zero"
11494  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11495	(if_then_else:SI (match_operand:SI 1 "t_reg_operand")
11496			 (match_operand:SI 2 "arith_reg_operand" "0")
11497			 (const_int 0)))]
11498  "TARGET_SH1 && TARGET_ZDCBRANCH"
11499{
11500  return       "bt	0f"	"\n"
11501	 "	mov	#0,%0"	"\n"
11502	 "0:";
11503}
11504  [(set_attr "type" "arith") ;; poor approximation
11505   (set_attr "length" "4")])
11506
11507(define_expand "cstoresf4"
11508  [(set (match_operand:SI 0 "register_operand" "=r")
11509	(match_operator:SI 1 "sh_float_comparison_operator"
11510	 [(match_operand:SF 2 "arith_operand" "")
11511	  (match_operand:SF 3 "arith_operand" "")]))]
11512  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11513{
11514  if (TARGET_SHMEDIA)
11515    {
11516      emit_insn (gen_cstore4_media (operands[0], operands[1],
11517				    operands[2], operands[3]));
11518      DONE;
11519    }
11520
11521  if (! currently_expanding_to_rtl)
11522    FAIL;
11523   
11524  sh_emit_compare_and_set (operands, SFmode);
11525  DONE;
11526})
11527
11528(define_expand "cstoredf4"
11529  [(set (match_operand:SI 0 "register_operand" "=r")
11530	(match_operator:SI 1 "sh_float_comparison_operator"
11531	 [(match_operand:DF 2 "arith_operand" "")
11532	  (match_operand:DF 3 "arith_operand" "")]))]
11533  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11534{
11535  if (TARGET_SHMEDIA)
11536    {
11537      emit_insn (gen_cstore4_media (operands[0], operands[1],
11538				    operands[2], operands[3]));
11539      DONE;
11540    }
11541
11542  if (! currently_expanding_to_rtl)
11543    FAIL;
11544   
11545  sh_emit_compare_and_set (operands, DFmode);
11546  DONE;
11547})
11548
11549;; -------------------------------------------------------------------------
11550;; Instructions to cope with inline literal tables
11551;; -------------------------------------------------------------------------
11552
11553;; 2 byte integer in line
11554(define_insn "consttable_2"
11555 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11556		    (match_operand 1 "" "")]
11557		   UNSPECV_CONST2)]
11558 ""
11559{
11560  if (operands[1] != const0_rtx)
11561    assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
11562  return "";
11563}
11564 [(set_attr "length" "2")
11565 (set_attr "in_delay_slot" "no")])
11566
11567;; 4 byte integer in line
11568(define_insn "consttable_4"
11569 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11570		    (match_operand 1 "" "")]
11571		   UNSPECV_CONST4)]
11572 ""
11573{
11574  if (operands[1] != const0_rtx)
11575    {
11576      assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
11577      mark_symbol_refs_as_used (operands[0]);
11578    }
11579  return "";
11580}
11581 [(set_attr "length" "4")
11582  (set_attr "in_delay_slot" "no")])
11583
11584;; 8 byte integer in line
11585(define_insn "consttable_8"
11586 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11587		    (match_operand 1 "" "")]
11588		   UNSPECV_CONST8)]
11589 ""
11590{
11591  if (operands[1] != const0_rtx)
11592    assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
11593  return "";
11594}
11595 [(set_attr "length" "8")
11596  (set_attr "in_delay_slot" "no")])
11597
11598;; 4 byte floating point
11599(define_insn "consttable_sf"
11600 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
11601		    (match_operand 1 "" "")]
11602		   UNSPECV_CONST4)]
11603 ""
11604{
11605  if (operands[1] != const0_rtx)
11606    {
11607      REAL_VALUE_TYPE d;
11608      REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11609      assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
11610    }
11611  return "";
11612}
11613 [(set_attr "length" "4")
11614  (set_attr "in_delay_slot" "no")])
11615
11616;; 8 byte floating point
11617(define_insn "consttable_df"
11618 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
11619		    (match_operand 1 "" "")]
11620		   UNSPECV_CONST8)]
11621 ""
11622{
11623  if (operands[1] != const0_rtx)
11624    {
11625      REAL_VALUE_TYPE d;
11626      REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11627      assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
11628    }
11629  return "";
11630}
11631 [(set_attr "length" "8")
11632  (set_attr "in_delay_slot" "no")])
11633
11634;; Alignment is needed for some constant tables; it may also be added for
11635;; Instructions at the start of loops, or after unconditional branches.
11636;; ??? We would get more accurate lengths if we did instruction
11637;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
11638;; here is too conservative.
11639
11640;; align to a two byte boundary
11641(define_expand "align_2"
11642 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
11643 ""
11644 "")
11645
11646;; Align to a four byte boundary.
11647;; align_4 and align_log are instructions for the starts of loops, or
11648;; after unconditional branches, which may take up extra room.
11649(define_expand "align_4"
11650 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
11651 ""
11652 "")
11653
11654;; Align to a cache line boundary.
11655(define_insn "align_log"
11656 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
11657 ""
11658 ""
11659 [(set_attr "length" "0")
11660  (set_attr "in_delay_slot" "no")])
11661
11662;; Emitted at the end of the literal table, used to emit the
11663;; 32bit branch labels if needed.
11664(define_insn "consttable_end"
11665  [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
11666  ""
11667{
11668  return output_jump_label_table ();
11669}
11670  [(set_attr "in_delay_slot" "no")])
11671
11672;; Emitted at the end of the window in the literal table.
11673(define_insn "consttable_window_end"
11674  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
11675  ""
11676  ""
11677  [(set_attr "length" "0")
11678   (set_attr "in_delay_slot" "no")])
11679
11680;; -------------------------------------------------------------------------
11681;; Misc
11682;; -------------------------------------------------------------------------
11683
11684;; String/block move insn.
11685
11686(define_expand "movmemsi"
11687  [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
11688		   (mem:BLK (match_operand:BLK 1 "" "")))
11689	      (use (match_operand:SI 2 "nonmemory_operand" ""))
11690	      (use (match_operand:SI 3 "immediate_operand" ""))
11691	      (clobber (reg:SI PR_REG))
11692	      (clobber (reg:SI R4_REG))
11693	      (clobber (reg:SI R5_REG))
11694	      (clobber (reg:SI R0_REG))])]
11695  "TARGET_SH1 && ! TARGET_SH5"
11696{
11697  if(expand_block_move (operands))
11698     DONE;
11699  else FAIL;
11700})
11701
11702(define_insn "block_move_real"
11703  [(parallel [(set (mem:BLK (reg:SI R4_REG))
11704		   (mem:BLK (reg:SI R5_REG)))
11705	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
11706	      (clobber (reg:SI PR_REG))
11707	      (clobber (reg:SI R0_REG))])]
11708  "TARGET_SH1 && ! TARGET_HARD_SH4"
11709  "jsr	@%0%#"
11710  [(set_attr "type" "sfunc")
11711   (set_attr "needs_delay_slot" "yes")])
11712
11713(define_insn "block_lump_real"
11714  [(parallel [(set (mem:BLK (reg:SI R4_REG))
11715		   (mem:BLK (reg:SI R5_REG)))
11716	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
11717	      (use (reg:SI R6_REG))
11718	      (clobber (reg:SI PR_REG))
11719	      (clobber (reg:SI T_REG))
11720	      (clobber (reg:SI R4_REG))
11721	      (clobber (reg:SI R5_REG))
11722	      (clobber (reg:SI R6_REG))
11723	      (clobber (reg:SI R0_REG))])]
11724  "TARGET_SH1 && ! TARGET_HARD_SH4"
11725  "jsr	@%0%#"
11726  [(set_attr "type" "sfunc")
11727   (set_attr "needs_delay_slot" "yes")])
11728
11729(define_insn "block_move_real_i4"
11730  [(parallel [(set (mem:BLK (reg:SI R4_REG))
11731		   (mem:BLK (reg:SI R5_REG)))
11732	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
11733	      (clobber (reg:SI PR_REG))
11734	      (clobber (reg:SI R0_REG))
11735	      (clobber (reg:SI R1_REG))
11736	      (clobber (reg:SI R2_REG))])]
11737  "TARGET_HARD_SH4"
11738  "jsr	@%0%#"
11739  [(set_attr "type" "sfunc")
11740   (set_attr "needs_delay_slot" "yes")])
11741
11742(define_insn "block_lump_real_i4"
11743  [(parallel [(set (mem:BLK (reg:SI R4_REG))
11744		   (mem:BLK (reg:SI R5_REG)))
11745	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
11746	      (use (reg:SI R6_REG))
11747	      (clobber (reg:SI PR_REG))
11748	      (clobber (reg:SI T_REG))
11749	      (clobber (reg:SI R4_REG))
11750	      (clobber (reg:SI R5_REG))
11751	      (clobber (reg:SI R6_REG))
11752	      (clobber (reg:SI R0_REG))
11753	      (clobber (reg:SI R1_REG))
11754	      (clobber (reg:SI R2_REG))
11755	      (clobber (reg:SI R3_REG))])]
11756  "TARGET_HARD_SH4"
11757  "jsr	@%0%#"
11758  [(set_attr "type" "sfunc")
11759   (set_attr "needs_delay_slot" "yes")])
11760
11761;; -------------------------------------------------------------------------
11762;; Floating point instructions.
11763;; -------------------------------------------------------------------------
11764
11765;; ??? All patterns should have a type attribute.
11766
11767(define_expand "movpsi"
11768  [(set (match_operand:PSI 0 "register_operand" "")
11769	(match_operand:PSI 1 "general_movsrc_operand" ""))]
11770  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11771  "")
11772
11773;; The c / m alternative is a fake to guide reload to load directly into
11774;; fpscr, since reload doesn't know how to use post-increment.
11775;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
11776;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
11777;; predicate after reload.
11778;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
11779;; like a mac -> gpr move.
11780(define_insn "fpu_switch"
11781  [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
11782	(match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
11783  "TARGET_SH2E
11784   && (! reload_completed
11785       || true_regnum (operands[0]) != FPSCR_REG
11786       || !MEM_P (operands[1])
11787       || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
11788  "@
11789	! precision stays the same
11790	lds.l	%1,fpscr
11791	mov.l	%1,%0
11792	#
11793	lds	%1,fpscr
11794	mov	%1,%0
11795	mov.l	%1,%0
11796	sts	fpscr,%0
11797	sts.l	fpscr,%0"
11798  [(set_attr "length" "0,2,2,4,2,2,2,2,2")
11799   (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,
11800		     mac_gp,fstore")])
11801
11802(define_peephole2
11803  [(set (reg:PSI FPSCR_REG)
11804	(mem:PSI (match_operand:SI 0 "register_operand" "")))]
11805  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
11806  [(const_int 0)]
11807{
11808  rtx fpscr, mem, new_insn;
11809
11810  fpscr = SET_DEST (PATTERN (curr_insn));
11811  mem = SET_SRC (PATTERN (curr_insn));
11812  mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
11813
11814  new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
11815  add_reg_note (new_insn, REG_INC, operands[0]);
11816  DONE;
11817})
11818
11819(define_split
11820  [(set (reg:PSI FPSCR_REG)
11821	(mem:PSI (match_operand:SI 0 "register_operand" "")))]
11822  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
11823   && (flag_peephole2 ? epilogue_completed : reload_completed)"
11824  [(const_int 0)]
11825{
11826  rtx fpscr, mem, new_insn;
11827
11828  fpscr = SET_DEST (PATTERN (curr_insn));
11829  mem = SET_SRC (PATTERN (curr_insn));
11830  mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
11831
11832  new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
11833  add_reg_note (new_insn, REG_INC, operands[0]);
11834
11835  if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
11836    emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
11837  DONE;
11838})
11839
11840;; ??? This uses the fp unit, but has no type indicating that.
11841;; If we did that, this would either give a bogus latency or introduce
11842;; a bogus FIFO constraint.
11843;; Since this insn is currently only used for prologues/epilogues,
11844;; it is probably best to claim no function unit, which matches the
11845;; current setting.
11846(define_insn "toggle_sz"
11847  [(set (reg:PSI FPSCR_REG)
11848	(xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
11849  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11850  "fschg"
11851  [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
11852
11853;; There's no way we can use it today, since optimize mode switching
11854;; doesn't enable us to know from which mode we're switching to the
11855;; mode it requests, to tell whether we can use a relative mode switch
11856;; (like toggle_pr) or an absolute switch (like loading fpscr from
11857;; memory).
11858(define_insn "toggle_pr"
11859  [(set (reg:PSI FPSCR_REG)
11860	(xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
11861  "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
11862  "fpchg"
11863  [(set_attr "type" "fpscr_toggle")])
11864
11865(define_expand "addsf3"
11866  [(set (match_operand:SF 0 "arith_reg_operand" "")
11867	(plus:SF (match_operand:SF 1 "arith_reg_operand" "")
11868		 (match_operand:SF 2 "arith_reg_operand" "")))]
11869  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11870{
11871  if (TARGET_SH2E)
11872    {
11873      expand_sf_binop (&gen_addsf3_i, operands);
11874      DONE;
11875    }
11876})
11877
11878(define_insn "*addsf3_media"
11879  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11880	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
11881		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
11882  "TARGET_SHMEDIA_FPU"
11883  "fadd.s	%1, %2, %0"
11884  [(set_attr "type" "fparith_media")])
11885
11886(define_insn_and_split "unary_sf_op"
11887  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11888	(vec_select:V2SF
11889	 (vec_concat:V2SF
11890	  (vec_select:SF
11891	   (match_dup 0)
11892	   (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
11893	  (match_operator:SF 2 "unary_float_operator"
11894	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11895			    (parallel [(match_operand 4
11896					"const_int_operand" "n")]))]))
11897	 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
11898  "TARGET_SHMEDIA_FPU"
11899  "#"
11900  "TARGET_SHMEDIA_FPU && reload_completed"
11901  [(set (match_dup 5) (match_dup 6))]
11902{
11903  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11904  rtx op1 = gen_rtx_REG (SFmode,
11905			 (true_regnum (operands[1])
11906			  + (INTVAL (operands[4]) ^ endian)));
11907
11908  operands[7] = gen_rtx_REG (SFmode,
11909			     (true_regnum (operands[0])
11910			      + (INTVAL (operands[3]) ^ endian)));
11911  operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
11912}
11913  [(set_attr "type" "fparith_media")])
11914
11915(define_insn_and_split "binary_sf_op0"
11916  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11917	(vec_concat:V2SF
11918	  (match_operator:SF 3 "binary_float_operator"
11919	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11920			    (parallel [(const_int 0)]))
11921	     (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
11922			    (parallel [(const_int 0)]))])
11923	  (vec_select:SF
11924	   (match_dup 0)
11925	   (parallel [(const_int 1)]))))]
11926  "TARGET_SHMEDIA_FPU"
11927  "#"
11928  "&& reload_completed"
11929  [(set (match_dup 4) (match_dup 5))]
11930{
11931  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11932  rtx op1 = gen_rtx_REG (SFmode,
11933			 true_regnum (operands[1]) + endian);
11934  rtx op2 = gen_rtx_REG (SFmode,
11935			 true_regnum (operands[2]) + endian);
11936
11937  operands[4] = gen_rtx_REG (SFmode,
11938			     true_regnum (operands[0]) + endian);
11939  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
11940}
11941  [(set_attr "type" "fparith_media")])
11942
11943(define_insn_and_split "binary_sf_op1"
11944  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11945	(vec_concat:V2SF
11946	  (vec_select:SF
11947	   (match_dup 0)
11948	   (parallel [(const_int 0)]))
11949	  (match_operator:SF 3 "binary_float_operator"
11950	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11951			    (parallel [(const_int 1)]))
11952	     (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
11953			    (parallel [(const_int 1)]))])))]
11954  "TARGET_SHMEDIA_FPU"
11955  "#"
11956  "&& reload_completed"
11957  [(set (match_dup 4) (match_dup 5))]
11958{
11959  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11960  rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
11961  rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
11962
11963  operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
11964  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
11965}
11966  [(set_attr "type" "fparith_media")])
11967
11968(define_insn "addsf3_i"
11969  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11970	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
11971		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
11972   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
11973  "TARGET_SH2E"
11974  "fadd	%2,%0"
11975  [(set_attr "type" "fp")
11976   (set_attr "fp_mode" "single")])
11977
11978(define_expand "subsf3"
11979  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
11980	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
11981		  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
11982  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11983{
11984  if (TARGET_SH2E)
11985    {
11986      expand_sf_binop (&gen_subsf3_i, operands);
11987      DONE;
11988    }
11989})
11990
11991(define_insn "*subsf3_media"
11992  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11993	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
11994		  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
11995  "TARGET_SHMEDIA_FPU"
11996  "fsub.s	%1, %2, %0"
11997  [(set_attr "type" "fparith_media")])
11998
11999(define_insn "subsf3_i"
12000  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12001	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12002		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12003   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12004  "TARGET_SH2E"
12005  "fsub	%2,%0"
12006  [(set_attr "type" "fp")
12007   (set_attr "fp_mode" "single")])
12008
12009(define_expand "mulsf3"
12010  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12011	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12012		 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
12013  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12014{
12015  if (TARGET_SH2E)
12016    {
12017      emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2],
12018		 get_fpscr_rtx ()));
12019      DONE;
12020    }
12021})
12022
12023(define_insn "*mulsf3_media"
12024  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12025	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12026		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12027  "TARGET_SHMEDIA_FPU"
12028  "fmul.s	%1, %2, %0"
12029  [(set_attr "type" "fparith_media")])
12030
12031(define_insn "mulsf3_i"
12032  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12033	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12034		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
12035   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12036  "TARGET_SH2E"
12037  "fmul	%2,%0"
12038  [(set_attr "type" "fp")
12039   (set_attr "fp_mode" "single")])
12040
12041;; FMA (fused multiply-add) patterns
12042(define_expand "fmasf4"
12043  [(set (match_operand:SF 0 "fp_arith_reg_operand")
12044	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand")
12045		(match_operand:SF 2 "fp_arith_reg_operand")
12046		(match_operand:SF 3 "fp_arith_reg_operand")))]
12047  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12048{
12049  if (TARGET_SH2E)
12050    {
12051      emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
12052				  operands[3], get_fpscr_rtx ()));
12053      DONE;
12054    }
12055})
12056
12057(define_insn "fmasf4_i"
12058  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12059	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
12060		(match_operand:SF 2 "fp_arith_reg_operand" "f")
12061		(match_operand:SF 3 "fp_arith_reg_operand" "0")))
12062   (use (match_operand:PSI 4 "fpscr_operand" "c"))]
12063  "TARGET_SH2E"
12064  "fmac	%1,%2,%0"
12065  [(set_attr "type" "fp")
12066   (set_attr "fp_mode" "single")])
12067
12068(define_insn "fmasf4_media"
12069  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12070	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12071		(match_operand:SF 2 "fp_arith_reg_operand" "f")
12072		(match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12073  "TARGET_SHMEDIA_FPU"
12074  "fmac.s %1, %2, %0"
12075  [(set_attr "type" "fparith_media")])
12076
12077;; For some cases such as 'a * b + a' the FMA pattern is not generated by
12078;; previous transformations.  If FMA is generally allowed, let the combine
12079;; pass utilize it.
12080(define_insn_and_split "*fmasf4"
12081  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12082	(plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
12083			  (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12084		 (match_operand:SF 3 "arith_reg_operand" "0")))
12085   (use (match_operand:PSI 4 "fpscr_operand"))]
12086  "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
12087  "fmac	%1,%2,%0"
12088  "&& can_create_pseudo_p ()"
12089  [(parallel [(set (match_dup 0)
12090		   (fma:SF (match_dup 1) (match_dup 2) (match_dup 3)))
12091	      (use (match_dup 4))])]
12092{
12093  /* Change 'b * a + a' into 'a * b + a'.
12094     This is better for register allocation.  */
12095  if (REGNO (operands[2]) == REGNO (operands[3]))
12096    {
12097      rtx tmp = operands[1];
12098      operands[1] = operands[2];
12099      operands[2] = tmp;
12100    }
12101}
12102  [(set_attr "type" "fp")
12103   (set_attr "fp_mode" "single")])
12104
12105(define_insn "*fmasf4_media"
12106  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12107	(plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12108			  (match_operand:SF 2 "fp_arith_reg_operand" "f"))
12109		 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12110  "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF"
12111  "fmac.s %1, %2, %0"
12112  [(set_attr "type" "fparith_media")])
12113
12114(define_expand "divsf3"
12115  [(set (match_operand:SF 0 "arith_reg_operand" "")
12116	(div:SF (match_operand:SF 1 "arith_reg_operand" "")
12117		(match_operand:SF 2 "arith_reg_operand" "")))]
12118  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12119{
12120  if (TARGET_SH2E)
12121    {
12122      expand_sf_binop (&gen_divsf3_i, operands);
12123      DONE;
12124    }
12125})
12126
12127(define_insn "*divsf3_media"
12128  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12129	(div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12130		(match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12131  "TARGET_SHMEDIA_FPU"
12132  "fdiv.s	%1, %2, %0"
12133  [(set_attr "type" "fdiv_media")])
12134
12135(define_insn "divsf3_i"
12136  [(set (match_operand:SF 0 "arith_reg_dest" "=f")
12137	(div:SF (match_operand:SF 1 "arith_reg_operand" "0")
12138		 (match_operand:SF 2 "arith_reg_operand" "f")))
12139   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12140  "TARGET_SH2E"
12141  "fdiv	%2,%0"
12142  [(set_attr "type" "fdiv")
12143   (set_attr "fp_mode" "single")])
12144
12145(define_insn "floatdisf2"
12146  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12147	(float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12148  "TARGET_SHMEDIA_FPU"
12149  "float.qs %1, %0"
12150  [(set_attr "type" "fpconv_media")])
12151
12152(define_expand "floatsisf2"
12153  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12154	(float:SF (match_operand:SI 1 "fpul_operand" "")))]
12155  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12156{
12157  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12158    {
12159      emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1],
12160				       get_fpscr_rtx ()));
12161      DONE;
12162    }
12163})
12164
12165(define_insn "*floatsisf2_media"
12166  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12167	(float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12168  "TARGET_SHMEDIA_FPU"
12169  "float.ls	%1, %0"
12170  [(set_attr "type" "fpconv_media")])
12171
12172(define_insn "floatsisf2_i4"
12173  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12174	(float:SF (match_operand:SI 1 "fpul_operand" "y")))
12175   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12176  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12177  "float	%1,%0"
12178  [(set_attr "type" "fp")
12179   (set_attr "fp_mode" "single")])
12180
12181(define_insn "*floatsisf2_ie"
12182  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12183	(float:SF (match_operand:SI 1 "fpul_operand" "y")))]
12184  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12185  "float	%1,%0"
12186  [(set_attr "type" "fp")])
12187
12188(define_insn "fix_truncsfdi2"
12189  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12190	(fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12191  "TARGET_SHMEDIA_FPU"
12192  "ftrc.sq %1, %0"
12193  [(set_attr "type" "fpconv_media")])
12194
12195(define_expand "fix_truncsfsi2"
12196  [(set (match_operand:SI 0 "fpul_operand" "=y")
12197	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12198  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12199{
12200  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
12201    {
12202      emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1],
12203					   get_fpscr_rtx ()));
12204      DONE;
12205    }
12206})
12207
12208(define_insn "*fix_truncsfsi2_media"
12209  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12210	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12211  "TARGET_SHMEDIA_FPU"
12212  "ftrc.sl	%1, %0"
12213  [(set_attr "type" "fpconv_media")])
12214
12215(define_insn "fix_truncsfsi2_i4"
12216  [(set (match_operand:SI 0 "fpul_operand" "=y")
12217	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12218   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12219  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12220  "ftrc	%1,%0"
12221  [(set_attr "type" "ftrc_s")
12222   (set_attr "fp_mode" "single")])
12223
12224;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
12225;; fix_truncsfsi2_i4.
12226;; (define_insn "fix_truncsfsi2_i4_2"
12227;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12228;;	(fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12229;;   (use (reg:PSI FPSCR_REG))
12230;;   (clobber (reg:SI FPUL_REG))]
12231;;  "TARGET_SH4"
12232;;  "#"
12233;;  [(set_attr "length" "4")
12234;;   (set_attr "fp_mode" "single")])
12235
12236;;(define_split
12237;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12238;;	(fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12239;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
12240;;   (clobber (reg:SI FPUL_REG))]
12241;;  "TARGET_SH4"
12242;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
12243;;	      (use (match_dup 2))])
12244;;   (set (match_dup 0) (reg:SI FPUL_REG))])
12245
12246(define_insn "*fixsfsi"
12247  [(set (match_operand:SI 0 "fpul_operand" "=y")
12248	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12249  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12250  "ftrc	%1,%0"
12251  [(set_attr "type" "fp")])
12252
12253(define_insn "cmpgtsf_t"
12254  [(set (reg:SI T_REG)
12255	(gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12256	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12257  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12258  "fcmp/gt	%1,%0"
12259  [(set_attr "type" "fp_cmp")
12260   (set_attr "fp_mode" "single")])
12261
12262(define_insn "cmpeqsf_t"
12263  [(set (reg:SI T_REG)
12264	(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12265	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12266  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12267  "fcmp/eq	%1,%0"
12268  [(set_attr "type" "fp_cmp")
12269   (set_attr "fp_mode" "single")])
12270
12271(define_insn "ieee_ccmpeqsf_t"
12272  [(set (reg:SI T_REG)
12273	(ior:SI (reg:SI T_REG)
12274		(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12275		       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
12276  "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12277{
12278  return output_ieee_ccmpeq (insn, operands);
12279}
12280  [(set_attr "length" "4")])
12281
12282
12283(define_insn "cmpgtsf_t_i4"
12284  [(set (reg:SI T_REG)
12285	(gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12286	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12287   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12288  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12289  "fcmp/gt	%1,%0"
12290  [(set_attr "type" "fp_cmp")
12291   (set_attr "fp_mode" "single")])
12292
12293(define_insn "cmpeqsf_t_i4"
12294  [(set (reg:SI T_REG)
12295	(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12296	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12297   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12298  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12299  "fcmp/eq	%1,%0"
12300  [(set_attr "type" "fp_cmp")
12301   (set_attr "fp_mode" "single")])
12302
12303(define_insn "*ieee_ccmpeqsf_t_4"
12304  [(set (reg:SI T_REG)
12305	(ior:SI (reg:SI T_REG)
12306		(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12307		       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
12308   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12309  "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12310{
12311  return output_ieee_ccmpeq (insn, operands);
12312}
12313  [(set_attr "length" "4")
12314   (set_attr "fp_mode" "single")])
12315
12316(define_insn "cmpeqsf_media"
12317  [(set (match_operand:SI 0 "register_operand" "=r")
12318	(eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12319	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12320  "TARGET_SHMEDIA_FPU"
12321  "fcmpeq.s	%1, %2, %0"
12322  [(set_attr "type" "fcmp_media")])
12323
12324(define_insn "cmpgtsf_media"
12325  [(set (match_operand:SI 0 "register_operand" "=r")
12326	(gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12327	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12328  "TARGET_SHMEDIA_FPU"
12329  "fcmpgt.s	%1, %2, %0"
12330  [(set_attr "type" "fcmp_media")])
12331
12332(define_insn "cmpgesf_media"
12333  [(set (match_operand:SI 0 "register_operand" "=r")
12334	(ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12335	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12336  "TARGET_SHMEDIA_FPU"
12337  "fcmpge.s	%1, %2, %0"
12338  [(set_attr "type" "fcmp_media")])
12339
12340(define_insn "cmpunsf_media"
12341  [(set (match_operand:SI 0 "register_operand" "=r")
12342	(unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12343		      (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12344  "TARGET_SHMEDIA_FPU"
12345  "fcmpun.s	%1, %2, %0"
12346  [(set_attr "type" "fcmp_media")])
12347
12348(define_expand "cbranchsf4"
12349  [(set (pc)
12350	(if_then_else (match_operator 0 "sh_float_comparison_operator"
12351		       [(match_operand:SF 1 "arith_operand" "")
12352			(match_operand:SF 2 "arith_operand" "")])
12353		      (match_operand 3 "" "")
12354		      (pc)))]
12355  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12356{
12357  if (TARGET_SHMEDIA)
12358    emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12359					  operands[3]));
12360  else
12361    sh_emit_compare_and_branch (operands, SFmode);
12362  DONE;
12363})
12364
12365(define_expand "negsf2"
12366  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12367	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12368  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12369{
12370  if (TARGET_SH2E)
12371    {
12372      expand_sf_unop (&gen_negsf2_i, operands);
12373      DONE;
12374    }
12375})
12376
12377(define_insn "*negsf2_media"
12378  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12379	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12380  "TARGET_SHMEDIA_FPU"
12381  "fneg.s	%1, %0"
12382  [(set_attr "type" "fmove_media")])
12383
12384(define_insn "negsf2_i"
12385  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12386	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12387   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12388  "TARGET_SH2E"
12389  "fneg	%0"
12390  [(set_attr "type" "fmove")
12391   (set_attr "fp_mode" "single")])
12392
12393(define_expand "sqrtsf2"
12394  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12395	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12396  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
12397{
12398  if (TARGET_SH3E)
12399    {
12400      expand_sf_unop (&gen_sqrtsf2_i, operands);
12401      DONE;
12402    }
12403})
12404
12405(define_insn "*sqrtsf2_media"
12406  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12407	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12408  "TARGET_SHMEDIA_FPU"
12409  "fsqrt.s	%1, %0"
12410  [(set_attr "type" "fdiv_media")])
12411
12412(define_insn "sqrtsf2_i"
12413  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12414	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12415   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12416  "TARGET_SH3E"
12417  "fsqrt	%0"
12418  [(set_attr "type" "fdiv")
12419   (set_attr "fp_mode" "single")])
12420
12421(define_insn "rsqrtsf2"
12422  [(set (match_operand:SF 0 "register_operand" "=f")
12423	(div:SF (match_operand:SF 1 "immediate_operand" "i")
12424		(sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
12425   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12426  "TARGET_FPU_ANY && TARGET_FSRRA
12427   && operands[1] == CONST1_RTX (SFmode)"
12428  "fsrra	%0"
12429  [(set_attr "type" "fsrra")
12430   (set_attr "fp_mode" "single")])
12431
12432;; When the sincos pattern is defined, the builtin functions sin and cos
12433;; will be expanded to the sincos pattern and one of the output values will
12434;; remain unused.
12435(define_expand "sincossf3"
12436  [(set (match_operand:SF 0 "nonimmediate_operand")
12437	(unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
12438   (set (match_operand:SF 1 "nonimmediate_operand")
12439	(unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
12440  "TARGET_FPU_ANY && TARGET_FSCA"
12441{
12442  rtx scaled = gen_reg_rtx (SFmode);
12443  rtx truncated = gen_reg_rtx (SImode);
12444  rtx fsca = gen_reg_rtx (V2SFmode);
12445  rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
12446
12447  emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
12448  emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
12449  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
12450			  get_fpscr_rtx ()));
12451
12452  emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
12453  emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
12454  DONE;
12455})
12456
12457(define_insn_and_split "fsca"
12458  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12459	(vec_concat:V2SF
12460	 (unspec:SF [(mult:SF
12461		      (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
12462		      (match_operand:SF 2 "fsca_scale_factor" "i"))
12463		    ] UNSPEC_FSINA)
12464	 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
12465		    ] UNSPEC_FCOSA)))
12466   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12467  "TARGET_FPU_ANY && TARGET_FSCA"
12468  "fsca	fpul,%d0"
12469  "&& !fpul_operand (operands[1], SImode)"
12470  [(const_int 0)]
12471{
12472  /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
12473     to a simple reg, otherwise reload will have trouble reloading the
12474     pseudo into fpul.  */
12475  rtx x = XEXP (operands[1], 0);
12476  while (x != NULL_RTX && !fpul_operand (x, SImode))
12477    {
12478      gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
12479      x = XEXP (x, 0);
12480    }
12481
12482  gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
12483  emit_insn (gen_fsca (operands[0], x, operands[2], operands[3]));
12484  DONE;
12485}
12486  [(set_attr "type" "fsca")
12487   (set_attr "fp_mode" "single")])
12488
12489(define_expand "abssf2"
12490  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12491	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12492  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12493{
12494  if (TARGET_SH2E)
12495    {
12496      expand_sf_unop (&gen_abssf2_i, operands);
12497      DONE;
12498    }
12499})
12500
12501(define_insn "*abssf2_media"
12502  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12503	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12504  "TARGET_SHMEDIA_FPU"
12505  "fabs.s	%1, %0"
12506  [(set_attr "type" "fmove_media")])
12507
12508(define_insn "abssf2_i"
12509  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12510	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12511   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12512  "TARGET_SH2E"
12513  "fabs	%0"
12514  [(set_attr "type" "fmove")
12515   (set_attr "fp_mode" "single")])
12516
12517(define_expand "adddf3"
12518  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12519	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12520		 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12521  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12522{
12523  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12524    {
12525      expand_df_binop (&gen_adddf3_i, operands);
12526      DONE;
12527    }
12528})
12529
12530(define_insn "*adddf3_media"
12531  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12532	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12533		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12534  "TARGET_SHMEDIA_FPU"
12535  "fadd.d	%1, %2, %0"
12536  [(set_attr "type" "dfparith_media")])
12537
12538(define_insn "adddf3_i"
12539  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12540	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12541		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12542   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12543  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12544  "fadd	%2,%0"
12545  [(set_attr "type" "dfp_arith")
12546   (set_attr "fp_mode" "double")])
12547
12548(define_expand "subdf3"
12549  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12550	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12551		  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12552  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12553{
12554  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12555    {
12556      expand_df_binop (&gen_subdf3_i, operands);
12557      DONE;
12558    }
12559})
12560
12561(define_insn "*subdf3_media"
12562  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12563	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12564		  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12565  "TARGET_SHMEDIA_FPU"
12566  "fsub.d	%1, %2, %0"
12567  [(set_attr "type" "dfparith_media")])
12568
12569(define_insn "subdf3_i"
12570  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12571	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12572		  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12573   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12574  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12575  "fsub	%2,%0"
12576  [(set_attr "type" "dfp_arith")
12577   (set_attr "fp_mode" "double")])
12578
12579(define_expand "muldf3"
12580  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12581	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12582		 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12583  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12584{
12585  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12586    {
12587      expand_df_binop (&gen_muldf3_i, operands);
12588      DONE;
12589    }
12590})
12591
12592(define_insn "*muldf3_media"
12593  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12594	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12595		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12596  "TARGET_SHMEDIA_FPU"
12597  "fmul.d	%1, %2, %0"
12598  [(set_attr "type" "dfmul_media")])
12599
12600(define_insn "muldf3_i"
12601  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12602	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12603		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12604   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12605  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12606  "fmul	%2,%0"
12607  [(set_attr "type" "dfp_mul")
12608   (set_attr "fp_mode" "double")])
12609
12610(define_expand "divdf3"
12611  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12612	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12613		(match_operand:DF 2 "fp_arith_reg_operand" "")))]
12614  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12615{
12616  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12617    {
12618      expand_df_binop (&gen_divdf3_i, operands);
12619      DONE;
12620    }
12621})
12622
12623(define_insn "*divdf3_media"
12624  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12625	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12626		(match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12627  "TARGET_SHMEDIA_FPU"
12628  "fdiv.d	%1, %2, %0"
12629  [(set_attr "type" "dfdiv_media")])
12630
12631(define_insn "divdf3_i"
12632  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12633	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12634		(match_operand:DF 2 "fp_arith_reg_operand" "f")))
12635   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12636  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12637  "fdiv	%2,%0"
12638  [(set_attr "type" "dfdiv")
12639   (set_attr "fp_mode" "double")])
12640
12641(define_insn "floatdidf2"
12642  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12643	(float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12644  "TARGET_SHMEDIA_FPU"
12645  "float.qd	%1, %0"
12646  [(set_attr "type" "dfpconv_media")])
12647
12648(define_expand "floatsidf2"
12649  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12650	(float:DF (match_operand:SI 1 "fpul_operand" "")))]
12651  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12652{
12653  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12654    {
12655      emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
12656				      get_fpscr_rtx ()));
12657      DONE;
12658    }
12659})
12660
12661(define_insn "*floatsidf2_media"
12662  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12663	(float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12664  "TARGET_SHMEDIA_FPU"
12665  "float.ld	%1, %0"
12666  [(set_attr "type" "dfpconv_media")])
12667
12668(define_insn "floatsidf2_i"
12669  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12670	(float:DF (match_operand:SI 1 "fpul_operand" "y")))
12671   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12672  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12673  "float	%1,%0"
12674  [(set_attr "type" "dfp_conv")
12675   (set_attr "fp_mode" "double")])
12676
12677(define_insn "fix_truncdfdi2"
12678  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12679	(fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12680  "TARGET_SHMEDIA_FPU"
12681  "ftrc.dq	%1, %0"
12682  [(set_attr "type" "dfpconv_media")])
12683
12684(define_expand "fix_truncdfsi2"
12685  [(set (match_operand:SI 0 "fpul_operand" "")
12686	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
12687  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12688{
12689  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12690    {
12691      emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
12692					  get_fpscr_rtx ()));
12693      DONE;
12694    }
12695})
12696
12697(define_insn "*fix_truncdfsi2_media"
12698  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12699	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12700  "TARGET_SHMEDIA_FPU"
12701  "ftrc.dl	%1, %0"
12702  [(set_attr "type" "dfpconv_media")])
12703
12704(define_insn "fix_truncdfsi2_i"
12705  [(set (match_operand:SI 0 "fpul_operand" "=y")
12706	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
12707   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12708  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12709  "ftrc	%1,%0"
12710  [(set_attr "type" "dfp_conv")
12711   (set_attr "dfp_comp" "no")
12712   (set_attr "fp_mode" "double")])
12713
12714;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
12715;; fix_truncdfsi2_i.
12716;; (define_insn "fix_truncdfsi2_i4"
12717;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12718;; 	(fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
12719;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
12720;;    (clobber (reg:SI FPUL_REG))]
12721;;   "TARGET_SH4"
12722;;   "#"
12723;;   [(set_attr "length" "4")
12724;;    (set_attr "fp_mode" "double")])
12725;;
12726;; (define_split
12727;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12728;; 	(fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
12729;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
12730;;    (clobber (reg:SI FPUL_REG))]
12731;;   "TARGET_SH4"
12732;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
12733;; 	      (use (match_dup 2))])
12734;;    (set (match_dup 0) (reg:SI FPUL_REG))])
12735
12736(define_insn "cmpgtdf_t"
12737  [(set (reg:SI T_REG)
12738	(gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
12739	       (match_operand:DF 1 "arith_reg_operand" "f")))
12740   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12741  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12742  "fcmp/gt	%1,%0"
12743  [(set_attr "type" "dfp_cmp")
12744   (set_attr "fp_mode" "double")])
12745
12746(define_insn "cmpeqdf_t"
12747  [(set (reg:SI T_REG)
12748	(eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
12749	       (match_operand:DF 1 "arith_reg_operand" "f")))
12750   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12751  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12752  "fcmp/eq	%1,%0"
12753  [(set_attr "type" "dfp_cmp")
12754   (set_attr "fp_mode" "double")])
12755
12756(define_insn "*ieee_ccmpeqdf_t"
12757  [(set (reg:SI T_REG)
12758	(ior:SI (reg:SI T_REG)
12759		(eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
12760		       (match_operand:DF 1 "arith_reg_operand" "f"))))
12761   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12762  "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12763{
12764  return output_ieee_ccmpeq (insn, operands);
12765}
12766  [(set_attr "length" "4")
12767   (set_attr "fp_mode" "double")])
12768
12769(define_insn "cmpeqdf_media"
12770  [(set (match_operand:SI 0 "register_operand" "=r")
12771	(eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12772	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12773  "TARGET_SHMEDIA_FPU"
12774  "fcmpeq.d	%1,%2,%0"
12775  [(set_attr "type" "fcmp_media")])
12776
12777(define_insn "cmpgtdf_media"
12778  [(set (match_operand:SI 0 "register_operand" "=r")
12779	(gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12780	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12781  "TARGET_SHMEDIA_FPU"
12782  "fcmpgt.d	%1,%2,%0"
12783  [(set_attr "type" "fcmp_media")])
12784
12785(define_insn "cmpgedf_media"
12786  [(set (match_operand:SI 0 "register_operand" "=r")
12787	(ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12788	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12789  "TARGET_SHMEDIA_FPU"
12790  "fcmpge.d	%1,%2,%0"
12791  [(set_attr "type" "fcmp_media")])
12792
12793(define_insn "cmpundf_media"
12794  [(set (match_operand:SI 0 "register_operand" "=r")
12795	(unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12796		      (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12797  "TARGET_SHMEDIA_FPU"
12798  "fcmpun.d	%1,%2,%0"
12799  [(set_attr "type" "fcmp_media")])
12800
12801(define_expand "cbranchdf4"
12802  [(set (pc)
12803	(if_then_else (match_operator 0 "sh_float_comparison_operator"
12804		       [(match_operand:DF 1 "arith_operand" "")
12805			(match_operand:DF 2 "arith_operand" "")])
12806		      (match_operand 3 "" "")
12807		      (pc)))]
12808  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12809{
12810  if (TARGET_SHMEDIA)
12811    emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12812					  operands[3]));
12813  else
12814    sh_emit_compare_and_branch (operands, DFmode);
12815  DONE;
12816})
12817
12818
12819(define_expand "negdf2"
12820  [(set (match_operand:DF 0 "arith_reg_operand" "")
12821	(neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
12822  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12823{
12824  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12825    {
12826      expand_df_unop (&gen_negdf2_i, operands);
12827      DONE;
12828    }
12829})
12830
12831(define_insn "*negdf2_media"
12832  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12833	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12834  "TARGET_SHMEDIA_FPU"
12835  "fneg.d	%1, %0"
12836  [(set_attr "type" "fmove_media")])
12837
12838(define_insn "negdf2_i"
12839  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12840	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
12841   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12842  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12843  "fneg	%0"
12844  [(set_attr "type" "fmove")
12845   (set_attr "fp_mode" "double")])
12846
12847(define_expand "sqrtdf2"
12848  [(set (match_operand:DF 0 "arith_reg_operand" "")
12849	(sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
12850  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12851{
12852  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12853    {
12854      expand_df_unop (&gen_sqrtdf2_i, operands);
12855      DONE;
12856    }
12857})
12858
12859(define_insn "*sqrtdf2_media"
12860  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12861	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12862  "TARGET_SHMEDIA_FPU"
12863  "fsqrt.d	%1, %0"
12864  [(set_attr "type" "dfdiv_media")])
12865
12866(define_insn "sqrtdf2_i"
12867  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12868	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
12869   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12870  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12871  "fsqrt	%0"
12872  [(set_attr "type" "dfdiv")
12873   (set_attr "fp_mode" "double")])
12874
12875(define_expand "absdf2"
12876  [(set (match_operand:DF 0 "arith_reg_operand" "")
12877	(abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
12878  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12879{
12880  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12881    {
12882      expand_df_unop (&gen_absdf2_i, operands);
12883      DONE;
12884    }
12885})
12886
12887(define_insn "*absdf2_media"
12888  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12889	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12890  "TARGET_SHMEDIA_FPU"
12891  "fabs.d	%1, %0"
12892  [(set_attr "type" "fmove_media")])
12893
12894(define_insn "absdf2_i"
12895  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12896	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
12897   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12898  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12899  "fabs	%0"
12900  [(set_attr "type" "fmove")
12901   (set_attr "fp_mode" "double")])
12902
12903(define_expand "extendsfdf2"
12904  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12905	(float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
12906  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12907{
12908  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12909    {
12910      emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
12911					get_fpscr_rtx ()));
12912      DONE;
12913    }
12914})
12915
12916(define_insn "*extendsfdf2_media"
12917  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12918	(float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12919  "TARGET_SHMEDIA_FPU"
12920  "fcnv.sd	%1, %0"
12921  [(set_attr "type" "dfpconv_media")])
12922
12923(define_insn "extendsfdf2_i4"
12924  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12925	(float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
12926   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12927  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12928  "fcnvsd  %1,%0"
12929  [(set_attr "type" "fp")
12930   (set_attr "fp_mode" "double")])
12931
12932(define_expand "truncdfsf2"
12933  [(set (match_operand:SF 0 "fpul_operand" "")
12934	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
12935  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12936{
12937  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12938    {
12939      emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
12940				       get_fpscr_rtx ()));
12941      DONE;
12942    }
12943})
12944
12945(define_insn "*truncdfsf2_media"
12946  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12947	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12948  "TARGET_SHMEDIA_FPU"
12949  "fcnv.ds	%1, %0"
12950  [(set_attr "type" "dfpconv_media")])
12951
12952(define_insn "truncdfsf2_i4"
12953  [(set (match_operand:SF 0 "fpul_operand" "=y")
12954	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
12955   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12956  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12957  "fcnvds  %1,%0"
12958  [(set_attr "type" "fp")
12959   (set_attr "fp_mode" "double")])
12960
12961;; -------------------------------------------------------------------------
12962;; Bit field extract patterns.
12963;; -------------------------------------------------------------------------
12964
12965;; These give better code for packed bitfields,  because they allow
12966;; auto-increment addresses to be generated.
12967
12968(define_expand "insv"
12969  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
12970			 (match_operand:SI 1 "immediate_operand" "")
12971			 (match_operand:SI 2 "immediate_operand" ""))
12972	(match_operand:SI 3 "general_operand" ""))]
12973  "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
12974{
12975  rtx addr_target, orig_address, shift_reg, qi_val;
12976  HOST_WIDE_INT bitsize, size, v = 0;
12977  rtx x = operands[3];
12978
12979  if (TARGET_SH2A && TARGET_BITOPS
12980      && (satisfies_constraint_Sbw (operands[0])
12981	  || satisfies_constraint_Sbv (operands[0]))
12982      && satisfies_constraint_M (operands[1])
12983      && satisfies_constraint_K03 (operands[2]))
12984    {
12985      if (satisfies_constraint_N (operands[3]))
12986	{
12987	  emit_insn (gen_bclr_m2a (operands[0], operands[2]));
12988	  DONE;
12989	}
12990      else if (satisfies_constraint_M (operands[3]))
12991	{
12992	  emit_insn (gen_bset_m2a (operands[0], operands[2]));
12993	  DONE;
12994	}
12995      else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
12996		&& satisfies_constraint_M (operands[1]))
12997	{
12998	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
12999	  DONE;
13000	}
13001      else if (REG_P (operands[3])
13002	       && satisfies_constraint_M (operands[1]))
13003	{
13004	  emit_insn (gen_bld_reg (operands[3], const0_rtx));
13005	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
13006	  DONE;
13007	}
13008    }
13009  /* ??? expmed doesn't care for non-register predicates.  */
13010  if (! memory_operand (operands[0], VOIDmode)
13011      || ! immediate_operand (operands[1], VOIDmode)
13012      || ! immediate_operand (operands[2], VOIDmode)
13013      || ! general_operand (x, VOIDmode))
13014    FAIL;
13015  /* If this isn't a 16 / 24 / 32 bit field, or if
13016     it doesn't start on a byte boundary, then fail.  */
13017  bitsize = INTVAL (operands[1]);
13018  if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
13019      || (INTVAL (operands[2]) % 8) != 0)
13020    FAIL;
13021
13022  size = bitsize / 8;
13023  orig_address = XEXP (operands[0], 0);
13024  shift_reg = gen_reg_rtx (SImode);
13025  if (CONST_INT_P (x))
13026    {
13027      v = INTVAL (x);
13028      qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
13029    }
13030  else
13031    {
13032      emit_insn (gen_movsi (shift_reg, operands[3]));
13033      qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13034    }
13035  addr_target = copy_addr_to_reg (plus_constant (Pmode,
13036						 orig_address, size - 1));
13037
13038  operands[0] = replace_equiv_address (operands[0], addr_target);
13039  emit_insn (gen_movqi (operands[0], qi_val));
13040
13041  while (size -= 1)
13042    {
13043      if (CONST_INT_P (x))
13044	qi_val
13045	  = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
13046      else
13047	{
13048	  emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
13049	  qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13050	}
13051      emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
13052      emit_insn (gen_movqi (operands[0], qi_val));
13053    }
13054
13055  DONE;
13056})
13057
13058(define_insn "movua"
13059  [(set (match_operand:SI 0 "register_operand" "=z")
13060	(unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
13061		   UNSPEC_MOVUA))]
13062  "TARGET_SH4A_ARCH"
13063  "movua.l	%1,%0"
13064  [(set_attr "type" "movua")])
13065
13066;; We shouldn't need this, but cse replaces increments with references
13067;; to other regs before flow has a chance to create post_inc
13068;; addressing modes, and only postreload's cse_move2add brings the
13069;; increments back to a usable form.
13070(define_peephole2
13071  [(set (match_operand:SI 0 "register_operand" "")
13072	(sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
13073			 (const_int 32) (const_int 0)))
13074   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13075  "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
13076  [(set (match_operand:SI 0 "register_operand" "")
13077	(sign_extract:SI (mem:SI (post_inc:SI
13078				  (match_operand:SI 1 "register_operand" "")))
13079			 (const_int 32) (const_int 0)))]
13080  "")
13081
13082(define_expand "extv"
13083  [(set (match_operand:SI 0 "register_operand" "")
13084	(sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13085			 (match_operand 2 "const_int_operand" "")
13086			 (match_operand 3 "const_int_operand" "")))]
13087  "TARGET_SH4A_ARCH || TARGET_SH2A"
13088{
13089  if (TARGET_SH2A && TARGET_BITOPS
13090      && (satisfies_constraint_Sbw (operands[1])
13091	  || satisfies_constraint_Sbv (operands[1]))
13092      && satisfies_constraint_M (operands[2])
13093      && satisfies_constraint_K03 (operands[3]))
13094   {
13095      emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
13096      if (REGNO (operands[0]) != T_REG)
13097	emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13098      DONE;
13099   }
13100  if (TARGET_SH4A_ARCH
13101      && INTVAL (operands[2]) == 32
13102      && INTVAL (operands[3]) == 0
13103      && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13104    {
13105      rtx src = adjust_address (operands[1], BLKmode, 0);
13106      set_mem_size (src, 4);
13107      emit_insn (gen_movua (operands[0], src));
13108      DONE;
13109    }
13110
13111  FAIL;
13112})
13113
13114(define_expand "extzv"
13115  [(set (match_operand:SI 0 "register_operand" "")
13116	(zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13117			 (match_operand 2 "const_int_operand" "")
13118			 (match_operand 3 "const_int_operand" "")))]
13119  "TARGET_SH4A_ARCH || TARGET_SH2A"
13120{
13121  if (TARGET_SH2A && TARGET_BITOPS
13122      && (satisfies_constraint_Sbw (operands[1])
13123	  || satisfies_constraint_Sbv (operands[1]))
13124      && satisfies_constraint_M (operands[2])
13125      && satisfies_constraint_K03 (operands[3]))
13126    {
13127      emit_insn (gen_bld_m2a (operands[1], operands[3]));
13128      if (REGNO (operands[0]) != T_REG)
13129	emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13130      DONE;
13131    }
13132  if (TARGET_SH4A_ARCH
13133      && INTVAL (operands[2]) == 32
13134      && INTVAL (operands[3]) == 0
13135      && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
13136    {
13137      rtx src = adjust_address (operands[1], BLKmode, 0);
13138      set_mem_size (src, 4);
13139      emit_insn (gen_movua (operands[0], src));
13140      DONE;
13141    }
13142
13143  FAIL;
13144})
13145
13146;; SH2A instructions for bitwise operations.
13147;; FIXME: Convert multiple instruction insns to insn_and_split.
13148;; FIXME: Use iterators to fold at least and,xor,or insn variations.
13149
13150;; Clear a bit in a memory location.
13151(define_insn "bclr_m2a"
13152  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13153	(and:QI
13154	    (not:QI (ashift:QI (const_int 1)
13155			(match_operand:QI 1 "const_int_operand" "K03,K03")))
13156	    (match_dup 0)))]
13157  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13158  "@
13159	bclr.b	%1,%0
13160	bclr.b	%1,@(0,%t0)"
13161[(set_attr "length" "4,4")])
13162
13163(define_insn "bclrmem_m2a"
13164  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13165        (and:QI (match_dup 0)
13166                (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
13167  "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
13168  "@
13169        bclr.b	%W1,%0
13170        bclr.b	%W1,@(0,%t0)"
13171  [(set_attr "length" "4,4")])
13172
13173;; Set a bit in a memory location.
13174(define_insn "bset_m2a"
13175  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13176	(ior:QI
13177	    (ashift:QI (const_int 1)
13178		       (match_operand:QI 1 "const_int_operand" "K03,K03"))
13179	    (match_dup 0)))]
13180  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13181  "@
13182	bset.b	%1,%0
13183	bset.b	%1,@(0,%t0)"
13184  [(set_attr "length" "4,4")])
13185
13186(define_insn "bsetmem_m2a"
13187  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13188	(ior:QI (match_dup 0)
13189		(match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
13190  "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
13191  "@
13192        bset.b	%V1,%0
13193        bset.b	%V1,@(0,%t0)"
13194  [(set_attr "length" "4,4")])
13195
13196;;; Transfer the contents of the T bit to a specified bit of memory.
13197(define_insn "bst_m2a"
13198  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
13199	(if_then_else (eq (reg:SI T_REG) (const_int 0))
13200	    (and:QI
13201		(not:QI (ashift:QI (const_int 1)
13202			(match_operand:QI 1 "const_int_operand" "K03,K03")))
13203		(match_dup 0))
13204	    (ior:QI
13205		(ashift:QI (const_int 1) (match_dup 1))
13206		(match_dup 0))))]
13207  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13208  "@
13209	bst.b	%1,%0
13210	bst.b	%1,@(0,%t0)"
13211  [(set_attr "length" "4")])
13212
13213;; Store a specified bit of memory in the T bit.
13214(define_insn "bld_m2a"
13215  [(set (reg:SI T_REG)
13216	(zero_extract:SI
13217	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
13218	    (const_int 1)
13219	    (match_operand 1 "const_int_operand" "K03,K03")))]
13220  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13221  "@
13222	bld.b	%1,%0
13223	bld.b	%1,@(0,%t0)"
13224  [(set_attr "length" "4,4")])
13225
13226;; Store a specified bit of memory in the T bit.
13227(define_insn "bldsign_m2a"
13228  [(set (reg:SI T_REG)
13229	(sign_extract:SI
13230	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13231	    (const_int 1)
13232	    (match_operand 1 "const_int_operand" "K03,K03")))]
13233  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13234  "@
13235	bld.b	%1,%0
13236	bld.b	%1,@(0,%t0)"
13237  [(set_attr "length" "4,4")])
13238
13239;; Store a specified bit of the LSB 8 bits of a register in the T bit.
13240(define_insn "bld_reg"
13241  [(set (reg:SI T_REG)
13242	(zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
13243			 (const_int 1)
13244			 (match_operand 1 "const_int_operand" "K03")))]
13245  "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13246  "bld	%1,%0")
13247
13248(define_insn "*bld_regqi"
13249  [(set (reg:SI T_REG)
13250	(zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
13251			 (const_int 1)
13252			 (match_operand 1 "const_int_operand" "K03")))]
13253  "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
13254  "bld	%1,%0")
13255
13256;; Take logical and of a specified bit of memory with the T bit and
13257;; store its result in the T bit.
13258(define_insn "band_m2a"
13259  [(set (reg:SI T_REG)
13260	(and:SI (reg:SI T_REG)
13261		(zero_extract:SI
13262		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13263		    (const_int 1)
13264		    (match_operand 1 "const_int_operand" "K03,K03"))))]
13265  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13266  "@
13267	band.b	%1,%0
13268	band.b	%1,@(0,%t0)"
13269  [(set_attr "length" "4,4")])
13270
13271(define_insn "bandreg_m2a"
13272  [(set (match_operand:SI 0 "register_operand" "=r,r")
13273	(and:SI (zero_extract:SI
13274		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13275		    (const_int 1)
13276		    (match_operand 2 "const_int_operand" "K03,K03"))
13277        	(match_operand:SI 3 "register_operand" "r,r")))]
13278  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13279{
13280  static const char* alt[] =
13281  {
13282       "band.b	%2,%1"		"\n"
13283    "	movt	%0",
13284
13285       "band.b	%2,@(0,%t1)"	"\n"
13286    "	movt	%0"
13287  };
13288  return alt[which_alternative];
13289}
13290  [(set_attr "length" "6,6")])
13291
13292;; Take logical or of a specified bit of memory with the T bit and
13293;; store its result in the T bit.
13294(define_insn "bor_m2a"
13295  [(set (reg:SI T_REG)
13296	(ior:SI (reg:SI T_REG)
13297		(zero_extract:SI
13298		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13299		    (const_int 1)
13300		    (match_operand 1 "const_int_operand" "K03,K03"))))]
13301  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13302  "@
13303	bor.b	%1,%0
13304	bor.b	%1,@(0,%t0)"
13305  [(set_attr "length" "4,4")])
13306
13307(define_insn "borreg_m2a"
13308  [(set (match_operand:SI 0 "register_operand" "=r,r")
13309	(ior:SI (zero_extract:SI
13310		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13311		    (const_int 1)
13312		    (match_operand 2 "const_int_operand" "K03,K03"))
13313		(match_operand:SI 3 "register_operand" "=r,r")))]
13314  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13315{
13316  static const char* alt[] =
13317  {
13318       "bor.b	%2,%1"		"\n"
13319    "	movt	%0",
13320
13321       "bor.b	%2,@(0,%t1)"	"\n"
13322    "	movt	%0"
13323  };
13324  return alt[which_alternative];
13325}
13326  [(set_attr "length" "6,6")])
13327
13328;; Take exclusive or of a specified bit of memory with the T bit and
13329;; store its result in the T bit.
13330(define_insn "bxor_m2a"
13331  [(set (reg:SI T_REG)
13332	(xor:SI (reg:SI T_REG)
13333		(zero_extract:SI
13334		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13335		    (const_int 1)
13336		    (match_operand 1 "const_int_operand" "K03,K03"))))]
13337  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
13338  "@
13339	bxor.b	%1,%0
13340	bxor.b	%1,@(0,%t0)"
13341  [(set_attr "length" "4,4")])
13342
13343(define_insn "bxorreg_m2a"
13344  [(set (match_operand:SI 0 "register_operand" "=r,r")
13345	(xor:SI (zero_extract:SI
13346		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13347		    (const_int 1)
13348		    (match_operand 2 "const_int_operand" "K03,K03"))
13349		(match_operand:SI 3 "register_operand" "=r,r")))]
13350  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
13351{
13352  static const char* alt[] =
13353  {
13354       "bxor.b	%2,%1"		"\n"
13355    "	movt	%0",
13356
13357       "bxor.b	%2,@(0,%t1)"	"\n"
13358    "	movt	%0"
13359  };
13360  return alt[which_alternative];
13361}
13362  [(set_attr "length" "6,6")])
13363
13364;; -------------------------------------------------------------------------
13365;; Peepholes
13366;; -------------------------------------------------------------------------
13367;; This matches cases where the bit in a memory location is set.
13368(define_peephole2
13369  [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13370	(sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13371   (set (match_dup 0)
13372	(ior:SI (match_dup 0)
13373	(match_operand:SI 2 "const_int_operand" "Pso,Pso")))
13374   (set (match_dup 1)
13375	(match_operand 3 "arith_reg_operand" "r,r"))]
13376  "TARGET_SH2A && TARGET_BITOPS
13377   && satisfies_constraint_Pso (operands[2])
13378   && REGNO (operands[0]) == REGNO (operands[3])"
13379  [(set (match_dup 1)
13380        (ior:QI (match_dup 1) (match_dup 2)))]
13381  "")
13382
13383;; This matches cases where the bit in a memory location is cleared.
13384(define_peephole2
13385  [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13386	(sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13387   (set (match_dup 0)
13388	(and:SI (match_dup 0)
13389	(match_operand:SI 2 "const_int_operand" "Psz,Psz")))
13390   (set (match_dup 1)
13391	(match_operand 3 "arith_reg_operand" "r,r"))]
13392  "TARGET_SH2A && TARGET_BITOPS
13393   && satisfies_constraint_Psz (operands[2])
13394   && REGNO (operands[0]) == REGNO (operands[3])"
13395  [(set (match_dup 1)
13396        (and:QI (match_dup 1) (match_dup 2)))]
13397  "")
13398
13399;; This matches cases where a stack pointer increment at the start of the
13400;; epilogue combines with a stack slot read loading the return value.
13401(define_peephole
13402  [(set (match_operand:SI 0 "arith_reg_operand" "")
13403	(mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
13404   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13405  "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
13406  "mov.l	@%1+,%0")
13407
13408;; See the comment on the dt combiner pattern above.
13409(define_peephole
13410  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13411	(plus:SI (match_dup 0)
13412		 (const_int -1)))
13413   (set (reg:SI T_REG)
13414	(eq:SI (match_dup 0) (const_int 0)))]
13415  "TARGET_SH2"
13416  "dt	%0")
13417
13418;; The following peepholes fold load sequences for which reload was not
13419;; able to generate a displacement addressing move insn.
13420;; This can happen when reload has to transform a move insn 
13421;; without displacement into one with displacement.  Or when reload can't
13422;; fit a displacement into the insn's constraints.  In the latter case, the
13423;; load destination reg remains at r0, which reload compensates by inserting
13424;; another mov insn.
13425
13426;; Fold sequence:
13427;;	mov #54,r0
13428;;	mov.{b,w} @(r0,r15),r0
13429;;	mov r0,r3
13430;; into:
13431;;	mov.{b,w} @(54,r15),r3
13432;;
13433(define_peephole2
13434  [(set (match_operand:SI 0 "arith_reg_dest" "")
13435	(match_operand:SI 1 "const_int_operand" ""))
13436   (set (match_operand:SI 2 "arith_reg_dest" "")
13437	(sign_extend:SI
13438	 (mem:QI (plus:SI (match_dup 0)
13439			  (match_operand:SI 3 "arith_reg_operand" "")))))
13440   (set (match_operand:QI 4 "arith_reg_dest" "")
13441	(match_operand:QI 5 "arith_reg_operand" ""))]
13442  "TARGET_SH2A
13443   && sh_legitimate_index_p (QImode, operands[1], true, true)
13444   && REGNO (operands[2]) == REGNO (operands[5])
13445   && peep2_reg_dead_p (3, operands[5])"
13446  [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
13447  "")
13448
13449(define_peephole2
13450  [(set (match_operand:SI 0 "arith_reg_dest" "")
13451	(match_operand:SI 1 "const_int_operand" ""))
13452   (set (match_operand:SI 2 "arith_reg_dest" "")
13453	(sign_extend:SI
13454	 (mem:HI (plus:SI (match_dup 0)
13455			  (match_operand:SI 3 "arith_reg_operand" "")))))
13456   (set (match_operand:HI 4 "arith_reg_dest" "")
13457	(match_operand:HI 5 "arith_reg_operand" ""))]
13458  "TARGET_SH2A
13459   && sh_legitimate_index_p (HImode, operands[1], true, true)
13460   && REGNO (operands[2]) == REGNO (operands[5])
13461   && peep2_reg_dead_p (3, operands[5])"
13462  [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
13463  "")
13464
13465;; Fold sequence:
13466;;	mov #54,r0
13467;;	mov.{b,w} @(r0,r15),r1
13468;; into:
13469;;	mov.{b,w} @(54,r15),r1
13470;;
13471(define_peephole2
13472  [(set (match_operand:SI 0 "arith_reg_dest" "")
13473	(match_operand:SI 1 "const_int_operand" ""))
13474   (set (match_operand:SI 2 "arith_reg_dest" "")
13475	 (sign_extend:SI
13476	 (mem:QI (plus:SI (match_dup 0)
13477			  (match_operand:SI 3 "arith_reg_operand" "")))))]
13478  "TARGET_SH2A
13479   && sh_legitimate_index_p (QImode, operands[1], true, true)
13480   && (peep2_reg_dead_p (2, operands[0])
13481       || REGNO (operands[0]) == REGNO (operands[2]))"
13482  [(set (match_dup 2)
13483	(sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
13484  "")
13485
13486(define_peephole2
13487  [(set (match_operand:SI 0 "arith_reg_dest" "")
13488	(match_operand:SI 1 "const_int_operand" ""))
13489   (set (match_operand:SI 2 "arith_reg_dest" "")
13490	 (sign_extend:SI
13491	 (mem:HI (plus:SI (match_dup 0)
13492			  (match_operand:SI 3 "arith_reg_operand" "")))))]
13493  "TARGET_SH2A
13494   && sh_legitimate_index_p (HImode, operands[1], true, true)
13495   && (peep2_reg_dead_p (2, operands[0])
13496       || REGNO (operands[0]) == REGNO (operands[2]))"
13497  [(set (match_dup 2)
13498	(sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
13499  "")
13500
13501;; Fold sequence:
13502;;	mov.{b,w} @(r0,r15),r0
13503;;	mov r0,r3
13504;; into:
13505;;	mov.{b,w} @(r0,r15),r3
13506;;
13507;; This can happen when initially a displacement address is picked, where
13508;; the destination reg is fixed to r0, and then the address is transformed
13509;; into 'r0 + reg'.
13510(define_peephole2
13511  [(set (match_operand:SI 0 "arith_reg_dest" "")
13512	(sign_extend:SI
13513	 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13514			  (match_operand:SI 2 "arith_reg_operand" "")))))
13515   (set (match_operand:QI 3 "arith_reg_dest" "")
13516	(match_operand:QI 4 "arith_reg_operand" ""))]
13517  "TARGET_SH1
13518   && REGNO (operands[0]) == REGNO (operands[4])
13519   && peep2_reg_dead_p (2, operands[0])"
13520  [(set (match_dup 3)
13521	(mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
13522  "")
13523
13524(define_peephole2
13525  [(set (match_operand:SI 0 "arith_reg_dest" "")
13526	(sign_extend:SI
13527	 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13528			  (match_operand:SI 2 "arith_reg_operand" "")))))
13529   (set (match_operand:HI 3 "arith_reg_dest" "")
13530	(match_operand:HI 4 "arith_reg_operand" ""))]
13531  "TARGET_SH1
13532   && REGNO (operands[0]) == REGNO (operands[4])
13533   && peep2_reg_dead_p (2, operands[0])"
13534  [(set (match_dup 3)
13535	(mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
13536  "")
13537
13538(define_peephole
13539  [(set (match_operand:SI 0 "register_operand" "=r")
13540	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13541   (set (mem:SF (match_dup 0))
13542	(match_operand:SF 2 "general_movsrc_operand" ""))]
13543  "TARGET_SH1 && REGNO (operands[0]) == 0
13544   && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13545       || (GET_CODE (operands[2]) == SUBREG
13546	   && REGNO (SUBREG_REG (operands[2])) < 16))
13547   && reg_unused_after (operands[0], insn)"
13548  "mov.l	%2,@(%0,%1)")
13549
13550(define_peephole
13551  [(set (match_operand:SI 0 "register_operand" "=r")
13552	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13553   (set (match_operand:SF 2 "general_movdst_operand" "")
13554
13555	(mem:SF (match_dup 0)))]
13556  "TARGET_SH1 && REGNO (operands[0]) == 0
13557   && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13558       || (GET_CODE (operands[2]) == SUBREG
13559	   && REGNO (SUBREG_REG (operands[2])) < 16))
13560   && reg_unused_after (operands[0], insn)"
13561  "mov.l	@(%0,%1),%2")
13562
13563(define_peephole
13564  [(set (match_operand:SI 0 "register_operand" "=r")
13565	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13566   (set (mem:SF (match_dup 0))
13567	(match_operand:SF 2 "general_movsrc_operand" ""))]
13568  "TARGET_SH2E && REGNO (operands[0]) == 0
13569   && ((REG_P (operands[2])
13570        && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13571       || (GET_CODE (operands[2]) == SUBREG
13572	   && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13573   && reg_unused_after (operands[0], insn)"
13574  "fmov{.s|}	%2,@(%0,%1)")
13575
13576(define_peephole
13577  [(set (match_operand:SI 0 "register_operand" "=r")
13578	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13579   (set (match_operand:SF 2 "general_movdst_operand" "")
13580
13581	(mem:SF (match_dup 0)))]
13582  "TARGET_SH2E && REGNO (operands[0]) == 0
13583   && ((REG_P (operands[2])
13584	&& FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13585       || (GET_CODE (operands[2]) == SUBREG
13586	   && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13587   && reg_unused_after (operands[0], insn)"
13588  "fmov{.s|}	@(%0,%1),%2")
13589
13590;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
13591(define_insn "sp_switch_1"
13592  [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")]
13593    UNSPECV_SP_SWITCH_B))]
13594  "TARGET_SH1"
13595{
13596  return       "mov.l	r0,@-r15"	"\n"
13597	 "	mov.l	%0,r0"		"\n"
13598	 "	mov.l	@r0,r0"		"\n"
13599	 "	mov.l	r15,@-r0"	"\n"
13600	 "	mov	r0,r15";
13601}
13602  [(set_attr "length" "10")])
13603
13604;; Switch back to the original stack for interrupt functions with the
13605;; sp_switch attribute.
13606(define_insn "sp_switch_2"
13607  [(unspec_volatile [(const_int 0)]
13608    UNSPECV_SP_SWITCH_E)]
13609  "TARGET_SH1"
13610{
13611  return       "mov.l	@r15,r15"	"\n"
13612	 "	mov.l	@r15+,r0";
13613}
13614  [(set_attr "length" "4")])
13615
13616;; -------------------------------------------------------------------------
13617;; Integer vector moves
13618;; -------------------------------------------------------------------------
13619
13620(define_expand "movv8qi"
13621  [(set (match_operand:V8QI 0 "general_movdst_operand" "")
13622	(match_operand:V8QI 1 "general_movsrc_operand" ""))]
13623  "TARGET_SHMEDIA"
13624{
13625  prepare_move_operands (operands, V8QImode);
13626})
13627
13628(define_insn "movv8qi_i"
13629  [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
13630	(match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13631  "TARGET_SHMEDIA
13632   && (register_operand (operands[0], V8QImode)
13633       || sh_register_operand (operands[1], V8QImode))"
13634  "@
13635	add	%1, r63, %0
13636	movi	%1, %0
13637	#
13638	ld%M1.q	%m1, %0
13639	st%M0.q	%m0, %N1"
13640  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13641   (set_attr "length" "4,4,16,4,4")])
13642
13643(define_split
13644  [(set (match_operand:V8QI 0 "arith_reg_dest" "")
13645	(subreg:V8QI (const_int 0) 0))]
13646  "TARGET_SHMEDIA"
13647  [(set (match_dup 0)
13648	(const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
13649			    (const_int 0) (const_int 0) (const_int 0)
13650			    (const_int 0) (const_int 0)]))])
13651
13652(define_split
13653  [(set (match_operand 0 "arith_reg_dest" "")
13654	(match_operand 1 "sh_rep_vec" ""))]
13655  "TARGET_SHMEDIA && reload_completed
13656   && GET_MODE (operands[0]) == GET_MODE (operands[1])
13657   && sh_vector_mode_supported_p (GET_MODE (operands[0]))
13658   && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
13659   && (XVECEXP (operands[1], 0, 0) != const0_rtx
13660       || XVECEXP (operands[1], 0, 1) != const0_rtx)
13661   && (XVECEXP (operands[1], 0, 0) != constm1_rtx
13662       || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
13663  [(set (match_dup 0) (match_dup 1))
13664   (match_dup 2)]
13665{
13666  int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
13667  rtx elt1 = XVECEXP (operands[1], 0, 1);
13668
13669  if (unit_size > 2)
13670    operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
13671  else
13672    {
13673      if (unit_size < 2)
13674	operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
13675      operands[2] = gen_mperm_w0 (operands[0], operands[0]);
13676    }
13677  operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
13678  operands[1] = XVECEXP (operands[1], 0, 0);
13679  if (unit_size < 2)
13680    {
13681      if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
13682	operands[1]
13683	  = GEN_INT (TARGET_LITTLE_ENDIAN
13684		     ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
13685		     : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
13686      else
13687	{
13688	  operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
13689	  operands[1]
13690	    = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
13691	}
13692    }
13693})
13694
13695(define_split
13696  [(set (match_operand 0 "arith_reg_dest" "")
13697	(match_operand 1 "sh_const_vec" ""))]
13698  "TARGET_SHMEDIA && reload_completed
13699   && GET_MODE (operands[0]) == GET_MODE (operands[1])
13700   && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
13701  [(set (match_dup 0) (match_dup 1))]
13702{
13703  rtx v = operands[1];
13704  enum machine_mode new_mode
13705    = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
13706
13707  operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
13708  operands[1]
13709    = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
13710})
13711
13712(define_expand "movv2hi"
13713  [(set (match_operand:V2HI 0 "general_movdst_operand" "")
13714	(match_operand:V2HI 1 "general_movsrc_operand" ""))]
13715  "TARGET_SHMEDIA"
13716{
13717  prepare_move_operands (operands, V2HImode);
13718})
13719
13720(define_insn "movv2hi_i"
13721  [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
13722	(match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13723  "TARGET_SHMEDIA
13724   && (register_operand (operands[0], V2HImode)
13725       || sh_register_operand (operands[1], V2HImode))"
13726  "@
13727	add.l	%1, r63, %0
13728	movi	%1, %0
13729	#
13730	ld%M1.l	%m1, %0
13731	st%M0.l	%m0, %N1"
13732  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13733   (set_attr "length" "4,4,16,4,4")
13734   (set (attr "highpart")
13735	(cond [(match_test "sh_contains_memref_p (insn)")
13736	       (const_string "user")]
13737	      (const_string "ignore")))])
13738
13739(define_expand "movv4hi"
13740  [(set (match_operand:V4HI 0 "general_movdst_operand" "")
13741	(match_operand:V4HI 1 "general_movsrc_operand" ""))]
13742  "TARGET_SHMEDIA"
13743{
13744  prepare_move_operands (operands, V4HImode);
13745})
13746
13747(define_insn "movv4hi_i"
13748  [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
13749	(match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13750  "TARGET_SHMEDIA
13751   && (register_operand (operands[0], V4HImode)
13752       || sh_register_operand (operands[1], V4HImode))"
13753  "@
13754	add	%1, r63, %0
13755	movi	%1, %0
13756	#
13757	ld%M1.q	%m1, %0
13758	st%M0.q	%m0, %N1"
13759  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13760   (set_attr "length" "4,4,16,4,4")
13761   (set_attr "highpart" "depend")])
13762
13763(define_expand "movv2si"
13764  [(set (match_operand:V2SI 0 "general_movdst_operand" "")
13765	(match_operand:V2SI 1 "general_movsrc_operand" ""))]
13766  "TARGET_SHMEDIA"
13767{
13768  prepare_move_operands (operands, V2SImode);
13769})
13770
13771(define_insn "movv2si_i"
13772  [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
13773	(match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13774  "TARGET_SHMEDIA
13775   && (register_operand (operands[0], V2SImode)
13776       || sh_register_operand (operands[1], V2SImode))"
13777  "@
13778	add	%1, r63, %0
13779	#
13780	#
13781	ld%M1.q	%m1, %0
13782	st%M0.q	%m0, %N1"
13783  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
13784   (set_attr "length" "4,4,16,4,4")
13785   (set_attr "highpart" "depend")])
13786
13787;; -------------------------------------------------------------------------
13788;; Multimedia Intrinsics
13789;; -------------------------------------------------------------------------
13790
13791(define_insn "absv2si2"
13792  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13793	(abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
13794  "TARGET_SHMEDIA"
13795  "mabs.l	%1, %0"
13796  [(set_attr "type" "mcmp_media")
13797   (set_attr "highpart" "depend")])
13798
13799(define_insn "absv4hi2"
13800  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13801	(abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
13802  "TARGET_SHMEDIA"
13803  "mabs.w	%1, %0"
13804  [(set_attr "type" "mcmp_media")
13805   (set_attr "highpart" "depend")])
13806
13807(define_insn "addv2si3"
13808  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13809	(plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
13810		   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13811  "TARGET_SHMEDIA"
13812  "madd.l	%1, %2, %0"
13813  [(set_attr "type" "arith_media")
13814   (set_attr "highpart" "depend")])
13815
13816(define_insn "addv4hi3"
13817  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13818	(plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
13819		   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13820  "TARGET_SHMEDIA"
13821  "madd.w	%1, %2, %0"
13822  [(set_attr "type" "arith_media")
13823   (set_attr "highpart" "depend")])
13824
13825(define_insn_and_split "addv2hi3"
13826  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
13827	(plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
13828		   (match_operand:V2HI 2 "extend_reg_operand" "r")))]
13829  "TARGET_SHMEDIA"
13830  "#"
13831  "TARGET_SHMEDIA"
13832  [(const_int 0)]
13833{
13834  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
13835  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
13836  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
13837  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
13838  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
13839
13840  emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
13841  emit_insn (gen_truncdisi2 (si_dst, di_dst));
13842  DONE;
13843}
13844  [(set_attr "highpart" "must_split")])
13845
13846(define_insn "ssaddv2si3"
13847  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13848	(ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
13849		      (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13850  "TARGET_SHMEDIA"
13851  "madds.l	%1, %2, %0"
13852  [(set_attr "type" "mcmp_media")
13853   (set_attr "highpart" "depend")])
13854
13855(define_insn "usaddv8qi3"
13856  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13857	(us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
13858		      (match_operand:V8QI 2 "arith_reg_operand" "r")))]
13859  "TARGET_SHMEDIA"
13860  "madds.ub	%1, %2, %0"
13861  [(set_attr "type" "mcmp_media")
13862   (set_attr "highpart" "depend")])
13863
13864(define_insn "ssaddv4hi3"
13865  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13866	(ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
13867		      (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13868  "TARGET_SHMEDIA"
13869  "madds.w	%1, %2, %0"
13870  [(set_attr "type" "mcmp_media")
13871   (set_attr "highpart" "depend")])
13872
13873(define_insn "negcmpeqv8qi"
13874  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13875	(neg:V8QI (eq:V8QI
13876		    (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
13877		    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
13878  "TARGET_SHMEDIA"
13879  "mcmpeq.b	%N1, %N2, %0"
13880  [(set_attr "type" "mcmp_media")
13881   (set_attr "highpart" "depend")])
13882
13883(define_insn "negcmpeqv2si"
13884  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13885	(neg:V2SI (eq:V2SI
13886		    (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
13887		    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
13888  "TARGET_SHMEDIA"
13889  "mcmpeq.l	%N1, %N2, %0"
13890  [(set_attr "type" "mcmp_media")
13891   (set_attr "highpart" "depend")])
13892
13893(define_insn "negcmpeqv4hi"
13894  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13895	(neg:V4HI (eq:V4HI
13896		    (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
13897		    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13898  "TARGET_SHMEDIA"
13899  "mcmpeq.w	%N1, %N2, %0"
13900  [(set_attr "type" "mcmp_media")
13901   (set_attr "highpart" "depend")])
13902
13903(define_insn "negcmpgtuv8qi"
13904  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13905	(neg:V8QI (gtu:V8QI
13906		    (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
13907		    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
13908  "TARGET_SHMEDIA"
13909  "mcmpgt.ub	%N1, %N2, %0"
13910  [(set_attr "type" "mcmp_media")
13911   (set_attr "highpart" "depend")])
13912
13913(define_insn "negcmpgtv2si"
13914  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13915	(neg:V2SI (gt:V2SI
13916		    (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
13917		    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
13918  "TARGET_SHMEDIA"
13919  "mcmpgt.l	%N1, %N2, %0"
13920  [(set_attr "type" "mcmp_media")
13921   (set_attr "highpart" "depend")])
13922
13923(define_insn "negcmpgtv4hi"
13924  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13925	(neg:V4HI (gt:V4HI
13926		    (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
13927		    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13928  "TARGET_SHMEDIA"
13929  "mcmpgt.w	%N1, %N2, %0"
13930  [(set_attr "type" "mcmp_media")
13931   (set_attr "highpart" "depend")])
13932
13933(define_insn "mcmv"
13934  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13935	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13936			(match_operand:DI 2 "arith_reg_operand" "r"))
13937		(and:DI (match_operand:DI 3 "arith_reg_operand" "0")
13938			(not:DI (match_dup 2)))))]
13939  "TARGET_SHMEDIA"
13940  "mcmv	%N1, %2, %0"
13941  [(set_attr "type" "arith_media")
13942   (set_attr "highpart" "depend")])
13943
13944(define_insn "mcnvs_lw"
13945  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13946	(vec_concat:V4HI
13947	 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
13948	 (ss_truncate:V2HI
13949	   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
13950  "TARGET_SHMEDIA"
13951  "mcnvs.lw	%N1, %N2, %0"
13952  [(set_attr "type" "mcmp_media")])
13953
13954(define_insn "mcnvs_wb"
13955  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13956	(vec_concat:V8QI
13957	 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
13958	 (ss_truncate:V4QI
13959	   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13960  "TARGET_SHMEDIA"
13961  "mcnvs.wb	%N1, %N2, %0"
13962  [(set_attr "type" "mcmp_media")])
13963
13964(define_insn "mcnvs_wub"
13965  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13966	(vec_concat:V8QI
13967	 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
13968	 (us_truncate:V4QI
13969	   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13970  "TARGET_SHMEDIA"
13971  "mcnvs.wub	%N1, %N2, %0"
13972  [(set_attr "type" "mcmp_media")])
13973
13974(define_insn "mextr_rl"
13975  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13976	(ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13977			     (match_operand:HI 3 "mextr_bit_offset" "i"))
13978		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13979			   (match_operand:HI 4 "mextr_bit_offset" "i"))))]
13980  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
13981{
13982  static char templ[21];
13983  sprintf (templ, "mextr%d	%%N1, %%N2, %%0",
13984	   (int) INTVAL (operands[3]) >> 3);
13985  return templ;
13986}
13987  [(set_attr "type" "arith_media")])
13988
13989(define_insn "*mextr_lr"
13990  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13991	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13992			   (match_operand:HI 3 "mextr_bit_offset" "i"))
13993		(lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13994			     (match_operand:HI 4 "mextr_bit_offset" "i"))))]
13995  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
13996{
13997  static char templ[21];
13998  sprintf (templ, "mextr%d	%%N2, %%N1, %%0",
13999	   (int) INTVAL (operands[4]) >> 3);
14000  return templ;
14001}
14002  [(set_attr "type" "arith_media")])
14003
14004; mextrN can be modelled with vec_select / vec_concat, but the selection
14005; vector then varies depending on endianness.
14006(define_expand "mextr1"
14007  [(match_operand:DI 0 "arith_reg_dest" "")
14008   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14009   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14010  "TARGET_SHMEDIA"
14011{
14012  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14013			   GEN_INT (1 * 8), GEN_INT (7 * 8)));
14014  DONE;
14015})
14016
14017(define_expand "mextr2"
14018  [(match_operand:DI 0 "arith_reg_dest" "")
14019   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14020   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14021  "TARGET_SHMEDIA"
14022{
14023  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14024			   GEN_INT (2 * 8), GEN_INT (6 * 8)));
14025  DONE;
14026})
14027
14028(define_expand "mextr3"
14029  [(match_operand:DI 0 "arith_reg_dest" "")
14030   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14031   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14032  "TARGET_SHMEDIA"
14033{
14034  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14035			   GEN_INT (3 * 8), GEN_INT (5 * 8)));
14036  DONE;
14037})
14038
14039(define_expand "mextr4"
14040  [(match_operand:DI 0 "arith_reg_dest" "")
14041   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14042   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14043  "TARGET_SHMEDIA"
14044{
14045  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14046			   GEN_INT (4 * 8), GEN_INT (4 * 8)));
14047  DONE;
14048})
14049
14050(define_expand "mextr5"
14051  [(match_operand:DI 0 "arith_reg_dest" "")
14052   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14053   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14054  "TARGET_SHMEDIA"
14055{
14056  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14057			   GEN_INT (5 * 8), GEN_INT (3 * 8)));
14058  DONE;
14059})
14060
14061(define_expand "mextr6"
14062  [(match_operand:DI 0 "arith_reg_dest" "")
14063   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14064   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14065  "TARGET_SHMEDIA"
14066{
14067  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14068			   GEN_INT (6 * 8), GEN_INT (2 * 8)));
14069  DONE;
14070})
14071
14072(define_expand "mextr7"
14073  [(match_operand:DI 0 "arith_reg_dest" "")
14074   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14075   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
14076  "TARGET_SHMEDIA"
14077{
14078  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
14079			   GEN_INT (7 * 8), GEN_INT (1 * 8)));
14080  DONE;
14081})
14082
14083(define_expand "mmacfx_wl"
14084  [(match_operand:V2SI 0 "arith_reg_dest" "")
14085   (match_operand:V2HI 1 "extend_reg_operand" "")
14086   (match_operand:V2HI 2 "extend_reg_operand" "")
14087   (match_operand:V2SI 3 "arith_reg_operand" "")]
14088  "TARGET_SHMEDIA"
14089{
14090  emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
14091			      operands[1], operands[2]));
14092  DONE;
14093})
14094
14095;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
14096;; is depend
14097(define_insn "mmacfx_wl_i"
14098  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14099	(ss_plus:V2SI
14100	 (match_operand:V2SI 1 "arith_reg_operand" "0")
14101	 (ss_truncate:V2SI
14102	  (ashift:V2DI
14103	   (sign_extend:V2DI
14104	    (mult:V2SI
14105	     (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14106	     (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14107	   (const_int 1)))))]
14108  "TARGET_SHMEDIA"
14109  "mmacfx.wl	%2, %3, %0"
14110  [(set_attr "type" "mac_media")
14111   (set_attr "highpart" "depend")])
14112
14113(define_expand "mmacnfx_wl"
14114  [(match_operand:V2SI 0 "arith_reg_dest" "")
14115   (match_operand:V2HI 1 "extend_reg_operand" "")
14116   (match_operand:V2HI 2 "extend_reg_operand" "")
14117   (match_operand:V2SI 3 "arith_reg_operand" "")]
14118  "TARGET_SHMEDIA"
14119{
14120  emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
14121			       operands[1], operands[2]));
14122  DONE;
14123})
14124
14125(define_insn "mmacnfx_wl_i"
14126  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14127	(ss_minus:V2SI
14128	 (match_operand:V2SI 1 "arith_reg_operand" "0")
14129	 (ss_truncate:V2SI
14130	  (ashift:V2DI
14131	   (sign_extend:V2DI
14132	    (mult:V2SI
14133	     (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14134	     (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14135	   (const_int 1)))))]
14136  "TARGET_SHMEDIA"
14137  "mmacnfx.wl	%2, %3, %0"
14138  [(set_attr "type" "mac_media")
14139   (set_attr "highpart" "depend")])
14140
14141(define_insn "mulv2si3"
14142  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14143	(mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14144		   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14145  "TARGET_SHMEDIA"
14146  "mmul.l	%1, %2, %0"
14147  [(set_attr "type" "d2mpy_media")
14148   (set_attr "highpart" "depend")])
14149
14150(define_insn "mulv4hi3"
14151  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14152	(mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14153		   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14154  "TARGET_SHMEDIA"
14155  "mmul.w	%1, %2, %0"
14156  [(set_attr "type" "dmpy_media")
14157   (set_attr "highpart" "depend")])
14158
14159(define_insn "mmulfx_l"
14160  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14161	(ss_truncate:V2SI
14162	 (ashiftrt:V2DI
14163	  (mult:V2DI
14164	   (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14165	   (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
14166	  (const_int 31))))]
14167  "TARGET_SHMEDIA"
14168  "mmulfx.l	%1, %2, %0"
14169  [(set_attr "type" "d2mpy_media")
14170   (set_attr "highpart" "depend")])
14171
14172(define_insn "mmulfx_w"
14173  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14174	(ss_truncate:V4HI
14175	 (ashiftrt:V4SI
14176	  (mult:V4SI
14177	   (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14178	   (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14179	  (const_int 15))))]
14180  "TARGET_SHMEDIA"
14181  "mmulfx.w	%1, %2, %0"
14182  [(set_attr "type" "dmpy_media")
14183   (set_attr "highpart" "depend")])
14184
14185(define_insn "mmulfxrp_w"
14186  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14187	(ss_truncate:V4HI
14188	 (ashiftrt:V4SI
14189	  (plus:V4SI
14190	   (mult:V4SI
14191	    (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14192	    (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14193	   (const_int 16384))
14194	  (const_int 15))))]
14195  "TARGET_SHMEDIA"
14196  "mmulfxrp.w	%1, %2, %0"
14197  [(set_attr "type" "dmpy_media")
14198   (set_attr "highpart" "depend")])
14199
14200
14201(define_expand "mmulhi_wl"
14202  [(match_operand:V2SI 0 "arith_reg_dest" "")
14203   (match_operand:V4HI 1 "arith_reg_operand" "")
14204   (match_operand:V4HI 2 "arith_reg_operand" "")]
14205  "TARGET_SHMEDIA"
14206{
14207  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
14208	     (operands[0], operands[1], operands[2]));
14209  DONE;
14210})
14211
14212(define_expand "mmullo_wl"
14213  [(match_operand:V2SI 0 "arith_reg_dest" "")
14214   (match_operand:V4HI 1 "arith_reg_operand" "")
14215   (match_operand:V4HI 2 "arith_reg_operand" "")]
14216  "TARGET_SHMEDIA"
14217{
14218  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
14219	     (operands[0], operands[1], operands[2]));
14220  DONE;
14221})
14222
14223(define_insn "mmul23_wl"
14224  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14225	(vec_select:V2SI
14226	 (mult:V4SI
14227	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14228	  (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14229	 (parallel [(const_int 2) (const_int 3)])))]
14230  "TARGET_SHMEDIA"
14231{
14232  return (TARGET_LITTLE_ENDIAN
14233	  ? "mmulhi.wl	%1, %2, %0"
14234	  : "mmullo.wl	%1, %2, %0");
14235}
14236  [(set_attr "type" "dmpy_media")
14237   (set (attr "highpart")
14238	(cond [(eq_attr "endian" "big") (const_string "ignore")]
14239	 (const_string "user")))])
14240
14241(define_insn "mmul01_wl"
14242  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14243	(vec_select:V2SI
14244	 (mult:V4SI
14245	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14246	  (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14247	 (parallel [(const_int 0) (const_int 1)])))]
14248  "TARGET_SHMEDIA"
14249{
14250  return (TARGET_LITTLE_ENDIAN
14251	  ? "mmullo.wl	%1, %2, %0"
14252	  : "mmulhi.wl	%1, %2, %0");
14253}
14254  [(set_attr "type" "dmpy_media")
14255   (set (attr "highpart")
14256	(cond [(eq_attr "endian" "little") (const_string "ignore")]
14257	 (const_string "user")))])
14258
14259
14260(define_expand "mmulsum_wq"
14261  [(match_operand:DI 0 "arith_reg_dest" "")
14262   (match_operand:V4HI 1 "arith_reg_operand" "")
14263   (match_operand:V4HI 2 "arith_reg_operand" "")
14264   (match_operand:DI 3 "arith_reg_operand" "")]
14265  "TARGET_SHMEDIA"
14266{
14267  emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
14268			       operands[1], operands[2]));
14269  DONE;
14270})
14271
14272(define_insn "mmulsum_wq_i"
14273  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14274	(plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
14275	 (plus:DI
14276	  (plus:DI
14277	   (vec_select:DI
14278	    (mult:V4DI
14279	     (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
14280	     (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
14281	    (parallel [(const_int 0)]))
14282	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14283				     (sign_extend:V4DI (match_dup 3)))
14284			  (parallel [(const_int 1)])))
14285	  (plus:DI
14286	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14287				     (sign_extend:V4DI (match_dup 3)))
14288			  (parallel [(const_int 2)]))
14289	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14290				     (sign_extend:V4DI (match_dup 3)))
14291			  (parallel [(const_int 3)]))))))]
14292  "TARGET_SHMEDIA"
14293  "mmulsum.wq	%2, %3, %0"
14294  [(set_attr "type" "mac_media")])
14295
14296(define_expand "mperm_w"
14297  [(match_operand:V4HI 0 "arith_reg_dest" "=r")
14298   (match_operand:V4HI 1 "arith_reg_operand" "r")
14299   (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
14300  "TARGET_SHMEDIA"
14301{
14302  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
14303	     (operands[0], operands[1], operands[2]));
14304  DONE;
14305})
14306
14307; This use of vec_select isn't exactly correct according to rtl.texi
14308; (because not constant), but it seems a straightforward extension.
14309(define_insn "mperm_w_little"
14310  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14311	(vec_select:V4HI
14312	 (match_operand:V4HI 1 "arith_reg_operand" "r")
14313	 (parallel
14314	  [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
14315			    (const_int 2) (const_int 0))
14316	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
14317	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
14318	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
14319  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
14320  "mperm.w	%1, %N2, %0"
14321  [(set_attr "type" "arith_media")])
14322
14323(define_insn "mperm_w_big"
14324  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14325	(vec_select:V4HI
14326	 (match_operand:V4HI 1 "arith_reg_operand" "r")
14327	 (parallel
14328	  [(zero_extract:QI (not:QI (match_operand:QI 2
14329				     "extend_reg_or_0_operand" "rZ"))
14330			    (const_int 2) (const_int 0))
14331	   (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
14332	   (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
14333	   (zero_extract:QI (not:QI (match_dup 2))
14334			    (const_int 2) (const_int 6))])))]
14335  "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
14336  "mperm.w	%1, %N2, %0"
14337  [(set_attr "type" "arith_media")])
14338
14339(define_insn "mperm_w0"
14340  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14341	(vec_duplicate:V4HI (truncate:HI (match_operand 1
14342					  "trunc_hi_operand" "r"))))]
14343  "TARGET_SHMEDIA"
14344  "mperm.w	%1, r63, %0"
14345  [(set_attr "type" "arith_media")
14346   (set_attr "highpart" "ignore")])
14347
14348(define_expand "msad_ubq"
14349  [(match_operand:DI 0 "arith_reg_dest" "")
14350   (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
14351   (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
14352   (match_operand:DI 3 "arith_reg_operand" "")]
14353  "TARGET_SHMEDIA"
14354{
14355  emit_insn (gen_msad_ubq_i (operands[0], operands[3],
14356			     operands[1], operands[2]));
14357  DONE;
14358})
14359
14360(define_insn "msad_ubq_i"
14361  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14362	(plus:DI
14363	 (plus:DI
14364	  (plus:DI
14365	   (plus:DI
14366	    (match_operand:DI 1 "arith_reg_operand" "0")
14367	    (abs:DI (vec_select:DI
14368		     (minus:V8DI
14369		      (zero_extend:V8DI
14370		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14371		      (zero_extend:V8DI
14372		       (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
14373		     (parallel [(const_int 0)]))))
14374	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14375					      (zero_extend:V8DI (match_dup 3)))
14376				  (parallel [(const_int 1)]))))
14377	  (plus:DI
14378	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14379					      (zero_extend:V8DI (match_dup 3)))
14380				  (parallel [(const_int 2)])))
14381	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14382					      (zero_extend:V8DI (match_dup 3)))
14383				  (parallel [(const_int 3)])))))
14384	 (plus:DI
14385	  (plus:DI
14386	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14387					      (zero_extend:V8DI (match_dup 3)))
14388				  (parallel [(const_int 4)])))
14389	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14390					      (zero_extend:V8DI (match_dup 3)))
14391				  (parallel [(const_int 5)]))))
14392	  (plus:DI
14393	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14394					      (zero_extend:V8DI (match_dup 3)))
14395				  (parallel [(const_int 6)])))
14396	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14397					      (zero_extend:V8DI (match_dup 3)))
14398				  (parallel [(const_int 7)])))))))]
14399  "TARGET_SHMEDIA"
14400  "msad.ubq	%N2, %N3, %0"
14401  [(set_attr "type" "mac_media")])
14402
14403(define_insn "mshalds_l"
14404  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14405	(ss_truncate:V2SI
14406	 (ashift:V2DI
14407	  (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14408	  (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14409		  (const_int 31)))))]
14410  "TARGET_SHMEDIA"
14411  "mshalds.l	%1, %2, %0"
14412  [(set_attr "type" "mcmp_media")
14413   (set_attr "highpart" "depend")])
14414
14415(define_insn "mshalds_w"
14416  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14417	(ss_truncate:V4HI
14418	 (ashift:V4SI
14419	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14420	  (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14421		  (const_int 15)))))]
14422  "TARGET_SHMEDIA"
14423  "mshalds.w	%1, %2, %0"
14424  [(set_attr "type" "mcmp_media")
14425   (set_attr "highpart" "depend")])
14426
14427(define_insn "ashrv2si3"
14428  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14429	(ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14430		       (match_operand:DI 2 "arith_reg_operand" "r")))]
14431  "TARGET_SHMEDIA"
14432  "mshard.l	%1, %2, %0"
14433  [(set_attr "type" "arith_media")
14434   (set_attr "highpart" "depend")])
14435
14436(define_insn "ashrv4hi3"
14437  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14438	(ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14439		       (match_operand:DI 2 "arith_reg_operand" "r")))]
14440  "TARGET_SHMEDIA"
14441  "mshard.w	%1, %2, %0"
14442  [(set_attr "type" "arith_media")
14443   (set_attr "highpart" "depend")])
14444
14445(define_insn "mshards_q"
14446  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
14447	(ss_truncate:HI
14448	 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
14449		      (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
14450  "TARGET_SHMEDIA"
14451  "mshards.q	%1, %N2, %0"
14452  [(set_attr "type" "mcmp_media")])
14453
14454(define_expand "mshfhi_b"
14455  [(match_operand:V8QI 0 "arith_reg_dest" "")
14456   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14457   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14458  "TARGET_SHMEDIA"
14459{
14460  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
14461	     (operands[0], operands[1], operands[2]));
14462  DONE;
14463})
14464
14465(define_expand "mshflo_b"
14466  [(match_operand:V8QI 0 "arith_reg_dest" "")
14467   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14468   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14469  "TARGET_SHMEDIA"
14470{
14471  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
14472	     (operands[0], operands[1], operands[2]));
14473  DONE;
14474})
14475
14476(define_insn "mshf4_b"
14477  [(set
14478    (match_operand:V8QI 0 "arith_reg_dest" "=r")
14479    (vec_select:V8QI
14480     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14481		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14482     (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
14483		(const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
14484  "TARGET_SHMEDIA"
14485{
14486  return (TARGET_LITTLE_ENDIAN
14487	  ? "mshfhi.b	%N1, %N2, %0"
14488	  : "mshflo.b	%N1, %N2, %0");
14489}
14490  [(set_attr "type" "arith_media")
14491   (set (attr "highpart")
14492	(cond [(eq_attr "endian" "big") (const_string "ignore")]
14493	 (const_string "user")))])
14494
14495(define_insn "mshf0_b"
14496  [(set
14497    (match_operand:V8QI 0 "arith_reg_dest" "=r")
14498    (vec_select:V8QI
14499     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14500		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14501     (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
14502		(const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
14503  "TARGET_SHMEDIA"
14504{
14505  return (TARGET_LITTLE_ENDIAN
14506	  ? "mshflo.b	%N1, %N2, %0"
14507	  : "mshfhi.b	%N1, %N2, %0");
14508}
14509  [(set_attr "type" "arith_media")
14510   (set (attr "highpart")
14511	(cond [(eq_attr "endian" "little") (const_string "ignore")]
14512	 (const_string "user")))])
14513
14514(define_expand "mshfhi_l"
14515  [(match_operand:V2SI 0 "arith_reg_dest" "")
14516   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14517   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14518  "TARGET_SHMEDIA"
14519{
14520  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
14521	     (operands[0], operands[1], operands[2]));
14522  DONE;
14523})
14524
14525(define_expand "mshflo_l"
14526  [(match_operand:V2SI 0 "arith_reg_dest" "")
14527   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14528   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14529  "TARGET_SHMEDIA"
14530{
14531  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
14532	     (operands[0], operands[1], operands[2]));
14533  DONE;
14534})
14535
14536(define_insn "mshf4_l"
14537  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14538	(vec_select:V2SI
14539	 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14540			  (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14541	 (parallel [(const_int 1) (const_int 3)])))]
14542  "TARGET_SHMEDIA"
14543{
14544  return (TARGET_LITTLE_ENDIAN
14545	  ? "mshfhi.l	%N1, %N2, %0"
14546	  : "mshflo.l	%N1, %N2, %0");
14547}
14548  [(set_attr "type" "arith_media")
14549   (set (attr "highpart")
14550	(cond [(eq_attr "endian" "big") (const_string "ignore")]
14551	 (const_string "user")))])
14552
14553(define_insn "mshf0_l"
14554  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14555	(vec_select:V2SI
14556	 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14557			  (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14558	 (parallel [(const_int 0) (const_int 2)])))]
14559  "TARGET_SHMEDIA"
14560{
14561  return (TARGET_LITTLE_ENDIAN
14562	  ? "mshflo.l	%N1, %N2, %0"
14563	  : "mshfhi.l	%N1, %N2, %0");
14564}
14565  [(set_attr "type" "arith_media")
14566   (set (attr "highpart")
14567	(cond [(eq_attr "endian" "little") (const_string "ignore")]
14568	 (const_string "user")))])
14569
14570(define_expand "mshfhi_w"
14571  [(match_operand:V4HI 0 "arith_reg_dest" "")
14572   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14573   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14574  "TARGET_SHMEDIA"
14575{
14576  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
14577	     (operands[0], operands[1], operands[2]));
14578  DONE;
14579})
14580
14581(define_expand "mshflo_w"
14582  [(match_operand:V4HI 0 "arith_reg_dest" "")
14583   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14584   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14585  "TARGET_SHMEDIA"
14586{
14587  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
14588	     (operands[0], operands[1], operands[2]));
14589  DONE;
14590})
14591
14592(define_insn "mshf4_w"
14593  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14594	(vec_select:V4HI
14595	 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14596			  (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14597	 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
14598  "TARGET_SHMEDIA"
14599{
14600  return (TARGET_LITTLE_ENDIAN
14601	  ? "mshfhi.w	%N1, %N2, %0"
14602	  : "mshflo.w	%N1, %N2, %0");
14603}
14604  [(set_attr "type" "arith_media")
14605   (set (attr "highpart")
14606	(cond [(eq_attr "endian" "big") (const_string "ignore")]
14607	 (const_string "user")))])
14608
14609(define_insn "mshf0_w"
14610  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14611	(vec_select:V4HI
14612	 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14613			  (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14614	 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
14615  "TARGET_SHMEDIA"
14616{
14617  return (TARGET_LITTLE_ENDIAN
14618	  ? "mshflo.w	%N1, %N2, %0"
14619	  : "mshfhi.w	%N1, %N2, %0");
14620}
14621  [(set_attr "type" "arith_media")
14622   (set (attr "highpart")
14623	(cond [(eq_attr "endian" "little") (const_string "ignore")]
14624	 (const_string "user")))])
14625
14626(define_insn "mshflo_w_x"
14627  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14628	(vec_select:V4HI
14629	 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
14630			  (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
14631	 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
14632  "TARGET_SHMEDIA"
14633  "mshflo.w	%N1, %N2, %0"
14634  [(set_attr "type" "arith_media")
14635   (set_attr "highpart" "ignore")])
14636
14637;; These are useful to expand ANDs and as combiner patterns.
14638(define_insn_and_split "mshfhi_l_di"
14639  [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
14640	(ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
14641			     (const_int 32))
14642		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
14643			(const_int -4294967296))))]
14644  "TARGET_SHMEDIA"
14645  "@
14646	mshfhi.l	%N1, %N2, %0
14647	#"
14648  "TARGET_SHMEDIA && reload_completed
14649   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14650  [(set (match_dup 3) (match_dup 4))
14651   (set (match_dup 5) (match_dup 6))]
14652{
14653  operands[3] = gen_lowpart (SImode, operands[0]);
14654  operands[4] = gen_highpart (SImode, operands[1]);
14655  operands[5] = gen_highpart (SImode, operands[0]);
14656  operands[6] = gen_highpart (SImode, operands[2]);
14657}
14658  [(set_attr "type" "arith_media")])
14659
14660(define_insn "*mshfhi_l_di_rev"
14661  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14662	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14663			(const_int -4294967296))
14664		(lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14665			     (const_int 32))))]
14666  "TARGET_SHMEDIA"
14667  "mshfhi.l	%N2, %N1, %0"
14668  [(set_attr "type" "arith_media")])
14669
14670(define_split
14671  [(set (match_operand:DI 0 "arith_reg_dest" "")
14672	(ior:DI (zero_extend:DI (match_operand:SI 1
14673					      "extend_reg_or_0_operand" ""))
14674		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
14675			(const_int -4294967296))))
14676   (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
14677  "TARGET_SHMEDIA"
14678  [(const_int 0)]
14679{
14680  emit_insn (gen_ashldi3_media (operands[3],
14681				simplify_gen_subreg (DImode, operands[1],
14682						     SImode, 0),
14683				GEN_INT (32)));
14684  emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
14685  DONE;
14686})
14687
14688(define_insn "mshflo_l_di"
14689  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14690	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14691			(const_int 4294967295))
14692		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14693			   (const_int 32))))]
14694
14695  "TARGET_SHMEDIA"
14696  "mshflo.l	%N1, %N2, %0"
14697  [(set_attr "type" "arith_media")
14698   (set_attr "highpart" "ignore")])
14699
14700(define_insn "*mshflo_l_di_rev"
14701  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14702	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14703			   (const_int 32))
14704		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14705			(const_int 4294967295))))]
14706
14707  "TARGET_SHMEDIA"
14708  "mshflo.l	%N2, %N1, %0"
14709  [(set_attr "type" "arith_media")
14710   (set_attr "highpart" "ignore")])
14711
14712;; Combiner pattern for trampoline initialization.
14713(define_insn_and_split "*double_shori"
14714  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14715	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
14716			   (const_int 32))
14717		(match_operand:DI 2 "const_int_operand" "n")))]
14718  "TARGET_SHMEDIA
14719   && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
14720  "#"
14721  "rtx_equal_p (operands[0], operands[1])"
14722  [(const_int 0)]
14723{
14724  HOST_WIDE_INT v = INTVAL (operands[2]);
14725
14726  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
14727  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
14728  DONE;
14729}
14730  [(set_attr "highpart" "ignore")])
14731
14732(define_insn "*mshflo_l_di_x"
14733  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14734	(ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
14735				 "rZ"))
14736		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14737			   (const_int 32))))]
14738  "TARGET_SHMEDIA"
14739  "mshflo.l	%N1, %N2, %0"
14740  [(set_attr "type" "arith_media")
14741   (set_attr "highpart" "ignore")])
14742
14743(define_insn_and_split "concat_v2sf"
14744  [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
14745;;	(vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
14746	(vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
14747			 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
14748  "TARGET_SHMEDIA"
14749  "@
14750	mshflo.l	%N1, %N2, %0
14751	#
14752	#"
14753  "TARGET_SHMEDIA && reload_completed
14754   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14755  [(set (match_dup 3) (match_dup 1))
14756   (set (match_dup 4) (match_dup 2))]
14757{
14758  operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
14759  operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
14760}
14761  [(set_attr "type" "arith_media")
14762   (set_attr "highpart" "ignore")])
14763
14764(define_insn "*mshflo_l_di_x_rev"
14765  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14766	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14767			   (const_int 32))
14768		(zero_extend:DI
14769		  (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
14770  "TARGET_SHMEDIA"
14771  "mshflo.l	%N2, %N1, %0"
14772  [(set_attr "type" "arith_media")
14773   (set_attr "highpart" "ignore")])
14774
14775(define_insn "ashlv2si3"
14776  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14777	(ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14778		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14779  "TARGET_SHMEDIA"
14780  "mshlld.l	%1, %2, %0"
14781  [(set_attr "type" "arith_media")
14782   (set_attr "highpart" "depend")])
14783
14784(define_split
14785  [(set (match_operand 0 "any_register_operand" "")
14786	(match_operator 3 "shift_operator"
14787	  [(match_operand 1 "any_register_operand" "")
14788	   (match_operand 2 "shift_count_reg_operand" "")]))]
14789  "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
14790  [(set (match_dup 0) (match_dup 3))]
14791{
14792  rtx count = operands[2];
14793  enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
14794
14795  while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
14796	 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
14797	 || GET_CODE (count) == TRUNCATE)
14798    count = XEXP (count, 0);
14799  inner_mode = GET_MODE (count);
14800  count = simplify_gen_subreg (outer_mode, count, inner_mode,
14801			       subreg_lowpart_offset (outer_mode, inner_mode));
14802  operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
14803				operands[1], count);
14804})
14805
14806(define_insn "ashlv4hi3"
14807  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14808	(ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14809		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14810  "TARGET_SHMEDIA"
14811  "mshlld.w	%1, %2, %0"
14812  [(set_attr "type" "arith_media")
14813   (set_attr "highpart" "depend")])
14814
14815(define_insn "lshrv2si3"
14816  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14817	(lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14818		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14819  "TARGET_SHMEDIA"
14820  "mshlrd.l	%1, %2, %0"
14821  [(set_attr "type" "arith_media")
14822   (set_attr "highpart" "depend")])
14823
14824(define_insn "lshrv4hi3"
14825  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14826	(lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14827		       (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14828  "TARGET_SHMEDIA"
14829  "mshlrd.w	%1, %2, %0"
14830  [(set_attr "type" "arith_media")
14831   (set_attr "highpart" "depend")])
14832
14833(define_insn "subv2si3"
14834  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14835	(minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14836		    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14837  "TARGET_SHMEDIA"
14838  "msub.l	%N1, %2, %0"
14839  [(set_attr "type" "arith_media")
14840   (set_attr "highpart" "depend")])
14841
14842(define_insn "subv4hi3"
14843  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14844	(minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14845		    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14846  "TARGET_SHMEDIA"
14847  "msub.w	%N1, %2, %0"
14848  [(set_attr "type" "arith_media")
14849   (set_attr "highpart" "depend")])
14850
14851(define_insn_and_split "subv2hi3"
14852  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
14853	(minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
14854		   (match_operand:V2HI 2 "arith_reg_operand" "r")))]
14855  "TARGET_SHMEDIA"
14856  "#"
14857  "TARGET_SHMEDIA"
14858  [(const_int 0)]
14859{
14860  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
14861  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
14862  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
14863  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
14864  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
14865
14866  emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
14867  emit_insn (gen_truncdisi2 (si_dst, di_dst));
14868  DONE;
14869}
14870  [(set_attr "highpart" "must_split")])
14871
14872(define_insn "sssubv2si3"
14873  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14874	(ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14875		       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14876  "TARGET_SHMEDIA"
14877  "msubs.l	%N1, %2, %0"
14878  [(set_attr "type" "mcmp_media")
14879   (set_attr "highpart" "depend")])
14880
14881(define_insn "ussubv8qi3"
14882  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14883	(us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14884		       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
14885  "TARGET_SHMEDIA"
14886  "msubs.ub	%N1, %2, %0"
14887  [(set_attr "type" "mcmp_media")
14888   (set_attr "highpart" "depend")])
14889
14890(define_insn "sssubv4hi3"
14891  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14892	(ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14893		       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14894  "TARGET_SHMEDIA"
14895  "msubs.w	%N1, %2, %0"
14896  [(set_attr "type" "mcmp_media")
14897   (set_attr "highpart" "depend")])
14898
14899;; -------------------------------------------------------------------------
14900;; Floating Point Intrinsics
14901;; -------------------------------------------------------------------------
14902
14903(define_insn "fcosa_s"
14904  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14905	(unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
14906		   UNSPEC_FCOSA))]
14907  "TARGET_SHMEDIA"
14908  "fcosa.s	%1, %0"
14909  [(set_attr "type" "atrans_media")])
14910
14911(define_insn "fsina_s"
14912  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14913	(unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
14914		   UNSPEC_FSINA))]
14915  "TARGET_SHMEDIA"
14916  "fsina.s	%1, %0"
14917  [(set_attr "type" "atrans_media")])
14918
14919(define_insn "fipr"
14920  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14921	(plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
14922						    "fp_arith_reg_operand" "f")
14923						   (match_operand:V4SF 2
14924						    "fp_arith_reg_operand" "f"))
14925					 (parallel [(const_int 0)]))
14926			  (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
14927					 (parallel [(const_int 1)])))
14928		 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
14929					 (parallel [(const_int 2)]))
14930			  (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
14931					 (parallel [(const_int 3)])))))]
14932  "TARGET_SHMEDIA"
14933  "fipr.s	%1, %2, %0"
14934  [(set_attr "type" "fparith_media")])
14935
14936(define_insn "fsrra_s"
14937  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14938	(unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
14939		   UNSPEC_FSRRA))]
14940  "TARGET_SHMEDIA"
14941  "fsrra.s	%1, %0"
14942  [(set_attr "type" "atrans_media")])
14943
14944(define_insn "ftrv"
14945  [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
14946	(plus:V4SF
14947	 (plus:V4SF
14948	  (mult:V4SF
14949	   (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
14950			    (parallel [(const_int 0) (const_int 5)
14951				       (const_int 10) (const_int 15)]))
14952	   (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
14953	  (mult:V4SF
14954	   (vec_select:V4SF (match_dup 1)
14955			    (parallel [(const_int 4) (const_int 9)
14956				       (const_int 14) (const_int 3)]))
14957	   (vec_select:V4SF (match_dup 2)
14958			    (parallel [(const_int 1) (const_int 2)
14959				       (const_int 3) (const_int 0)]))))
14960	 (plus:V4SF
14961	  (mult:V4SF
14962	   (vec_select:V4SF (match_dup 1)
14963			    (parallel [(const_int 8) (const_int 13)
14964				       (const_int 2) (const_int 7)]))
14965	   (vec_select:V4SF (match_dup 2)
14966			    (parallel [(const_int 2) (const_int 3)
14967				       (const_int 0) (const_int 1)])))
14968	  (mult:V4SF
14969	   (vec_select:V4SF (match_dup 1)
14970			    (parallel [(const_int 12) (const_int 1)
14971				       (const_int 6) (const_int 11)]))
14972	   (vec_select:V4SF (match_dup 2)
14973			    (parallel [(const_int 3) (const_int 0)
14974				       (const_int 1) (const_int 2)]))))))]
14975  "TARGET_SHMEDIA"
14976  "ftrv.s %1, %2, %0"
14977  [(set_attr "type" "fparith_media")])
14978
14979(define_insn "ldhi_l"
14980  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
14981	(zero_extract:SI
14982	 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
14983				  (const_int 3))
14984			  (const_int -3)))
14985	 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
14986	 (const_int 0)))]
14987  "TARGET_SHMEDIA32"
14988  "ldhi.l	%U1, %0"
14989  [(set_attr "type" "load_media")])
14990
14991(define_insn "ldhi_q"
14992  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14993	(zero_extract:DI
14994	 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
14995				  (const_int 7))
14996			  (const_int -7)))
14997	 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
14998	 (const_int 0)))]
14999  "TARGET_SHMEDIA32"
15000  "ldhi.q	%U1, %0"
15001  [(set_attr "type" "load_media")])
15002
15003(define_insn_and_split "*ldhi_q_comb0"
15004  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15005	(zero_extract:DI
15006	 (mem:DI (plus:SI (ior:SI (plus:SI
15007				    (match_operand:SI 1 "register_operand" "r")
15008				    (match_operand:SI 2 "ua_offset" "I06"))
15009				  (const_int 7))
15010			  (const_int -7)))
15011	 (plus:SI (and:SI (match_dup 1) (const_int 7))
15012		  (const_int 1))
15013	 (const_int 0)))]
15014  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15015  "#"
15016  ""
15017  [(pc)]
15018{
15019  emit_insn (gen_ldhi_q (operands[0],
15020			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15021  DONE;
15022})
15023
15024(define_insn_and_split "*ldhi_q_comb1"
15025  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15026	(zero_extract:DI
15027	 (mem:DI (plus:SI (ior:SI (plus:SI
15028				    (match_operand:SI 1 "register_operand" "r")
15029				    (match_operand:SI 2 "ua_offset" "I06"))
15030				  (const_int 7))
15031			  (const_int -7)))
15032	 (plus:SI (and:SI (plus:SI (match_dup 1)
15033				   (match_operand:SI 3 "ua_offset" "I06"))
15034			  (const_int 7))
15035		  (const_int 1))
15036	 (const_int 0)))]
15037  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15038   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15039  "#"
15040  ""
15041  [(pc)]
15042{
15043  emit_insn (gen_ldhi_q (operands[0],
15044			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15045  DONE;
15046})
15047
15048(define_insn "ldlo_l"
15049  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15050	(zero_extract:SI
15051	 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15052			 (const_int -4)))
15053	 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
15054	 (and:SI (match_dup 1) (const_int 3))))]
15055  "TARGET_SHMEDIA32"
15056  "ldlo.l	%U1, %0"
15057  [(set_attr "type" "load_media")])
15058
15059(define_insn "ldlo_q"
15060  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15061	(zero_extract:DI
15062	 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15063			 (const_int -8)))
15064	 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15065	 (and:SI (match_dup 1) (const_int 7))))]
15066  "TARGET_SHMEDIA32"
15067  "ldlo.q	%U1, %0"
15068  [(set_attr "type" "load_media")])
15069
15070(define_insn_and_split "*ldlo_q_comb0"
15071  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15072	(zero_extract:DI
15073	 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15074				  (match_operand:SI 2 "ua_offset" "I06"))
15075			 (const_int -8)))
15076	 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15077	 (and:SI (match_dup 1) (const_int 7))))]
15078  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15079  "#"
15080  ""
15081  [(pc)]
15082{
15083  emit_insn (gen_ldlo_q (operands[0],
15084			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15085  DONE;
15086})
15087
15088(define_insn_and_split "*ldlo_q_comb1"
15089  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15090	(zero_extract:DI
15091	 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15092				  (match_operand:SI 2 "ua_offset" "I06"))
15093			 (const_int -8)))
15094	 (minus:SI (const_int 8)
15095		   (and:SI (plus:SI (match_dup 1)
15096				    (match_operand:SI 3 "ua_offset" "I06"))
15097			   (const_int 7)))
15098	 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
15099  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15100   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15101  "#"
15102  ""
15103  [(pc)]
15104{
15105  emit_insn (gen_ldlo_q (operands[0],
15106			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15107  DONE;
15108})
15109
15110(define_insn "sthi_l"
15111  [(set (zero_extract:SI
15112	 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15113				  (const_int 3))
15114			  (const_int -3)))
15115	 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
15116	 (const_int 0))
15117	(match_operand:SI 1 "arith_reg_operand" "r"))]
15118  "TARGET_SHMEDIA32"
15119  "sthi.l	%U0, %1"
15120  [(set_attr "type" "ustore_media")])
15121
15122;; All unaligned stores are considered to be 'narrow' because they typically
15123;; operate on less that a quadword, and when they operate on a full quadword,
15124;; the vanilla store high / store low sequence will cause a stall if not
15125;; scheduled apart.
15126(define_insn "sthi_q"
15127  [(set (zero_extract:DI
15128	 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15129				  (const_int 7))
15130			  (const_int -7)))
15131	 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15132	 (const_int 0))
15133	(match_operand:DI 1 "arith_reg_operand" "r"))]
15134  "TARGET_SHMEDIA32"
15135  "sthi.q	%U0, %1"
15136  [(set_attr "type" "ustore_media")])
15137
15138(define_insn_and_split "*sthi_q_comb0"
15139  [(set (zero_extract:DI
15140	 (mem:DI (plus:SI (ior:SI (plus:SI
15141				    (match_operand:SI 0 "register_operand" "r")
15142				    (match_operand:SI 1 "ua_offset" "I06"))
15143				  (const_int 7))
15144			  (const_int -7)))
15145	 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15146	 (const_int 0))
15147	(match_operand:DI 2 "arith_reg_operand" "r"))]
15148  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15149  "#"
15150  ""
15151  [(pc)]
15152{
15153  emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15154			 operands[2]));
15155  DONE;
15156})
15157
15158(define_insn_and_split "*sthi_q_comb1"
15159  [(set (zero_extract:DI
15160	 (mem:DI (plus:SI (ior:SI (plus:SI
15161				    (match_operand:SI 0 "register_operand" "r")
15162				    (match_operand:SI 1 "ua_offset" "I06"))
15163				  (const_int 7))
15164			  (const_int -7)))
15165	 (plus:SI (and:SI (plus:SI (match_dup 0)
15166				   (match_operand:SI 2 "ua_offset" "I06"))
15167			  (const_int 7))
15168		  (const_int 1))
15169	 (const_int 0))
15170	(match_operand:DI 3 "arith_reg_operand" "r"))]
15171  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
15172   && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15173  "#"
15174  ""
15175  [(pc)]
15176{
15177  emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15178			 operands[3]));
15179  DONE;
15180})
15181
15182;; This is highpart user because the address is used as full 64 bit.
15183(define_insn "stlo_l"
15184  [(set (zero_extract:SI
15185	 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15186			 (const_int -4)))
15187	 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
15188	 (and:SI (match_dup 0) (const_int 3)))
15189	(match_operand:SI 1 "arith_reg_operand" "r"))]
15190  "TARGET_SHMEDIA32"
15191  "stlo.l	%U0, %1"
15192  [(set_attr "type" "ustore_media")])
15193
15194(define_insn "stlo_q"
15195  [(set (zero_extract:DI
15196	 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15197			 (const_int -8)))
15198	 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15199	 (and:SI (match_dup 0) (const_int 7)))
15200	(match_operand:DI 1 "arith_reg_operand" "r"))]
15201  "TARGET_SHMEDIA32"
15202  "stlo.q	%U0, %1"
15203  [(set_attr "type" "ustore_media")])
15204
15205(define_insn_and_split "*stlo_q_comb0"
15206  [(set (zero_extract:DI
15207	 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15208				  (match_operand:SI 1 "ua_offset" "I06"))
15209			 (const_int -8)))
15210	 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15211	 (and:SI (match_dup 0) (const_int 7)))
15212	(match_operand:DI 2 "arith_reg_operand" "r"))]
15213  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15214  "#"
15215  ""
15216  [(pc)]
15217{
15218  emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15219			 operands[2]));
15220  DONE;
15221})
15222
15223(define_insn_and_split "*stlo_q_comb1"
15224  [(set (zero_extract:DI
15225	 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15226				  (match_operand:SI 1 "ua_offset" "I06"))
15227			 (const_int -8)))
15228	 (minus:SI (const_int 8)
15229		   (and:SI (plus:SI (match_dup 0)
15230				    (match_operand:SI 2 "ua_offset" "I06"))
15231			   (const_int 7)))
15232	 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
15233	(match_operand:DI 3 "arith_reg_operand" "r"))]
15234  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15235  "#"
15236  ""
15237  [(pc)]
15238{
15239  emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15240			 operands[3]));
15241   DONE;
15242})
15243
15244(define_insn "ldhi_l64"
15245  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15246	(zero_extract:SI
15247	 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15248				  (const_int 3))
15249			  (const_int -3)))
15250	 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
15251	 (const_int 0)))]
15252  "TARGET_SHMEDIA64"
15253  "ldhi.l	%U1, %0"
15254  [(set_attr "type" "load_media")])
15255
15256(define_insn "ldhi_q64"
15257  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15258	(zero_extract:DI
15259	 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15260				  (const_int 7))
15261			  (const_int -7)))
15262	 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
15263	 (const_int 0)))]
15264  "TARGET_SHMEDIA64"
15265  "ldhi.q	%U1, %0"
15266  [(set_attr "type" "load_media")])
15267
15268(define_insn "ldlo_l64"
15269  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15270	(zero_extract:SI
15271	 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15272			 (const_int -4)))
15273	 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
15274	 (and:DI (match_dup 1) (const_int 3))))]
15275  "TARGET_SHMEDIA64"
15276  "ldlo.l	%U1, %0"
15277  [(set_attr "type" "load_media")])
15278
15279(define_insn "ldlo_q64"
15280  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15281	(zero_extract:DI
15282	 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15283			 (const_int -8)))
15284	 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
15285	 (and:DI (match_dup 1) (const_int 7))))]
15286  "TARGET_SHMEDIA64"
15287  "ldlo.q	%U1, %0"
15288  [(set_attr "type" "load_media")])
15289
15290(define_insn "sthi_l64"
15291  [(set (zero_extract:SI
15292	 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15293				  (const_int 3))
15294			  (const_int -3)))
15295	 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
15296	 (const_int 0))
15297	(match_operand:SI 1 "arith_reg_operand" "r"))]
15298  "TARGET_SHMEDIA64"
15299  "sthi.l	%U0, %1"
15300  [(set_attr "type" "ustore_media")])
15301
15302(define_insn "sthi_q64"
15303  [(set (zero_extract:DI
15304	 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15305				  (const_int 7))
15306			  (const_int -7)))
15307	 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
15308	 (const_int 0))
15309	(match_operand:DI 1 "arith_reg_operand" "r"))]
15310  "TARGET_SHMEDIA64"
15311  "sthi.q	%U0, %1"
15312  [(set_attr "type" "ustore_media")])
15313
15314(define_insn "stlo_l64"
15315  [(set (zero_extract:SI
15316	 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15317			 (const_int -4)))
15318	 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
15319	 (and:DI (match_dup 0) (const_int 3)))
15320	(match_operand:SI 1 "arith_reg_operand" "r"))]
15321  "TARGET_SHMEDIA64"
15322  "stlo.l	%U0, %1"
15323  [(set_attr "type" "ustore_media")])
15324
15325(define_insn "stlo_q64"
15326  [(set (zero_extract:DI
15327	 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15328			 (const_int -8)))
15329	 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
15330	 (and:DI (match_dup 0) (const_int 7)))
15331	(match_operand:DI 1 "arith_reg_operand" "r"))]
15332  "TARGET_SHMEDIA64"
15333  "stlo.q	%U0, %1"
15334  [(set_attr "type" "ustore_media")])
15335
15336(define_insn "nsb"
15337  [(set (match_operand:QI 0 "arith_reg_dest" "=r")
15338	(unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15339		   UNSPEC_NSB))]
15340  "TARGET_SHMEDIA"
15341  "nsb	%1, %0"
15342  [(set_attr "type" "arith_media")])
15343
15344(define_insn "nsbsi"
15345  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15346	(zero_extend:SI
15347	 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15348		    UNSPEC_NSB)))]
15349  "TARGET_SHMEDIA"
15350  "nsb	%1, %0"
15351  [(set_attr "type" "arith_media")])
15352
15353(define_insn "nsbdi"
15354  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15355	(zero_extend:DI
15356	 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15357		    UNSPEC_NSB)))]
15358  "TARGET_SHMEDIA"
15359  "nsb	%1, %0"
15360  [(set_attr "type" "arith_media")])
15361
15362(define_expand "ffsdi2"
15363  [(set (match_operand:DI 0 "arith_reg_dest" "")
15364	(ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
15365  "TARGET_SHMEDIA"
15366{
15367  rtx scratch = gen_reg_rtx (DImode);
15368  rtx last;
15369
15370  emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
15371  emit_insn (gen_xordi3 (scratch, operands[1], scratch));
15372  emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
15373  emit_insn (gen_nsbdi (scratch, scratch));
15374  emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
15375  emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
15376  last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
15377  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
15378
15379  DONE;
15380})
15381
15382(define_expand "ffssi2"
15383  [(set (match_operand:SI 0 "arith_reg_dest" "")
15384	(ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
15385  "TARGET_SHMEDIA"
15386{
15387  rtx scratch = gen_reg_rtx (SImode);
15388  rtx discratch = gen_reg_rtx (DImode);
15389  rtx last;
15390
15391  emit_insn (gen_adddi3 (discratch,
15392			 simplify_gen_subreg (DImode, operands[1], SImode, 0),
15393			 constm1_rtx));
15394  emit_insn (gen_andcdi3 (discratch,
15395			  simplify_gen_subreg (DImode, operands[1], SImode, 0),
15396			  discratch));
15397  emit_insn (gen_nsbsi (scratch, discratch));
15398  last = emit_insn (gen_subsi3 (operands[0],
15399				force_reg (SImode, GEN_INT (63)), scratch));
15400  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
15401
15402  DONE;
15403})
15404
15405(define_insn "byterev"
15406  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15407	(vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
15408			 (parallel [(const_int 7) (const_int 6) (const_int 5)
15409				    (const_int 4) (const_int 3) (const_int 2)
15410				    (const_int 1) (const_int 0)])))]
15411  "TARGET_SHMEDIA"
15412  "byterev	%1, %0"
15413  [(set_attr "type" "arith_media")])
15414
15415;; In user mode, the "pref" instruction will raise a RADDERR exception
15416;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
15417;; implementation of __builtin_prefetch for VxWorks RTPs.
15418(define_expand "prefetch"
15419  [(prefetch (match_operand 0 "address_operand" "")
15420	     (match_operand:SI 1 "const_int_operand" "")
15421	     (match_operand:SI 2 "const_int_operand" ""))]
15422  "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
15423   && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
15424
15425(define_insn "*prefetch"
15426  [(prefetch (match_operand:SI 0 "register_operand" "r")
15427	     (match_operand:SI 1 "const_int_operand" "n")
15428	     (match_operand:SI 2 "const_int_operand" "n"))]
15429  "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
15430  "pref	@%0"
15431  [(set_attr "type" "other")])
15432
15433(define_insn "*prefetch_media"
15434  [(prefetch (match_operand:QI 0 "address_operand" "p")
15435	     (match_operand:SI 1 "const_int_operand" "n")
15436	     (match_operand:SI 2 "const_int_operand" "n"))]
15437  "TARGET_SHMEDIA"
15438{
15439  operands[0] = gen_rtx_MEM (QImode, operands[0]);
15440  output_asm_insn ("ld%M0.b	%m0,r63", operands);
15441  return "";
15442}
15443  [(set_attr "type" "other")])
15444
15445(define_insn "alloco_i"
15446  [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
15447	(unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
15448  "TARGET_SHMEDIA32"
15449{
15450  rtx xops[2];
15451
15452  if (GET_CODE (operands[0]) == PLUS)
15453    {
15454      xops[0] = XEXP (operands[0], 0);
15455      xops[1] = XEXP (operands[0], 1);
15456    }
15457  else
15458    {
15459      xops[0] = operands[0];
15460      xops[1] = const0_rtx;
15461    }
15462  output_asm_insn ("alloco	%0, %1", xops);
15463  return "";
15464}
15465  [(set_attr "type" "other")])
15466
15467(define_split
15468  [(set (match_operand 0 "any_register_operand" "")
15469	(match_operand 1 "" ""))]
15470  "TARGET_SHMEDIA && reload_completed"
15471  [(set (match_dup 0) (match_dup 1))]
15472{
15473  int n_changes = 0;
15474
15475  for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
15476  if (!n_changes)
15477    FAIL;
15478})
15479
15480;; -------------------------------------------------------------------------
15481;; Stack Protector Patterns
15482;; -------------------------------------------------------------------------
15483
15484(define_expand "stack_protect_set"
15485  [(set (match_operand 0 "memory_operand" "")
15486	(match_operand 1 "memory_operand" ""))]
15487  ""
15488{
15489  if (TARGET_SHMEDIA)
15490    {
15491      if (TARGET_SHMEDIA64)
15492	emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
15493      else
15494	emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
15495    }
15496  else
15497    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
15498
15499  DONE;
15500})
15501
15502(define_insn "stack_protect_set_si"
15503  [(set (match_operand:SI 0 "memory_operand" "=m")
15504	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15505   (set (match_scratch:SI 2 "=&r") (const_int 0))]
15506  "!TARGET_SHMEDIA"
15507{
15508  return       "mov.l	%1,%2"	"\n"
15509	 "	mov.l	%2,%0"	"\n"
15510	 "	mov	#0,%2";
15511}
15512  [(set_attr "type" "other")
15513   (set_attr "length" "6")])
15514
15515(define_insn "stack_protect_set_si_media"
15516  [(set (match_operand:SI 0 "memory_operand" "=m")
15517	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15518   (set (match_scratch:SI 2 "=&r") (const_int 0))]
15519  "TARGET_SHMEDIA"
15520{
15521  return       "ld%M1.l	%m1,%2"	"\n"
15522	 "	st%M0.l	%m0,%2"	"\n"
15523	 "	movi	0,%2";
15524}
15525  [(set_attr "type" "other")
15526   (set_attr "length" "12")])
15527
15528(define_insn "stack_protect_set_di_media"
15529  [(set (match_operand:DI 0 "memory_operand" "=m")
15530	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15531   (set (match_scratch:DI 2 "=&r") (const_int 0))]
15532  "TARGET_SHMEDIA64"
15533{
15534  return       "ld%M1.q	%m1,%2"	"\n"
15535	 "	st%M0.q	%m0,%2"	"\n"
15536	 "	movi	0,%2";
15537}
15538  [(set_attr "type" "other")
15539   (set_attr "length" "12")])
15540
15541(define_expand "stack_protect_test"
15542  [(match_operand 0 "memory_operand" "")
15543   (match_operand 1 "memory_operand" "")
15544   (match_operand 2 "" "")]
15545  ""
15546{
15547  if (TARGET_SHMEDIA)
15548    {
15549      rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
15550      rtx test;
15551
15552      test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
15553      if (TARGET_SHMEDIA64)
15554	{
15555	  emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
15556						      operands[1]));
15557	  emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
15558	}
15559      else
15560	{
15561	  emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
15562						      operands[1]));
15563	  emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
15564	}
15565    }
15566  else
15567    {
15568      emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
15569      emit_jump_insn (gen_branch_true (operands[2]));
15570    }
15571
15572  DONE;
15573})
15574
15575(define_insn "stack_protect_test_si"
15576  [(set (reg:SI T_REG)
15577	(unspec:SI [(match_operand:SI 0 "memory_operand" "m")
15578		    (match_operand:SI 1 "memory_operand" "m")]
15579		   UNSPEC_SP_TEST))
15580  (set (match_scratch:SI 2 "=&r") (const_int 0))
15581  (set (match_scratch:SI 3 "=&r") (const_int 0))]
15582  "!TARGET_SHMEDIA"
15583{
15584  return       "mov.l	%0,%2"	"\n"
15585	 "	mov.l	%1,%3"	"\n"
15586	 "	cmp/eq	%2,%3"	"\n"
15587	 "	mov	#0,%2"	"\n"
15588	 "	mov	#0,%3";
15589}
15590  [(set_attr "type" "other")
15591   (set_attr "length" "10")])
15592
15593(define_insn "stack_protect_test_si_media"
15594  [(set (match_operand:SI 0 "register_operand" "=&r")
15595	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")
15596		    (match_operand:SI 2 "memory_operand" "m")]
15597		   UNSPEC_SP_TEST))
15598  (set (match_scratch:SI 3 "=&r") (const_int 0))]
15599  "TARGET_SHMEDIA"
15600{
15601  return       "ld%M1.l	%m1,%0"		"\n"
15602	 "	ld%M2.l	%m2,%3"		"\n"
15603	 "	cmpeq	%0,%3,%0"	"\n"
15604	 "	movi	0,%3";
15605}
15606  [(set_attr "type" "other")
15607   (set_attr "length" "16")])
15608
15609(define_insn "stack_protect_test_di_media"
15610  [(set (match_operand:DI 0 "register_operand" "=&r")
15611	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")
15612		    (match_operand:DI 2 "memory_operand" "m")]
15613		   UNSPEC_SP_TEST))
15614  (set (match_scratch:DI 3 "=&r") (const_int 0))]
15615  "TARGET_SHMEDIA64"
15616{
15617  return       "ld%M1.q	%m1,%0"		"\n"
15618	 "	ld%M2.q	%m2,%3"		"\n"
15619	 "	cmpeq	%0,%3,%0"	"\n"
15620	 "	movi	0,%3";
15621}
15622  [(set_attr "type" "other")
15623   (set_attr "length" "16")])
15624
15625;; -------------------------------------------------------------------------
15626;; Atomic operations
15627;; -------------------------------------------------------------------------
15628
15629(include "sync.md")
15630