sh.md revision 1.5
1;;- Machine description for Renesas / SuperH SH.
2;;  Copyright (C) 1993-2015 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;; BSR is not generated by the compiler proper, but when relaxing, it
35;; generates .uses pseudo-ops that allow linker relaxation to create
36;; BSR.  This is actually implemented in bfd/{coff,elf32}-sh.c
37
38;; Special constraints for SH machine description:
39;;
40;;    t -- T
41;;    x -- mac
42;;    l -- pr
43;;    z -- r0
44;;
45;; Special formats used for outputting SH instructions:
46;;
47;;   %.  --  print a .s if insn needs delay slot
48;;   %@  --  print rte/rts if is/isn't an interrupt function
49;;   %#  --  output a nop if there is nothing to put in the delay slot
50;;   %O  --  print a constant without the #
51;;   %R  --  print the lsw reg of a double
52;;   %S  --  print the msw reg of a double
53;;   %T  --  print next word of a double REG or MEM
54;;
55;; Special predicates:
56;;
57;;  arith_operand          -- operand is valid source for arithmetic op
58;;  arith_reg_operand      -- operand is valid register for arithmetic op
59;;  general_movdst_operand -- operand is valid move destination
60;;  general_movsrc_operand -- operand is valid move source
61;;  logical_operand        -- operand is valid source for logical op
62
63;; -------------------------------------------------------------------------
64;; Constants
65;; -------------------------------------------------------------------------
66
67(define_constants [
68  (AP_REG	145)
69  (PR_REG	146)
70  (T_REG	147)
71  (GBR_REG	144)
72  (MACH_REG	148)
73  (MACL_REG	149)
74  (FPUL_REG	150)
75  (RAP_REG	152)
76
77  (FPSCR_REG	151)
78
79  ;; Virtual FPSCR - bits that are used by FP ops.
80  (FPSCR_MODES_REG 154)
81
82  ;; Virtual FPSCR - bits that are updated by FP ops.
83  (FPSCR_STAT_REG 155)
84
85  (PIC_REG	12)
86  (FP_REG	14)
87  (SP_REG	15)
88
89  (PR_MEDIA_REG	18)
90  (T_MEDIA_REG	19)
91
92  (R0_REG	0)
93  (R1_REG	1)
94  (R2_REG	2)
95  (R3_REG	3)
96  (R4_REG	4)
97  (R5_REG	5)
98  (R6_REG	6)
99  (R7_REG	7)
100  (R8_REG	8)
101  (R9_REG	9)
102  (R10_REG	10)
103  (R20_REG	20)
104  (R21_REG	21)
105  (R22_REG	22)
106  (R23_REG	23)
107
108  (DR0_REG	64)
109  (DR2_REG	66)
110  (DR4_REG	68)
111  (FR23_REG	87)
112
113  (TR0_REG	128)
114  (TR1_REG	129)
115  (TR2_REG	130)
116
117  (XD0_REG	136)
118
119  (FPSCR_PR	524288)  ;; 1 << 19
120  (FPSCR_SZ	1048576) ;; 1 << 20
121  (FPSCR_FR	2097152) ;; 1 << 21
122])
123
124(define_c_enum "unspec" [
125  ;; These are used with unspec.
126  UNSPEC_COMPACT_ARGS
127  UNSPEC_MOVA
128  UNSPEC_CASESI
129  UNSPEC_DATALABEL
130  UNSPEC_BBR
131  UNSPEC_SFUNC
132  UNSPEC_PIC
133  UNSPEC_GOT
134  UNSPEC_GOTOFF
135  UNSPEC_PLT
136  UNSPEC_CALLER
137  UNSPEC_GOTPLT
138  UNSPEC_ICACHE
139  UNSPEC_INIT_TRAMP
140  UNSPEC_FCOSA
141  UNSPEC_FSRRA
142  UNSPEC_FSINA
143  UNSPEC_NSB
144  UNSPEC_ALLOCO
145  UNSPEC_TLSGD
146  UNSPEC_TLSLDM
147  UNSPEC_TLSIE
148  UNSPEC_DTPOFF
149  UNSPEC_GOTTPOFF
150  UNSPEC_TPOFF
151  UNSPEC_RA
152  UNSPEC_DIV_INV_M0
153  UNSPEC_DIV_INV_M1
154  UNSPEC_DIV_INV_M2
155  UNSPEC_DIV_INV_M3
156  UNSPEC_DIV_INV20
157  UNSPEC_DIV_INV_TABLE
158  UNSPEC_ASHIFTRT
159  UNSPEC_THUNK
160  UNSPEC_CHKADD
161  UNSPEC_SP_SET
162  UNSPEC_SP_TEST
163  UNSPEC_MOVUA
164  ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
165  ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
166  UNSPEC_EXTRACT_S16
167  UNSPEC_EXTRACT_U16
168  ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
169  UNSPEC_SYMOFF
170  ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
171  UNSPEC_PCREL_SYMOFF
172  ;; Misc builtins
173  UNSPEC_BUILTIN_STRLEN
174])
175
176(define_c_enum "unspecv" [
177  ;; These are used with unspec_volatile.
178  UNSPECV_BLOCKAGE
179  UNSPECV_ALIGN
180  UNSPECV_CONST2
181  UNSPECV_CONST4
182  UNSPECV_CONST8
183  UNSPECV_WINDOW_END
184  UNSPECV_CONST_END
185  UNSPECV_EH_RETURN
186  UNSPECV_GBR
187  UNSPECV_SP_SWITCH_B
188  UNSPECV_SP_SWITCH_E
189
190  UNSPECV_FPSCR_MODES
191  UNSPECV_FPSCR_STAT
192])
193
194;; -------------------------------------------------------------------------
195;; Attributes
196;; -------------------------------------------------------------------------
197
198;; Target CPU.
199
200(define_attr "cpu"
201 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
202  (const (symbol_ref "sh_cpu_attr")))
203
204(define_attr "endian" "big,little"
205 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
206		      (const_string "little") (const_string "big"))))
207
208;; Indicate if the default fpu mode is single precision.
209(define_attr "fpu_single" "yes,no"
210  (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
211		       (const_string "yes") (const_string "no"))))
212
213(define_attr "fmovd" "yes,no"
214  (const (if_then_else (symbol_ref "TARGET_FMOVD")
215		       (const_string "yes") (const_string "no"))))
216;; pipeline model
217(define_attr "pipe_model" "sh1,sh4,sh5media"
218  (const
219   (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
220          (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
221         (const_string "sh1"))))
222
223;; cbranch	conditional branch instructions
224;; jump		unconditional jumps
225;; arith	ordinary arithmetic
226;; arith3	a compound insn that behaves similarly to a sequence of
227;;		three insns of type arith
228;; arith3b	like above, but might end with a redirected branch
229;; load		from memory
230;; load_si	Likewise, SImode variant for general register.
231;; fload	Likewise, but load to fp register.
232;; store	to memory
233;; fstore	floating point register to memory
234;; move		general purpose register to register
235;; movi8	8-bit immediate to general purpose register
236;; mt_group	other sh4 mt instructions
237;; fmove	register to register, floating point
238;; smpy		word precision integer multiply
239;; dmpy		longword or doublelongword precision integer multiply
240;; return	rts
241;; pload	load of pr reg, which can't be put into delay slot of rts
242;; prset	copy register to pr reg, ditto
243;; pstore	store of pr reg, which can't be put into delay slot of jsr
244;; prget	copy pr to register, ditto
245;; pcload	pc relative load of constant value
246;; pcfload	Likewise, but load to fp register.
247;; pcload_si	Likewise, SImode variant for general register.
248;; rte		return from exception
249;; sfunc	special function call with known used registers
250;; call		function call
251;; fp		floating point
252;; fpscr_toggle	toggle a bit in the fpscr
253;; fdiv		floating point divide (or square root)
254;; gp_fpul	move from general purpose register to fpul
255;; fpul_gp	move from fpul to general purpose register
256;; mac_gp	move from mac[lh] to general purpose register
257;; gp_mac	move from general purpose register to mac[lh]
258;; mac_mem	move from mac[lh] to memory
259;; mem_mac	move from memory to mac[lh]
260;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
261;; ftrc_s	fix_truncsfsi2_i4
262;; dfdiv	double precision floating point divide (or square root)
263;; cwb		ic_invalidate_line_i
264;; movua	SH4a unaligned load
265;; fsrra	square root reciprocal approximate
266;; fsca		sine and cosine approximate
267;; tls_load     load TLS related address
268;; arith_media	SHmedia arithmetic, logical, and shift instructions
269;; cbranch_media SHmedia conditional branch instructions
270;; cmp_media	SHmedia compare instructions
271;; dfdiv_media	SHmedia double precision divide and square root
272;; dfmul_media	SHmedia double precision multiply instruction
273;; dfparith_media SHmedia double precision floating point arithmetic
274;; dfpconv_media SHmedia double precision floating point conversions
275;; dmpy_media	SHmedia longword multiply
276;; fcmp_media	SHmedia floating point compare instructions
277;; fdiv_media	SHmedia single precision divide and square root
278;; fload_media	SHmedia floating point register load instructions
279;; fmove_media	SHmedia floating point register moves (inc. fabs and fneg)
280;; fparith_media SHmedia single precision floating point arithmetic
281;; fpconv_media	SHmedia single precision floating point conversions
282;; fstore_media	SHmedia floating point register store instructions
283;; gettr_media	SHmedia gettr instruction
284;; invalidate_line_media SHmedia invalidate_line sequence
285;; jump_media	SHmedia unconditional branch instructions
286;; load_media	SHmedia general register load instructions
287;; pt_media	SHmedia pt instruction (expanded by assembler)
288;; ptabs_media	SHmedia ptabs instruction
289;; store_media	SHmedia general register store instructions
290;; mcmp_media	SHmedia multimedia compare, absolute, saturating ops
291;; mac_media	SHmedia mac-style fixed point operations
292;; d2mpy_media	SHmedia: two 32-bit integer multiplies
293;; atrans_media	SHmedia approximate transcendental functions
294;; ustore_media	SHmedia unaligned stores
295;; nil		no-op move, will be deleted.
296
297(define_attr "type"
298 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,
299  fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,
300  prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,
301  dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,
302  gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,
303  arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,
304  dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,
305  fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,
306  jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,
307  d2mpy_media,atrans_media,ustore_media,nil,other"
308  (const_string "other"))
309
310;; We define a new attribute namely "insn_class".We use
311;; this for the DFA based pipeline description.
312;;
313;; mt_group      SH4 "mt" group instructions.
314;;
315;; ex_group      SH4 "ex" group instructions.
316;;
317;; ls_group      SH4 "ls" group instructions.
318;;
319(define_attr "insn_class"
320  "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
321  (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
322	 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
323	 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,
324			  store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
325	 (eq_attr "type" "cbranch,jump") (const_string "br_group")
326	 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
327	   (const_string "fe_group")
328	 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,
329			  prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,
330			  gp_mac,mac_mem,mem_mac") (const_string "co_group")]
331	(const_string "none")))
332
333;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
334;; so these do not belong in an insn group, although they are modeled
335;; with their own define_insn_reservations.
336
337;; Indicate what precision must be selected in fpscr for this insn, if any.
338(define_attr "fp_mode" "single,double,none" (const_string "none"))
339
340;; Indicate if the fpu mode is set by this instruction
341;; "unknown" must have the value as "none" in fp_mode, and means
342;; that the instruction/abi has left the processor in an unknown
343;; state.
344;; "none" means that nothing has changed and no mode is set.
345;; This attribute is only used for the Renesas ABI.
346(define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
347
348; If a conditional branch destination is within -252..258 bytes away
349; from the instruction it can be 2 bytes long.  Something in the
350; range -4090..4100 bytes can be 6 bytes long.  All other conditional
351; branches are initially assumed to be 16 bytes long.
352; In machine_dependent_reorg, we split all branches that are longer than
353; 2 bytes.
354
355;; The maximum range used for SImode constant pool entries is 1018.  A final
356;; instruction can add 8 bytes while only being 4 bytes in size, thus we
357;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
358;; instruction around the pool table, 2 bytes of alignment before the table,
359;; and 30 bytes of alignment after the table.  That gives a maximum total
360;; pool size of 1058 bytes.
361;; Worst case code/pool content size ratio is 1:2 (using asms).
362;; Thus, in the worst case, there is one instruction in front of a maximum
363;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
364;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
365;; If we have a forward branch, the initial table will be put after the
366;; unconditional branch.
367;;
368;; ??? We could do much better by keeping track of the actual pcloads within
369;; the branch range and in the pcload range in front of the branch range.
370
371;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
372;; inside an le.
373(define_attr "short_cbranch_p" "no,yes"
374  (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
375	 (const_string "no")
376	 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
377	 (const_string "yes")
378	 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
379	 (const_string "no")
380	 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
381	 (const_string "yes")
382	 ] (const_string "no")))
383
384(define_attr "med_branch_p" "no,yes"
385  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
386	      (const_int 1988))
387	 (const_string "yes")
388	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
389	 (const_string "no")
390	 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
391	      (const_int 8186))
392	 (const_string "yes")
393	 ] (const_string "no")))
394
395(define_attr "med_cbranch_p" "no,yes"
396  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
397	      (const_int 1986))
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 4090))
402	       (const_int 8184))
403	 (const_string "yes")
404	 ] (const_string "no")))
405
406(define_attr "braf_branch_p" "no,yes"
407  (cond [(match_test "! TARGET_SH2")
408	 (const_string "no")
409	 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
410	      (const_int 20660))
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 32764))
415	      (const_int 65530))
416	 (const_string "yes")
417	 ] (const_string "no")))
418
419(define_attr "braf_cbranch_p" "no,yes"
420  (cond [(match_test "! TARGET_SH2")
421	 (const_string "no")
422	 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
423	      (const_int 20658))
424	 (const_string "yes")
425	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
426	 (const_string "no")
427	 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
428	      (const_int 65528))
429	 (const_string "yes")
430	 ] (const_string "no")))
431
432;; An unconditional jump in the range -4092..4098 can be 2 bytes long.
433;; For wider ranges, we need a combination of a code and a data part.
434;; If we can get a scratch register for a long range jump, the code
435;; part can be 4 bytes long; otherwise, it must be 8 bytes long.
436;; If the jump is in the range -32764..32770, the data part can be 2 bytes
437;; long; otherwise, it must be 6 bytes long.
438
439;; All other instructions are two bytes long by default.
440
441;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
442;; but getattrtab doesn't understand this.
443(define_attr "length" ""
444  (cond [(eq_attr "type" "cbranch")
445	 (cond [(eq_attr "short_cbranch_p" "yes")
446		(const_int 2)
447		(eq_attr "med_cbranch_p" "yes")
448		(const_int 6)
449		(eq_attr "braf_cbranch_p" "yes")
450		(const_int 12)
451;; ??? using pc is not computed transitively.
452		(ne (match_dup 0) (match_dup 0))
453		(const_int 14)
454		(match_test "flag_pic")
455		(const_int 24)
456		] (const_int 16))
457	 (eq_attr "type" "jump")
458	 (cond [(eq_attr "med_branch_p" "yes")
459		(const_int 2)
460		(and (match_test "prev_nonnote_insn (insn)")
461		     (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
462			      (symbol_ref "INSN"))
463			  (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
464			      (symbol_ref "code_for_indirect_jump_scratch"))))
465		(cond [(eq_attr "braf_branch_p" "yes")
466		       (const_int 6)
467		       (not (match_test "flag_pic"))
468		       (const_int 10)
469		       (match_test "TARGET_SH2")
470		       (const_int 10)] (const_int 18))
471		(eq_attr "braf_branch_p" "yes")
472		(const_int 10)
473;; ??? using pc is not computed transitively.
474		(ne (match_dup 0) (match_dup 0))
475		(const_int 12)
476		(match_test "flag_pic")
477		(const_int 22)
478		] (const_int 14))
479	 (eq_attr "type" "pt_media")
480	 (if_then_else (match_test "TARGET_SHMEDIA64")
481		       (const_int 20) (const_int 12))
482	 (and (eq_attr "type" "jump_media")
483	      (match_test "TARGET_SH5_CUT2_WORKAROUND"))
484	 (const_int 8)
485	 ] (if_then_else (match_test "TARGET_SHMEDIA")
486			 (const_int 4)
487			 (const_int 2))))
488
489;; DFA descriptions for the pipelines
490
491(include "sh1.md")
492(include "shmedia.md")
493(include "sh4.md")
494
495(include "iterators.md")
496(include "predicates.md")
497(include "constraints.md")
498
499;; Definitions for filling delay slots
500
501(define_attr "needs_delay_slot" "yes,no" (const_string "no"))
502
503(define_attr "banked" "yes,no" 
504	(cond [(match_test "sh_loads_bankedreg_p (insn)")
505	       (const_string "yes")]
506	      (const_string "no")))
507
508;; ??? This should be (nil) instead of (const_int 0)
509(define_attr "hit_stack" "yes,no"
510	(cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
511	       (const_string "no")]
512	      (const_string "yes")))
513
514(define_attr "interrupt_function" "no,yes"
515  (const (symbol_ref "current_function_interrupt")))
516
517(define_attr "in_delay_slot" "yes,no"
518  (cond [(eq_attr "type" "cbranch") (const_string "no")
519	 (eq_attr "type" "pcload,pcload_si") (const_string "no")
520	 (eq_attr "type" "fpscr_toggle") (const_string "no")
521	 (eq_attr "needs_delay_slot" "yes") (const_string "no")
522	 (eq_attr "length" "2") (const_string "yes")
523	 ] (const_string "no")))
524
525(define_attr "cond_delay_slot" "yes,no"
526  (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
527	 ] (const_string "no")))
528
529(define_attr "is_sfunc" ""
530  (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
531
532(define_attr "is_mac_media" ""
533  (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
534
535(define_attr "branch_zero" "yes,no"
536  (cond [(eq_attr "type" "!cbranch") (const_string "no")
537	 (ne (symbol_ref "(next_active_insn (insn)\
538			   == (prev_active_insn\
539			       (XEXP (SET_SRC (PATTERN (insn)), 1))))\
540			  && get_attr_length (next_active_insn (insn)) == 2")
541	     (const_int 0))
542	 (const_string "yes")]
543	(const_string "no")))
544
545;; SH4 Double-precision computation with double-precision result -
546;; the two halves are ready at different times.
547(define_attr "dfp_comp" "yes,no"
548  (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
549	(const_string "no")))
550
551;; Insns for which the latency of a preceding fp insn is decreased by one.
552(define_attr "late_fp_use" "yes,no" (const_string "no"))
553;; And feeding insns for which this relevant.
554(define_attr "any_fp_comp" "yes,no"
555  (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
556	 (const_string "yes")]
557	(const_string "no")))
558
559(define_attr "any_int_load" "yes,no"
560  (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
561	 (const_string "yes")]
562	(const_string "no")))
563
564(define_attr "highpart" "user, ignore, extend, depend, must_split"
565  (const_string "user"))
566
567(define_delay
568  (eq_attr "needs_delay_slot" "yes")
569  [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
570
571;; Since a normal return (rts) implicitly uses the PR register,
572;; we can't allow PR register loads in an rts delay slot.
573;; On the SH1* and SH2*, the rte instruction reads the return pc from the
574;; stack, and thus we can't put a pop instruction in its delay slot.
575;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
576;; pop instruction can go in the delay slot, unless it references a banked
577;; register (the register bank is switched by rte).
578(define_delay
579  (eq_attr "type" "return")
580  [(and (eq_attr "in_delay_slot" "yes")
581	(ior (and (eq_attr "interrupt_function" "no")
582		  (eq_attr "type" "!pload,prset"))
583	     (and (eq_attr "interrupt_function" "yes")
584		  (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
585		  (eq_attr "banked" "no"))))
586   (nil) (nil)])
587
588;; Since a call implicitly uses the PR register, we can't allow
589;; a PR register store in a jsr delay slot.
590
591(define_delay
592  (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
593  [(and (eq_attr "in_delay_slot" "yes")
594	(eq_attr "type" "!pstore,prget")) (nil) (nil)])
595
596;; Conditional branches with delay slots are available starting with SH2.
597(define_delay
598  (and (eq_attr "type" "cbranch") (match_test "TARGET_SH2"))
599  [(eq_attr "cond_delay_slot" "yes") (nil) (nil)])
600
601;; -------------------------------------------------------------------------
602;; SImode signed integer comparisons
603;; -------------------------------------------------------------------------
604
605;; Patterns to generate the tst instruction which are usually formed by
606;; the combine pass.
607;; The canonical form here being used is (eq (and (op) (op)) 0).
608;; For some bit patterns, such as contiguous bits, we also must accept
609;; zero_extract forms.  Single bit tests are also handled via zero_extract
610;; patterns in the 'bit field extract patterns' section.  All variants
611;; are eventually converted to the 'tstsi_t' insn.
612;; As long as pseudos can be created (before RA), 'tstsi_t' will also accept
613;; constants that won't fit into 8 bits.  After having captured the constant
614;; we can decide better whether/how to load it into a register and do other
615;; post-combine optimizations such as bypassing sign/zero extensions.
616(define_insn_and_split "tstsi_t"
617  [(set (reg:SI T_REG)
618	(eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "%z,r")
619		       (match_operand:SI 1 "arith_or_int_operand" "K08,r"))
620	       (const_int 0)))]
621  "TARGET_SH1
622   && (can_create_pseudo_p () || arith_reg_operand (operands[1], SImode)
623       || satisfies_constraint_K08 (operands[1]))"
624  "tst	%1,%0"
625  "TARGET_SH1 && can_create_pseudo_p () && CONST_INT_P (operands[1])
626   && !sh_in_recog_treg_set_expr ()"
627  [(const_int 0)]
628{
629  gcc_assert (CONST_INT_P (operands[1]));
630
631  HOST_WIDE_INT op1val = INTVAL (operands[1]);
632  bool op0_dead_after_this =
633	sh_reg_dead_or_unused_after_insn (curr_insn, REGNO (operands[0]));
634
635  if (optimize)
636    {
637      if (dump_file)
638	fprintf (dump_file,
639		 "tstsi_t: trying to optimize const_int 0x%08x\n",
640		 (uint32_t)op1val);
641
642      /* See if we can convert a test with a reg and a constant into
643	 something simpler, if the reg is known to be zero or sign
644	 extended.  */
645      sh_extending_set_of_reg eop0 = sh_find_extending_set_of_reg (operands[0],
646								   curr_insn);
647      if (eop0.ext_code != UNKNOWN)
648	{
649	  /* Adjust the constant, trying to eliminate bits that are not
650	     contributing to the result.  */
651	  if (eop0.from_mode == QImode)
652	    op1val = (op1val
653                      | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFFFF80)
654			 ? 0x80 : 0)) & 0xFF;
655	  else if (eop0.from_mode == HImode)
656	    op1val = (op1val
657		      | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFF8000)
658			 ? 0x8000 : 0)) & 0xFFFF;
659
660	  if (dump_file)
661	    fprintf (dump_file, "tstsi_t: using effective const_int: 0x%08x\n",
662		     (uint32_t)op1val);
663
664	  /* Try to bypass the sign/zero extension first if op0 dies after
665	     this insn.  */
666	  if (op0_dead_after_this && eop0.can_use_as_unextended_reg ())
667	    {
668	      if (dump_file)
669		fprintf (dump_file, "tstsi_t: bypassing sign/zero extension\n");
670
671	      operands[0] = eop0.use_as_unextended_reg (curr_insn);
672	    }
673	  else if ((eop0.from_mode == QImode && op1val == 0xFF)
674		   || (eop0.from_mode == HImode && op1val == 0xFFFF))
675	    {
676	      if (dump_file)
677		fprintf (dump_file, "tstsi_t: converting to cmpeqsi_t\n");
678	      emit_insn (gen_cmpeqsi_t (eop0.use_as_extended_reg (curr_insn),
679					const0_rtx));
680	      DONE;
681	    }
682	  else if (eop0.ext_code == SIGN_EXTEND
683		   && ((eop0.from_mode == QImode && op1val == 0x80)
684		       || (eop0.from_mode == HImode && op1val == 0x8000)))
685	    {
686	      if (dump_file)
687		fprintf (dump_file, "tstsi_t: converting to cmpgesi_t\n");
688	      emit_insn (gen_cmpgesi_t (eop0.use_as_extended_reg (curr_insn),
689					const0_rtx));
690	      DONE;
691	    }
692	  else if (!CONST_OK_FOR_K08 (op1val))
693	    {
694	      if (dump_file)
695		fprintf (dump_file, "tstsi_t: converting const_int to signed "
696			 "value\n");
697
698	      /* If here we haven't done anything yet.  Convert the constant
699		 to a signed value to reduce the constant pool size.  */
700	      operands[0] = eop0.use_as_extended_reg (curr_insn);
701
702	      if (eop0.from_mode == QImode)
703		op1val |= (op1val & 0x80) ? 0xFFFFFFFFFFFFFF00LL : 0;
704	      else if (eop0.from_mode == HImode)
705		op1val |= (op1val & 0x8000) ? 0xFFFFFFFFFFFF0000LL : 0;
706	    }
707	  else
708	    operands[0] = eop0.use_as_extended_reg (curr_insn);
709	}
710    }
711
712    if (dump_file)
713      fprintf (dump_file, "tstsi_t: using const_int 0x%08x\n",
714	       (uint32_t)op1val);
715
716  /* Try to fit the constant into 8 bits by shuffling the value in the
717     register operand.
718     Doing that usually results in smaller code as the constants in the
719     pools are avoided (32 bit constant = load + constant = 6 bytes).
720     However, if the constant load (LS insn) can be hoisted insn dependencies
721     can be avoided and chances for parallel execution increase.  The common
722     usage pattern is:
723       - load reg from mem
724       - test bits
725       - conditional branch
726
727     FIXME: For now we do that only when optimizing for size until there is
728     a better heuristic.
729
730     FIXME: If there are multiple tst insns in the block with the same
731     constant, avoid the #imm variant to avoid R0 loads.  Use the 'tst Rn,Rm'
732     variant instead and load the constant into a reg.  For that we'd need
733     to do some analysis.  */
734
735  if (CONST_OK_FOR_K08 (op1val))
736    {
737      /* Do nothing.  */
738    }
739  else if ((op1val & 0xFFFF) == 0
740	   && CONST_OK_FOR_K08 (op1val >> 16) && optimize_size)
741    {
742      /* Use a swap.w insn to do a shift + reg copy (to R0) in one insn.  */
743      op1val = op1val >> 16;
744      rtx r = gen_reg_rtx (SImode);
745      emit_insn (gen_rotlsi3_16 (r, operands[0]));
746      operands[0] = r;
747    }
748  else if ((op1val & 0xFF) == 0
749	   && CONST_OK_FOR_K08 (op1val >> 8) && optimize_size)
750    {
751      /* Use a swap.b insn to do a shift + reg copy (to R0) in one insn.  */
752      op1val = op1val >> 8;
753      rtx r = gen_reg_rtx (SImode);
754      emit_insn (gen_swapbsi2 (r, operands[0]));
755      operands[0] = r;
756    }
757  else if ((op1val & 3) == 0
758	   && CONST_OK_FOR_K08 (op1val >> 2) && optimize_size)
759    {
760      op1val = op1val >> 2;
761      rtx r = gen_reg_rtx (SImode);
762      emit_insn (gen_lshrsi3_k (r, operands[0], GEN_INT (2)));
763      operands[0] = r;
764    }
765  else if ((op1val & 1) == 0
766	   && CONST_OK_FOR_K08 (op1val >> 1) && optimize_size)
767    {
768      op1val = op1val >> 1;
769      rtx r = gen_reg_rtx (SImode);
770      emit_insn (gen_shlr (r, operands[0]));
771      operands[0] = r;
772    }
773
774  operands[1] = GEN_INT (op1val);
775
776  if (!satisfies_constraint_K08 (operands[1]))
777    operands[1] = force_reg (SImode, operands[1]);
778
779  emit_insn (gen_tstsi_t (operands[0], operands[1]));
780  DONE;
781}
782  [(set_attr "type" "mt_group")])
783
784;; This pattern is used by combine when testing QI/HImode subregs with a
785;; negative constant.  Ignore high bits by masking them out in the constant.
786(define_insn_and_split "*tst<mode>_t"
787  [(set (reg:SI T_REG)
788	(eq:SI (subreg:SI
789		 (and:QIHI (match_operand:QIHI 0 "arith_reg_operand")
790			   (match_operand 1 "const_int_operand")) 0)
791	       (const_int 0)))]
792  "TARGET_SH1 && can_create_pseudo_p ()"
793  "#"
794  "&& 1"
795  [(set (reg:SI T_REG)
796	(eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))]
797{
798  operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
799  operands[1] = GEN_INT (INTVAL (operands[1])
800			 & (<MODE>mode == HImode ? 0xFFFF : 0xFF));
801})
802
803;; This pattern might be risky because it also tests the upper bits and not
804;; only the subreg.  We have to check whether the operands have been sign
805;; or zero extended.  In the worst case, a zero extension has to be inserted
806;; to mask out the unwanted bits.
807(define_insn_and_split "*tst<mode>_t_subregs"
808  [(set (reg:SI T_REG)
809	(eq:SI
810	  (subreg:QIHI
811	    (and:SI (match_operand:SI 0 "arith_reg_operand")
812		    (match_operand:SI 1 "arith_reg_operand")) <lowpart_le>)
813	  (const_int 0)))]
814  "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()"
815  "#"
816  "&& !sh_in_recog_treg_set_expr ()"
817  [(const_int 0)]
818{
819  sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_le>, operands);
820  DONE;
821})
822
823(define_insn_and_split "*tst<mode>_t_subregs"
824  [(set (reg:SI T_REG)
825	(eq:SI
826	  (subreg:QIHI
827	    (and:SI (match_operand:SI 0 "arith_reg_operand")
828		    (match_operand:SI 1 "arith_reg_operand")) <lowpart_be>)
829	  (const_int 0)))]
830  "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()"
831  "#"
832  "&& !sh_in_recog_treg_set_expr ()"
833  [(const_int 0)]
834{
835  sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_be>, operands);
836  DONE;
837})
838
839;; Extract contiguous bits and compare them against zero.
840;; Notice that this will not be used for single bits.  Special single bit
841;; extraction patterns are in the 'bit field extract patterns' section.
842(define_insn_and_split "*tst<mode>_t_zero_extract"
843  [(set (reg:SI T_REG)
844	(eq:SI (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand")
845				(match_operand 1 "const_int_operand")
846				(match_operand 2 "const_int_operand"))
847	       (const_int 0)))]
848  "TARGET_SH1 && can_create_pseudo_p ()"
849  "#"
850  "&& 1"
851  [(set (reg:SI T_REG)
852	(eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))]
853{
854  operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
855  if (GET_MODE (operands[0]) != SImode)
856    operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
857})
858
859;; Convert '(reg << shift) & mask' into 'reg & (mask >> shift)'.
860;; The shifted-out bits in the mask will always be zero, since the
861;; shifted-in bits in the reg will also be always zero.
862(define_insn_and_split "*tstsi_t_shift_mask"
863  [(set (reg:SI T_REG)
864	(eq:SI (and:SI (ashift:SI (match_operand:SI 0 "arith_reg_operand")
865				  (match_operand 1 "const_int_operand"))
866		       (match_operand 2 "const_int_operand"))
867	       (const_int 0)))]
868  "TARGET_SH1 && can_create_pseudo_p ()"
869  "#"
870  "&& 1"
871  [(set (reg:SI T_REG)
872	(eq:SI (and:SI (match_dup 0) (match_dup 2)) (const_int 0)))]
873{
874  operands[2] = GEN_INT (INTVAL (operands[2]) >> INTVAL (operands[1]));
875})
876
877(define_insn "cmpeqsi_t"
878  [(set (reg:SI T_REG)
879	(eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
880	       (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
881  "TARGET_SH1"
882  "@
883	tst	%0,%0
884	cmp/eq	%1,%0
885	cmp/eq	%1,%0"
886  [(set_attr "type" "mt_group")])
887
888;; Sometimes combine fails to form the (eq (and (op) (op)) 0) tst insn.
889;; Try to fix that in the split1 pass by looking for the previous set
890;; of the tested op.  Also see if there is a preceeding sign/zero
891;; extension that can be avoided.
892(define_split
893  [(set (reg:SI T_REG)
894	(eq:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))]
895  "TARGET_SH1 && can_create_pseudo_p () && optimize
896   && !sh_in_recog_treg_set_expr ()"
897  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
898{
899  if (dump_file)
900    fprintf (dump_file, "cmpeqsi_t: trying to optimize const_int 0\n");
901
902  /* If the tested reg is not dead after this insn, it's probably used by
903     something else after the comparison.  It's probably better to leave
904     it as it is.  */
905  if (find_regno_note (curr_insn, REG_DEAD, REGNO (operands[0])) == NULL_RTX)
906    FAIL;
907
908  /* FIXME: Maybe also search the predecessor basic blocks to catch
909     more cases.  */
910  set_of_reg op = sh_find_set_of_reg (operands[0], curr_insn,
911				      prev_nonnote_insn_bb);
912
913  if (op.set_src != NULL && GET_CODE (op.set_src) == AND
914      && !sh_insn_operands_modified_between_p (op.insn, op.insn, curr_insn))
915    {
916      if (dump_file)
917	fprintf (dump_file, "cmpeqsi_t: found preceeding and in insn %d\n",
918		 INSN_UID (op.insn));
919
920      if (!(arith_reg_operand (XEXP (op.set_src, 0), SImode)
921	    && (arith_reg_operand (XEXP (op.set_src, 1), SImode)
922		|| CONST_INT_P (XEXP (op.set_src, 1)))))
923	FAIL;
924
925      /* Assume that the operands of the andsi insn are compatible with the
926	 operands of the tstsi_t insn, which is generally the case.  */
927      if (dump_file)
928	fprintf (dump_file, "cmpeqsi_t: replacing with tstsi_t\n");
929      emit_insn (gen_tstsi_t (XEXP (op.set_src, 0), XEXP (op.set_src, 1)));
930      DONE;
931    }
932
933  /* Converting HImode into tests against 0xFFFF tends to increase the code
934     size, as it will create constant pool entries.  Disable it for now.  */
935  const bool enable_himode = false;
936
937  /* FIXME: try to keep the (eq (reg) (const_int 0)).  Even if the zero
938     extended reg is used after this insn, if we know that _before_ the zero
939     extension the value was loaded via sign extending mem load, we can just
940     use the value of the mem load directly.  */
941  sh_extending_set_of_reg eop = sh_find_extending_set_of_reg (operands[0],
942							      curr_insn);
943
944  if (eop.ext_code != UNKNOWN
945      && (eop.from_mode == QImode || (eop.from_mode == HImode && enable_himode))
946      && eop.can_use_as_unextended_reg ()
947      && !reg_used_between_p (operands[0], eop.insn, curr_insn))
948    {
949      /* Bypass the sign/zero extension and test against the bit mask, but
950	 only if it's the only use of the sign/zero extracted value.
951	 Otherwise we'd be introducing new constants in the pool.  */
952      if (dump_file)
953	fprintf (dump_file, "cmpeqsi_t: bypassing sign/zero extension in "
954		 "insn %d and using tstsi_t\n", INSN_UID (op.insn));
955
956      emit_insn (gen_tstsi_t (
957	  eop.use_as_unextended_reg (curr_insn),
958	  GEN_INT (eop.from_mode == QImode ? 0xFF : 0xFFFF)));
959      DONE;
960    }
961
962  if (dump_file)
963    fprintf (dump_file, "cmpeqsi_t: nothing optimized\n");
964  FAIL;
965})
966
967;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
968;; pattern by itself.  What this actually does is:
969;;	x == 0: (1 >> 0-0) & 1 = 1
970;;	x != 0: (1 >> 0-x) & 1 = 0
971;; Without this the test pr51244-8.c fails on SH2A and SH4A.
972(define_insn_and_split "*cmpeqsi_t"
973  [(set (reg:SI T_REG)
974	(and:SI (lshiftrt:SI
975		  (const_int 1)
976		  (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
977		(const_int 1)))]
978  "TARGET_SH1"
979  "#"
980  "&& 1"
981  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
982
983(define_insn "cmpgtsi_t"
984  [(set (reg:SI T_REG)
985	(gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
986	       (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
987  "TARGET_SH1"
988  "@
989	cmp/pl	%0
990	cmp/gt	%1,%0"
991  [(set_attr "type" "mt_group")])
992
993(define_insn "cmpgesi_t"
994  [(set (reg:SI T_REG)
995	(ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
996	       (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
997  "TARGET_SH1"
998  "@
999	cmp/pz	%0
1000	cmp/ge	%1,%0"
1001  [(set_attr "type" "mt_group")])
1002
1003;; Recombine a cmp/pz followed by a nott into a shll.
1004;; On non-SH2A recombine a cmp/pz followed by a movrt into shll-movt.
1005;; On SH2A cmp/pz-movrt is slightly better, as it does not mutate the input.
1006(define_split
1007  [(set (reg:SI T_REG)
1008	(ge:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))]
1009
1010  "TARGET_SH1 && can_create_pseudo_p () && optimize
1011   && !sh_in_recog_treg_set_expr ()"
1012  [(const_int 0)]
1013{
1014  if (dump_file)
1015    fprintf (dump_file, "cmpgesi_t: trying to optimize for const_int 0\n");
1016
1017  rtx_insn* i = next_nonnote_insn_bb (curr_insn);
1018
1019  if (dump_file)
1020    {
1021      fprintf (dump_file, "cmpgesi_t: following insn is \n");
1022      print_rtl_single (dump_file, i);
1023      fprintf (dump_file, "\n");
1024    }
1025
1026  if (sh_is_nott_insn (i))
1027    {
1028      if (dump_file)
1029	fprintf (dump_file,
1030		 "cmpgesi_t: replacing (cmp/pz, nott) with (shll)\n");
1031      emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
1032      set_insn_deleted (i);
1033      DONE;
1034    }
1035
1036  /* On non-SH2A negc is used as movrt replacement, which sets T = 1.
1037     Thus we can remove it only if T is marked as dead afterwards.  */
1038  if (rtx dest_reg = !TARGET_SH2A
1039		     && sh_reg_dead_or_unused_after_insn (i, T_REG)
1040		     ? sh_movrt_set_dest (i) : NULL)
1041    {
1042      if (dump_file)
1043	fprintf (dump_file,
1044		 "cmpgesi_t: replacing (cmp/pz, movrt) with (shll, movt)\n");
1045      emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
1046      add_reg_note (emit_insn (gen_movt (dest_reg, get_t_reg_rtx ())),
1047		    REG_DEAD, get_t_reg_rtx ());
1048      set_insn_deleted (i);
1049      DONE;
1050    }
1051
1052  if (dump_file)
1053    fprintf (dump_file, "cmpgesi_t: nothing optimized\n");
1054
1055  FAIL;
1056})
1057
1058;; FIXME: This is actually wrong.  There is no way to literally move a
1059;; general reg to t reg.  Luckily, it seems that this pattern will be only
1060;; used when the general reg is known be either '0' or '1' during combine.
1061;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
1062;; Due to interactions with other patterns, combine fails to pick the latter
1063;; and invert the dependent logic.
1064(define_insn "*negtstsi"
1065  [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
1066  "TARGET_SH1 && !sh_in_recog_treg_set_expr ()"
1067  "cmp/pl	%0"
1068  [(set_attr "type" "mt_group")])
1069
1070;; Some integer sign comparison patterns can be realized with the div0s insn.
1071;;	div0s	Rm,Rn		T = (Rm >> 31) ^ (Rn >> 31)
1072;;
1073;; The 'cmp_div0s' pattern is our canonical form, into which all the other
1074;; variations are converted.  The negative forms will split into a trailing
1075;; nott sequence, which will be eliminated either by the
1076;; 'any_treg_expr_to_reg' pattern, or by the 'sh_treg_combine' pass.
1077(define_insn "cmp_div0s"
1078  [(set (reg:SI T_REG)
1079	(lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
1080			     (match_operand:SI 1 "arith_reg_operand" "r"))
1081		     (const_int 31)))]
1082  "TARGET_SH1"
1083  "div0s	%0,%1"
1084  [(set_attr "type" "arith")])
1085
1086(define_insn_and_split "*cmp_div0s_1"
1087  [(set (reg:SI T_REG)
1088	(xor:SI (ge:SI (match_operand:SI 0 "arith_reg_operand")
1089		       (const_int 0))
1090		(ge:SI (match_operand:SI 1 "arith_reg_operand")
1091		       (const_int 0))))]
1092  "TARGET_SH1 && can_create_pseudo_p ()"
1093  "#"
1094  "&& 1"
1095  [(set (reg:SI T_REG)
1096	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))])
1097
1098(define_insn_and_split "*cmp_div0s_2"
1099  [(set (reg:SI T_REG)
1100	(eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
1101			    (const_int 31))
1102	       (ge:SI (match_operand:SI 1 "arith_reg_operand")
1103		      (const_int 0))))]
1104  "TARGET_SH1 && can_create_pseudo_p ()"
1105  "#"
1106  "&& 1"
1107  [(set (reg:SI T_REG)
1108	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))])
1109
1110(define_insn_and_split "*cmp_div0s_3"
1111  [(set (reg:SI T_REG)
1112	(eq:SI (ge:SI (match_operand:SI 0 "arith_reg_operand")
1113		      (const_int 0))
1114	       (ge:SI (match_operand:SI 1 "arith_reg_operand")
1115		      (const_int 0))))]
1116  "TARGET_SH1 && can_create_pseudo_p ()"
1117  "#"
1118  "&& 1"
1119  [(set (reg:SI T_REG)
1120	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1121   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1122
1123(define_insn_and_split "*cmp_div0s_4"
1124  [(set (reg:SI T_REG)
1125	(ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand")
1126		       (match_operand:SI 1 "arith_reg_operand"))
1127	       (const_int 0)))]
1128  "TARGET_SH1 && can_create_pseudo_p ()"
1129  "#"
1130  "&& 1"
1131  [(set (reg:SI T_REG)
1132	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1133   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1134
1135(define_insn_and_split "*cmp_div0s_5"
1136  [(set (reg:SI T_REG)
1137	(xor:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
1138			     (const_int 31))
1139		(ge:SI (match_operand:SI 1 "arith_reg_operand")
1140		       (const_int 0))))]
1141  "TARGET_SH1 && can_create_pseudo_p ()"
1142  "#"
1143  "&& 1"
1144  [(set (reg:SI T_REG)
1145	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1146   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1147
1148(define_insn_and_split "*cmp_div0s_6"
1149  [(set (reg:SI T_REG)
1150	(eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
1151			    (const_int 31))
1152	       (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
1153			    (const_int 31))))]
1154  "TARGET_SH1 && can_create_pseudo_p ()"
1155  "#"
1156  "&& 1"
1157  [(set (reg:SI T_REG)
1158	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1159   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1160
1161;; -------------------------------------------------------------------------
1162;; SImode compare and branch
1163;; -------------------------------------------------------------------------
1164
1165(define_expand "cbranchsi4"
1166  [(set (pc)
1167	(if_then_else (match_operator 0 "comparison_operator"
1168			[(match_operand:SI 1 "arith_operand" "")
1169			 (match_operand:SI 2 "arith_operand" "")])
1170		      (label_ref (match_operand 3 "" ""))
1171		      (pc)))
1172   (clobber (reg:SI T_REG))]
1173  ""
1174{
1175  if (TARGET_SHMEDIA)
1176    emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1177					   operands[2], operands[3]));
1178  else
1179    expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
1180
1181  DONE;
1182})
1183
1184;; Combine patterns to invert compare and branch operations for which we
1185;; don't have actual comparison insns.  These patterns are used in cases
1186;; which appear after the initial cbranchsi expansion, which also does
1187;; some condition inversion.
1188(define_split
1189  [(set (pc)
1190	(if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
1191			  (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1192		      (label_ref (match_operand 2))
1193		      (pc)))
1194   (clobber (reg:SI T_REG))]
1195  "TARGET_SH1"
1196  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
1197   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1198			   (label_ref (match_dup 2))
1199			   (pc)))])
1200
1201;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
1202;; and SH2A combine fails to simplify this pattern by itself.
1203;; What this actually does is:
1204;;	x == 0: (1 >> 0-0) & 1 = 1
1205;;	x != 0: (1 >> 0-x) & 1 = 0
1206;; Without this the test pr51244-8.c fails on SH2A and SH4A.
1207(define_split
1208  [(set (pc)
1209	(if_then_else
1210	  (eq (and:SI (lshiftrt:SI
1211			(const_int 1)
1212			(neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
1213		      (const_int 1))
1214	      (const_int 0))
1215	  (label_ref (match_operand 2))
1216	  (pc)))
1217   (clobber (reg:SI T_REG))]
1218  "TARGET_SH1"
1219  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
1220   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1221			   (label_ref (match_dup 2))
1222			   (pc)))])
1223
1224;; FIXME: These could probably use code iterators for the compare op.
1225(define_split
1226  [(set (pc)
1227	(if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
1228			  (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1229		      (label_ref (match_operand 2))
1230		      (pc)))
1231   (clobber (reg:SI T_REG))]
1232  "TARGET_SH1"
1233  [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
1234   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1235			   (label_ref (match_dup 2))
1236			   (pc)))])
1237
1238(define_split
1239  [(set (pc)
1240	(if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
1241			  (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1242		      (label_ref (match_operand 2))
1243		      (pc)))
1244   (clobber (reg:SI T_REG))]
1245  "TARGET_SH1"
1246  [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
1247   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1248			   (label_ref (match_dup 2))
1249			   (pc)))])
1250
1251(define_split
1252  [(set (pc)
1253	(if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
1254			   (match_operand:SI 1 "arith_reg_operand" ""))
1255		      (label_ref (match_operand 2))
1256		      (pc)))
1257   (clobber (reg:SI T_REG))]
1258  "TARGET_SH1"
1259  [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
1260   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1261			   (label_ref (match_dup 2))
1262			   (pc)))])
1263
1264(define_split
1265  [(set (pc)
1266	(if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
1267			   (match_operand:SI 1 "arith_reg_operand" ""))
1268		      (label_ref (match_operand 2))
1269		      (pc)))
1270   (clobber (reg:SI T_REG))]
1271  "TARGET_SH1"
1272  [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
1273   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1274			   (label_ref (match_dup 2))
1275			   (pc)))])
1276
1277;; -------------------------------------------------------------------------
1278;; SImode unsigned integer comparisons
1279;; -------------------------------------------------------------------------
1280
1281;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1282;; However, especially when optimizations are off (e.g. -O0) such comparisons
1283;; might remain and we have to handle them.  If the '>= 0' case wasn't
1284;; handled here, something else would just load a '0' into the second operand
1285;; and do the comparison.  We can do slightly better by just setting the
1286;; T bit to '1'.
1287(define_insn_and_split "cmpgeusi_t"
1288  [(set (reg:SI T_REG)
1289	(geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1290		(match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1291  "TARGET_SH1"
1292  "cmp/hs	%1,%0"
1293  "&& satisfies_constraint_Z (operands[1])"
1294  [(set (reg:SI T_REG) (const_int 1))]
1295  ""
1296  [(set_attr "type" "mt_group")])
1297
1298(define_insn "cmpgtusi_t"
1299  [(set (reg:SI T_REG)
1300	(gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1301		(match_operand:SI 1 "arith_reg_operand" "r")))]
1302  "TARGET_SH1"
1303  "cmp/hi	%1,%0"
1304  [(set_attr "type" "mt_group")])
1305
1306;; -------------------------------------------------------------------------
1307;; DImode compare and branch
1308;; -------------------------------------------------------------------------
1309
1310;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1311;; Therefore, we aim to have a set of three branches that go straight to the
1312;; destination, i.e. only one of them is taken at any one time.
1313;; This mechanism should also be slightly better for the sh4-200.
1314
1315(define_expand "cbranchdi4"
1316  [(set (pc)
1317	(if_then_else (match_operator 0 "comparison_operator"
1318			[(match_operand:DI 1 "arith_operand" "")
1319			 (match_operand:DI 2 "arith_operand" "")])
1320		      (label_ref (match_operand 3 "" ""))
1321		      (pc)))
1322   (clobber (match_dup 4))
1323   (clobber (reg:SI T_REG))]
1324  "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1325{
1326  enum rtx_code comparison;
1327
1328  if (TARGET_SHMEDIA)
1329    {
1330      emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1331					     operands[2], operands[3]));
1332      DONE;
1333    }
1334  else if (!TARGET_CBRANCHDI4)
1335    {
1336      sh_emit_compare_and_branch (operands, DImode);
1337      DONE;
1338    }
1339  else
1340    {
1341      if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1342	DONE;
1343
1344      comparison = prepare_cbranch_operands (operands, DImode,
1345					     LAST_AND_UNUSED_RTX_CODE);
1346      if (comparison != GET_CODE (operands[0]))
1347	operands[0]
1348	  = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1349       operands[4] = gen_rtx_SCRATCH (SImode);
1350    }
1351})
1352
1353(define_insn_and_split "cbranchdi4_i"
1354  [(set (pc)
1355	(if_then_else (match_operator 0 "comparison_operator"
1356			[(match_operand:DI 1 "arith_operand" "r,r")
1357			 (match_operand:DI 2 "arith_operand" "rN,I08")])
1358		      (label_ref (match_operand 3 "" ""))
1359		      (pc)))
1360   (clobber (match_scratch:SI 4 "=X,&r"))
1361   (clobber (reg:SI T_REG))]
1362  "TARGET_CBRANCHDI4"
1363  "#"
1364  "&& reload_completed"
1365  [(pc)]
1366{
1367  if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1368    FAIL;
1369  DONE;
1370})
1371
1372;; -------------------------------------------------------------------------
1373;; DImode signed integer comparisons
1374;; -------------------------------------------------------------------------
1375
1376(define_insn ""
1377  [(set (reg:SI T_REG)
1378	(eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1379		       (match_operand:DI 1 "arith_operand" "r"))
1380	       (const_int 0)))]
1381  "TARGET_SH1"
1382{
1383  return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1384			      insn, operands);
1385}
1386  [(set_attr "length" "6")
1387   (set_attr "type" "arith3b")])
1388
1389(define_insn "cmpeqdi_t"
1390  [(set (reg:SI T_REG)
1391	(eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1392	       (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1393  "TARGET_SH1"
1394{
1395  static const char* alt[] =
1396  {
1397       "tst	%S0,%S0"	"\n"
1398    "	bf	0f"		"\n"
1399    "	tst	%R0,%R0"	"\n"
1400    "0:",
1401
1402       "cmp/eq	%S1,%S0"	"\n"
1403    "	bf	0f"		"\n"
1404    "	cmp/eq	%R1,%R0"	"\n"
1405    "0:"
1406  };
1407  return alt[which_alternative];
1408}
1409  [(set_attr "length" "6")
1410   (set_attr "type" "arith3b")])
1411
1412(define_split
1413  [(set (reg:SI T_REG)
1414	(eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1415	       (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1416;; If we applied this split when not optimizing, it would only be
1417;; applied during the machine-dependent reorg, when no new basic blocks
1418;; may be created.
1419  "TARGET_SH1 && reload_completed && optimize"
1420  [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1421   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1422			   (label_ref (match_dup 6))
1423			   (pc)))
1424   (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1425   (match_dup 6)]
1426{
1427  operands[2] = gen_highpart (SImode, operands[0]);
1428  operands[3] = operands[1] == const0_rtx
1429		? const0_rtx
1430		: gen_highpart (SImode, operands[1]);
1431  operands[4] = gen_lowpart (SImode, operands[0]);
1432  operands[5] = gen_lowpart (SImode, operands[1]);
1433  operands[6] = gen_label_rtx ();
1434})
1435
1436(define_insn "cmpgtdi_t"
1437  [(set (reg:SI T_REG)
1438	(gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1439	       (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1440  "TARGET_SH2"
1441{
1442  static const char* alt[] =
1443  {
1444       "cmp/eq	%S1,%S0"	"\n"
1445    "	bf{.|/}s	0f"	"\n"
1446    "	cmp/gt	%S1,%S0"	"\n"
1447    "	cmp/hi	%R1,%R0"	"\n"
1448    "0:",
1449
1450        "tst	%S0,%S0"	"\n"
1451    "	bf{.|/}s	0f"	"\n"
1452    "	cmp/pl	%S0"		"\n"
1453    "	cmp/hi	%S0,%R0"	"\n"
1454    "0:"
1455  };
1456  return alt[which_alternative];
1457}
1458  [(set_attr "length" "8")
1459   (set_attr "type" "arith3")])
1460
1461(define_insn "cmpgedi_t"
1462  [(set (reg:SI T_REG)
1463	(ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1464	       (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1465  "TARGET_SH2"
1466{
1467  static const char* alt[] =
1468  {
1469       "cmp/eq	%S1,%S0"	"\n"
1470    "	bf{.|/}s	0f"	"\n"
1471    "	cmp/ge	%S1,%S0"	"\n"
1472    "	cmp/hs	%R1,%R0"	"\n"
1473    "0:",
1474
1475       "cmp/pz	%S0"
1476  };
1477  return alt[which_alternative];
1478}
1479  [(set_attr "length" "8,2")
1480   (set_attr "type" "arith3,mt_group")])
1481
1482;; -------------------------------------------------------------------------
1483;; DImode unsigned integer comparisons
1484;; -------------------------------------------------------------------------
1485
1486(define_insn "cmpgeudi_t"
1487  [(set (reg:SI T_REG)
1488	(geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1489		(match_operand:DI 1 "arith_reg_operand" "r")))]
1490  "TARGET_SH2"
1491{
1492  return       "cmp/eq	%S1,%S0"	"\n"
1493	 "	bf{.|/}s	0f"	"\n"
1494	 "	cmp/hs	%S1,%S0"	"\n"
1495	 "	cmp/hs	%R1,%R0"	"\n"
1496	 "0:";
1497}
1498  [(set_attr "length" "8")
1499   (set_attr "type" "arith3")])
1500
1501(define_insn "cmpgtudi_t"
1502  [(set (reg:SI T_REG)
1503	(gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1504		(match_operand:DI 1 "arith_reg_operand" "r")))]
1505  "TARGET_SH2"
1506{
1507  return       "cmp/eq	%S1,%S0"	"\n"
1508	 "	bf{.|/}s	0f"	"\n"
1509	 "	cmp/hi	%S1,%S0"	"\n"
1510	 "	cmp/hi	%R1,%R0"	"\n"
1511	 "0:";
1512}
1513  [(set_attr "length" "8")
1514   (set_attr "type" "arith3")])
1515
1516(define_insn "cmpeqsi_media"
1517  [(set (match_operand:SI 0 "register_operand" "=r")
1518	(eq:SI (match_operand:SI 1 "logical_operand" "%r")
1519	       (match_operand:SI 2 "cmp_operand" "Nr")))]
1520  "TARGET_SHMEDIA"
1521  "cmpeq	%1, %N2, %0"
1522  [(set_attr "type" "cmp_media")])
1523
1524(define_insn "cmpeqdi_media"
1525  [(set (match_operand:SI 0 "register_operand" "=r")
1526	(eq:SI (match_operand:DI 1 "register_operand" "%r")
1527	       (match_operand:DI 2 "cmp_operand" "Nr")))]
1528  "TARGET_SHMEDIA"
1529  "cmpeq	%1, %N2, %0"
1530  [(set_attr "type" "cmp_media")])
1531
1532(define_insn "cmpgtsi_media"
1533  [(set (match_operand:SI 0 "register_operand" "=r")
1534	(gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1535	       (match_operand:SI 2 "cmp_operand" "rN")))]
1536  "TARGET_SHMEDIA"
1537  "cmpgt	%N1, %N2, %0"
1538  [(set_attr "type" "cmp_media")])
1539
1540(define_insn "cmpgtdi_media"
1541  [(set (match_operand:SI 0 "register_operand" "=r")
1542	(gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1543	       (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1544  "TARGET_SHMEDIA"
1545  "cmpgt	%N1, %N2, %0"
1546  [(set_attr "type" "cmp_media")])
1547
1548(define_insn "cmpgtusi_media"
1549  [(set (match_operand:SI 0 "register_operand" "=r")
1550	(gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1551		(match_operand:SI 2 "cmp_operand" "rN")))]
1552  "TARGET_SHMEDIA"
1553  "cmpgtu	%N1, %N2, %0"
1554  [(set_attr "type" "cmp_media")])
1555
1556(define_insn "cmpgtudi_media"
1557  [(set (match_operand:SI 0 "register_operand" "=r")
1558	(gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1559		(match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1560  "TARGET_SHMEDIA"
1561  "cmpgtu	%N1, %N2, %0"
1562  [(set_attr "type" "cmp_media")])
1563
1564; This pattern is for combine.
1565(define_insn "*cmpne0sisi_media"
1566  [(set (match_operand:SI 0 "register_operand" "=r")
1567	(ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1568  "TARGET_SHMEDIA"
1569  "cmpgtu	%1,r63,%0"
1570  [(set_attr "type" "cmp_media")])
1571
1572;; -------------------------------------------------------------------------
1573;; Conditional move instructions
1574;; -------------------------------------------------------------------------
1575
1576;; The insn names may seem reversed, but note that cmveq performs the move
1577;; if op1 == 0, and cmvne does it if op1 != 0.
1578
1579(define_insn "movdicc_false"
1580  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1581	(if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1582			     (const_int 0))
1583	 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1584	 (match_operand:DI 3 "arith_reg_operand" "0")))]
1585  "TARGET_SHMEDIA"
1586  "cmveq	%1, %N2, %0"
1587  [(set_attr "type" "arith_media")])
1588
1589(define_insn "movdicc_true"
1590  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1591	(if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1592			     (const_int 0))
1593	 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1594	 (match_operand:DI 3 "arith_reg_operand" "0")))]
1595  "TARGET_SHMEDIA"
1596  "cmvne	%1, %N2, %0"
1597  [(set_attr "type" "arith_media")])
1598
1599(define_peephole2
1600  [(set (match_operand:DI 0 "arith_reg_dest" "")
1601	(if_then_else:DI (match_operator 3 "equality_comparison_operator"
1602			   [(match_operand:DI 1 "arith_reg_operand" "")
1603			    (const_int 0)])
1604	 (match_operand:DI 2 "arith_reg_dest" "")
1605	 (match_dup 0)))
1606   (set (match_dup 2) (match_dup 0))]
1607  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1608  [(set (match_dup 2)
1609	(if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1610{
1611  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1612				VOIDmode, operands[1], CONST0_RTX (DImode));
1613})
1614
1615(define_peephole2
1616  [(set (match_operand:DI 0 "general_movdst_operand" "")
1617	(match_operand:DI 1 "arith_reg_or_0_operand" ""))
1618   (set (match_operand:DI 2 "arith_reg_dest" "")
1619	(if_then_else:DI (match_operator 4 "equality_comparison_operator"
1620			   [(match_operand:DI 3 "arith_reg_operand" "")
1621			    (const_int 0)])
1622	 (match_dup 0)
1623	 (match_dup 2)))]
1624  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1625  [(set (match_dup 2)
1626	(if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1627  "")
1628
1629(define_expand "movdicc"
1630  [(set (match_operand:DI 0 "register_operand" "")
1631	(if_then_else:DI (match_operand 1 "comparison_operator" "")
1632			 (match_operand:DI 2 "register_operand" "")
1633			 (match_operand:DI 3 "register_operand" "")))]
1634  "TARGET_SHMEDIA"
1635{
1636  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1637      && GET_MODE (XEXP (operands[1], 0)) == DImode
1638      && XEXP (operands[1], 1) == const0_rtx)
1639    ;
1640  else
1641    {
1642      if (!can_create_pseudo_p ())
1643	FAIL;
1644
1645      operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1646					      GET_CODE (operands[1]),
1647					      XEXP (operands[1], 0),
1648					      XEXP (operands[1], 1));
1649      if (!operands[1])
1650	FAIL;
1651    }
1652})
1653
1654;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1655;; SImode to DImode.
1656(define_insn "movsicc_false"
1657  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1658	(if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1659			  (const_int 0))
1660	 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1661	 (match_operand:SI 3 "arith_reg_operand" "0")))]
1662  "TARGET_SHMEDIA"
1663  "cmveq	%1, %N2, %0"
1664  [(set_attr "type" "arith_media")])
1665
1666(define_insn "movsicc_true"
1667  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1668	(if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1669			  (const_int 0))
1670	 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1671	 (match_operand:SI 3 "arith_reg_operand" "0")))]
1672  "TARGET_SHMEDIA"
1673  "cmvne	%1, %N2, %0"
1674  [(set_attr "type" "arith_media")])
1675
1676(define_peephole2
1677  [(set (match_operand:SI 0 "arith_reg_dest" "")
1678	(if_then_else:SI (match_operator 3 "equality_comparison_operator"
1679			   [(match_operand:SI 1 "arith_reg_operand" "")
1680			    (const_int 0)])
1681	 (match_operand:SI 2 "arith_reg_dest" "")
1682	 (match_dup 0)))
1683   (set (match_dup 2) (match_dup 0))]
1684  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1685  [(set (match_dup 2)
1686	(if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1687{
1688  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1689				VOIDmode, operands[1], CONST0_RTX (SImode));
1690})
1691
1692(define_peephole2
1693  [(set (match_operand:SI 0 "general_movdst_operand" "")
1694	(match_operand:SI 1 "arith_reg_or_0_operand" ""))
1695   (set (match_operand:SI 2 "arith_reg_dest" "")
1696	(if_then_else:SI (match_operator 4 "equality_comparison_operator"
1697			   [(match_operand:SI 3 "arith_reg_operand" "")
1698			    (const_int 0)])
1699	 (match_dup 0)
1700	 (match_dup 2)))]
1701  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1702   && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1703  [(set (match_dup 2)
1704	(if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1705{
1706  replace_rtx (operands[4], operands[0], operands[1]);
1707})
1708
1709;; The register allocator is rather clumsy in handling multi-way conditional
1710;; moves, so allow the combiner to make them, and we split them up after
1711;; reload.  */
1712(define_insn_and_split "*movsicc_umin"
1713  [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1714	(umin:SI (if_then_else:SI
1715		   (eq (match_operand:SI 1 "arith_reg_operand" "r")
1716		       (const_int 0))
1717		   (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1718		   (match_operand:SI 3 "register_operand" "0"))
1719		 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1720   (clobber (match_scratch:SI 5 "=&r"))]
1721  "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1722  "#"
1723  "TARGET_SHMEDIA && reload_completed"
1724  [(pc)]
1725{
1726  emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1727				operands[3]));
1728  emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1729  emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1730				operands[0]));
1731  DONE;
1732})
1733
1734(define_insn "*movsicc_t_false"
1735  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1736	(if_then_else (eq (reg:SI T_REG) (const_int 0))
1737		      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1738		      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1739  "TARGET_PRETEND_CMOVE
1740   && (arith_reg_operand (operands[1], SImode)
1741       || (immediate_operand (operands[1], SImode)
1742	   && satisfies_constraint_I08 (operands[1])))"
1743{
1744  return       "bt	0f"	"\n"
1745	 "	mov	%1,%0"	"\n"
1746	 "0:";
1747}
1748  [(set_attr "type" "mt_group,arith") ;; poor approximation
1749   (set_attr "length" "4")])
1750
1751(define_insn "*movsicc_t_true"
1752  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1753	(if_then_else (ne (reg:SI T_REG) (const_int 0))
1754		      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1755		      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1756  "TARGET_PRETEND_CMOVE
1757   && (arith_reg_operand (operands[1], SImode)
1758       || (immediate_operand (operands[1], SImode)
1759	   && satisfies_constraint_I08 (operands[1])))"
1760{
1761  return       "bf	0f"	"\n"
1762	 "	mov	%1,%0"	"\n"
1763	 "0:";
1764}
1765  [(set_attr "type" "mt_group,arith") ;; poor approximation
1766   (set_attr "length" "4")])
1767
1768(define_expand "movsicc"
1769  [(set (match_operand:SI 0 "arith_reg_dest" "")
1770	(if_then_else:SI (match_operand 1 "comparison_operator" "")
1771			 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1772			 (match_operand:SI 3 "arith_reg_operand" "")))]
1773  "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1774{
1775  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1776      && GET_MODE (XEXP (operands[1], 0)) == SImode
1777      && (TARGET_SHMEDIA
1778	  || (REG_P (XEXP (operands[1], 0))
1779	      && REGNO (XEXP (operands[1], 0)) == T_REG))
1780      && XEXP (operands[1], 1) == const0_rtx)
1781    ;
1782
1783  else if (TARGET_PRETEND_CMOVE)
1784    {
1785      enum rtx_code code = GET_CODE (operands[1]);
1786      enum rtx_code new_code = code;
1787      rtx op0 = XEXP (operands[1], 0);
1788      rtx op1 = XEXP (operands[1], 1);
1789
1790      if (! currently_expanding_to_rtl)
1791	FAIL;
1792      switch (code)
1793	{
1794	case LT: case LE: case LEU: case LTU:
1795	  if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1796	    break;
1797	case NE:
1798	  new_code = reverse_condition (code);
1799	  break;
1800	case EQ: case GT: case GE: case GEU: case GTU:
1801	  break;
1802	default:
1803	  FAIL;
1804	}
1805      sh_emit_scc_to_t (new_code, op0, op1);
1806      operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1807				    gen_rtx_REG (SImode, T_REG), const0_rtx);
1808    }
1809  else
1810    {
1811      if (!can_create_pseudo_p ())
1812	FAIL;
1813
1814      operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1815					      GET_CODE (operands[1]),
1816					      XEXP (operands[1], 0),
1817					      XEXP (operands[1], 1));
1818      if (!operands[1])
1819	FAIL;
1820    }
1821})
1822
1823(define_expand "movqicc"
1824  [(set (match_operand:QI 0 "register_operand" "")
1825	(if_then_else:QI (match_operand 1 "comparison_operator" "")
1826			 (match_operand:QI 2 "register_operand" "")
1827			 (match_operand:QI 3 "register_operand" "")))]
1828  "TARGET_SHMEDIA"
1829{
1830  operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1831  operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1832  operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1833  emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1834  DONE;
1835})
1836
1837;; -------------------------------------------------------------------------
1838;; Addition instructions
1839;; -------------------------------------------------------------------------
1840
1841(define_expand "adddi3"
1842  [(set (match_operand:DI 0 "arith_reg_operand")
1843	(plus:DI (match_operand:DI 1 "arith_reg_operand")
1844		 (match_operand:DI 2 "arith_operand")))]
1845  ""
1846{
1847  if (TARGET_SH1)
1848    {
1849      operands[2] = force_reg (DImode, operands[2]);
1850      emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1851      DONE;
1852    }
1853})
1854
1855(define_insn "*adddi3_media"
1856  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1857	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1858		 (match_operand:DI 2 "arith_operand" "r,I10")))]
1859  "TARGET_SHMEDIA"
1860  "@
1861	add	%1, %2, %0
1862	addi	%1, %2, %0"
1863  [(set_attr "type" "arith_media")])
1864
1865(define_insn "*adddisi3_media"
1866  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1867	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1868		 (match_operand:DI 2 "arith_operand" "r,I10")))]
1869  "TARGET_SHMEDIA"
1870  "@
1871	add.l	%1, %2, %0
1872	addi.l	%1, %2, %0"
1873  [(set_attr "type" "arith_media")
1874   (set_attr "highpart" "ignore")])
1875
1876(define_insn "adddi3z_media"
1877  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1878	(zero_extend:DI
1879	 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1880		  (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1881  "TARGET_SHMEDIA"
1882  "addz.l	%1, %N2, %0"
1883  [(set_attr "type" "arith_media")
1884   (set_attr "highpart" "ignore")])
1885
1886(define_insn_and_split "adddi3_compact"
1887  [(set (match_operand:DI 0 "arith_reg_dest")
1888	(plus:DI (match_operand:DI 1 "arith_reg_operand")
1889		 (match_operand:DI 2 "arith_reg_operand")))
1890   (clobber (reg:SI T_REG))]
1891  "TARGET_SH1"
1892  "#"
1893  "&& can_create_pseudo_p ()"
1894  [(const_int 0)]
1895{
1896  emit_insn (gen_clrt ());
1897  emit_insn (gen_addc (gen_lowpart (SImode, operands[0]),
1898		       gen_lowpart (SImode, operands[1]),
1899		       gen_lowpart (SImode, operands[2])));
1900  emit_insn (gen_addc (gen_highpart (SImode, operands[0]),
1901		       gen_highpart (SImode, operands[1]),
1902		       gen_highpart (SImode, operands[2])));
1903  DONE;
1904})
1905
1906(define_insn "addc"
1907  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1908	(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1909			  (match_operand:SI 2 "arith_reg_operand" "r"))
1910		 (reg:SI T_REG)))
1911   (set (reg:SI T_REG)
1912	(ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1913  "TARGET_SH1"
1914  "addc	%2,%0"
1915  [(set_attr "type" "arith")])
1916
1917;; A simplified version of the addc insn, where the exact value of the
1918;; T bit doesn't matter.  This is easier for combine to pick up.
1919;; We allow a reg or 0 for one of the operands in order to be able to
1920;; do 'reg + T' sequences.
1921(define_insn_and_split "*addc"
1922  [(set (match_operand:SI 0 "arith_reg_dest")
1923	(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand")
1924			  (match_operand:SI 2 "arith_reg_or_0_operand"))
1925		 (match_operand 3 "treg_set_expr")))
1926   (clobber (reg:SI T_REG))]
1927  "TARGET_SH1 && can_create_pseudo_p ()"
1928  "#"
1929  "&& 1"
1930  [(const_int 0)]
1931{
1932  sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn);
1933  if (ti.has_trailing_nott ())
1934    {
1935      if (operands[2] == const0_rtx)
1936	{
1937	  /* op1 + 0 + (1 - T) = op1 + 1 - T = op1 - (-1) - T  */
1938	  remove_insn (ti.trailing_nott ());
1939	  emit_insn (gen_subc (operands[0], operands[1],
1940			       force_reg (SImode, GEN_INT (-1))));
1941	  DONE;
1942	}
1943      else if (!TARGET_SH2A)
1944	{
1945	  /* op1 + op2 + (1 - T) = op1 - (0 - op2 - 1) - T = op1 - ~op2 - T
1946	     On SH2A keep the nott insn, because nott-addc sequence doesn't
1947	     mutate the inputs.  */
1948	  remove_insn (ti.trailing_nott ());
1949	  rtx tmp = gen_reg_rtx (SImode);
1950	  emit_insn (gen_one_cmplsi2 (tmp, operands[2]));
1951	  emit_insn (gen_subc (operands[0], operands[1], tmp));
1952	  DONE;
1953	}
1954    }
1955
1956  emit_insn (gen_addc (operands[0], operands[1],
1957		       force_reg (SImode, operands[2])));
1958  DONE;
1959})
1960
1961(define_insn_and_split "*addc"
1962  [(set (match_operand:SI 0 "arith_reg_dest")
1963	(plus:SI (plus:SI (match_operand 1 "treg_set_expr")
1964			  (match_operand:SI 2 "arith_reg_operand"))
1965		 (match_operand:SI 3 "arith_reg_operand")))
1966   (clobber (reg:SI T_REG))]
1967  "TARGET_SH1 && can_create_pseudo_p ()"
1968  "#"
1969  "&& 1"
1970  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1971				          (match_dup 1)))
1972	      (clobber (reg:SI T_REG))])])
1973
1974(define_insn_and_split "*addc"
1975  [(set (match_operand:SI 0 "arith_reg_dest")
1976	(plus:SI (match_operand 1 "treg_set_expr")
1977		 (plus:SI (match_operand:SI 2 "arith_reg_operand")
1978			  (match_operand:SI 3 "arith_reg_operand"))))
1979   (clobber (reg:SI T_REG))]
1980  "TARGET_SH1 && can_create_pseudo_p ()"
1981  "#"
1982  "&& 1"
1983  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1984					  (match_dup 1)))
1985	      (clobber (reg:SI T_REG))])])
1986
1987;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1988;; matched.  Split this up into a simple sub add sequence, as this will save
1989;; us one sett insn.
1990(define_insn_and_split "*minus_plus_one"
1991  [(set (match_operand:SI 0 "arith_reg_dest" "")
1992	(plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1993			   (match_operand:SI 2 "arith_reg_operand" ""))
1994		 (const_int 1)))]
1995  "TARGET_SH1"
1996  "#"
1997  "&& 1"
1998  [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1999   (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
2000
2001;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
2002;; If the 0 constant can be CSE-ed, this becomes a one instruction
2003;; operation, as opposed to sequences such as
2004;;	movt	r2
2005;;	add	r2,r3
2006;;
2007;; Even if the constant is not CSE-ed, a sequence such as
2008;;	mov	#0,r2
2009;;	addc	r2,r3
2010;; can be scheduled much better since the load of the constant can be
2011;; done earlier, before any comparison insns that store the result in
2012;; the T bit.
2013;; However, avoid things like 'reg + 1', which would expand into a
2014;; 3 insn sequence, instead of add #imm8.
2015(define_insn_and_split "*addc_t_r"
2016  [(set (match_operand:SI 0 "arith_reg_dest")
2017	(plus:SI (match_operand 1 "treg_set_expr_not_const01")
2018		 (match_operand:SI 2 "arith_reg_operand")))
2019   (clobber (reg:SI T_REG))]
2020  "TARGET_SH1 && can_create_pseudo_p ()"
2021  "#"
2022  "&& 1"
2023  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (const_int 0))
2024					  (match_dup 1)))
2025	      (clobber (reg:SI T_REG))])])
2026
2027(define_insn_and_split "*addc_r_t"
2028  [(set (match_operand:SI 0 "arith_reg_dest")
2029	(plus:SI (match_operand:SI 1 "arith_reg_operand")
2030		 (match_operand 2 "treg_set_expr_not_const01")))
2031   (clobber (reg:SI T_REG))]
2032  "TARGET_SH1 && can_create_pseudo_p ()"
2033  "#"
2034  "&& 1"
2035  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (const_int 0))
2036					  (match_dup 2)))
2037	      (clobber (reg:SI T_REG))])])
2038
2039;; Convert '2 * reg + T' into 'reg + reg + T'.
2040(define_insn_and_split "*addc_2r_t"
2041  [(set (match_operand:SI 0 "arith_reg_dest")
2042	(plus:SI (match_operand 1 "treg_set_expr")
2043		 (mult:SI (match_operand:SI 2 "arith_reg_operand")
2044			  (const_int 2))))
2045   (clobber (reg:SI T_REG))]
2046  "TARGET_SH1 && can_create_pseudo_p ()"
2047  "#"
2048  "&& 1"
2049  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 2))
2050					  (match_dup 1)))
2051	      (clobber (reg:SI T_REG))])])
2052
2053(define_insn_and_split "*addc_2r_t"
2054  [(set (match_operand:SI 0 "arith_reg_dest")
2055	(plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
2056			  (const_int 2))
2057		 (match_operand 2 "treg_set_expr")))
2058   (clobber (reg:SI T_REG))]
2059  "TARGET_SH1 && can_create_pseudo_p ()"
2060  "#"
2061  "&& 1"
2062  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
2063					  (match_dup 2)))
2064	      (clobber (reg:SI T_REG))])])
2065
2066;; Convert '(op2 + T) - op3' into 'op2 + (-op3) + T'
2067(define_insn_and_split "*addc_negreg_t"
2068  [(set (match_operand:SI 0 "arith_reg_dest")
2069	(minus:SI (plus:SI (match_operand 1 "treg_set_expr")
2070			   (match_operand:SI 2 "arith_reg_operand"))
2071		  (match_operand:SI 3 "arith_reg_operand")))
2072   (clobber (reg:SI T_REG))]
2073  "TARGET_SH1 && can_create_pseudo_p ()"
2074  "#"
2075  "&& 1"
2076  [(set (match_dup 4) (neg:SI (match_dup 3)))
2077   (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 4))
2078					  (match_dup 1)))
2079	      (clobber (reg:SI T_REG))])]
2080{
2081  operands[4] = gen_reg_rtx (SImode);
2082})
2083
2084(define_expand "addsi3"
2085  [(set (match_operand:SI 0 "arith_reg_dest")
2086	(plus:SI (match_operand:SI 1 "arith_reg_operand")
2087		 (match_operand:SI 2 "arith_or_int_operand")))]
2088  ""
2089{
2090  if (TARGET_SH1 && !arith_operand (operands[2], SImode))
2091    {
2092      if (!sh_lra_p () || reg_overlap_mentioned_p (operands[0], operands[1]))
2093	{
2094	  emit_insn (gen_addsi3_scr (operands[0], operands[1], operands[2]));
2095	  DONE;
2096	}
2097    }
2098})
2099
2100(define_insn "addsi3_media"
2101  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
2102	(plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
2103		 (match_operand:SI 2 "arith_operand" "r,I10")))]
2104  "TARGET_SHMEDIA"
2105  "@
2106	add.l	%1, %2, %0
2107	addi.l	%1, %2, %0"
2108  [(set_attr "type" "arith_media")
2109   (set_attr "highpart" "ignore")])
2110
2111(define_insn "addsidi3_media"
2112  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
2113	(sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
2114				  "%r,r")
2115				 (match_operand:SI 2 "arith_operand"
2116				  "r,I10"))))]
2117  "TARGET_SHMEDIA"
2118  "@
2119	add.l	%1, %2, %0
2120	addi.l	%1, %2, %0"
2121  [(set_attr "type" "arith_media")
2122   (set_attr "highpart" "ignore")])
2123
2124;; The *addsi3_compact is made an insn_and_split and accepts actually
2125;; impossible constraints to make LRA's register elimination work well on SH.
2126;; The problem is that LRA expects something like
2127;;    (set rA (plus rB (const_int N)))
2128;; to work.  We can do that, but we have to split out an additional reg-reg
2129;; copy or constant load before the actual add insn.
2130;; Use u constraint for that case to avoid the invalid value in the stack
2131;; pointer.
2132;; This also results in better code when LRA is not used.  However, we have
2133;; to use different sets of patterns and the order of these patterns is
2134;; important.
2135;; In some cases the constant zero might end up in operands[2] of the
2136;; patterns.  We have to accept that and convert it into a reg-reg move.
2137(define_insn_and_split "*addsi3_compact_lra"
2138  [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u")
2139	(plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r")
2140		 (match_operand:SI 2 "arith_or_int_operand" "rI08,rn")))]
2141  "TARGET_SH1 && sh_lra_p ()
2142   && (! reg_overlap_mentioned_p (operands[0], operands[1])
2143       || arith_operand (operands[2], SImode))"
2144  "@
2145	add	%2,%0
2146	#"
2147  "&& reload_completed
2148   && ! reg_overlap_mentioned_p (operands[0], operands[1])"
2149  [(set (match_dup 0) (match_dup 2))
2150   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
2151{
2152  /* Prefer 'mov r0,r1; add #imm8,r1' over 'mov #imm8,r1; add r0,r1'  */
2153  if (satisfies_constraint_I08 (operands[2]))
2154    std::swap (operands[1], operands[2]);
2155}
2156  [(set_attr "type" "arith")])
2157
2158(define_insn_and_split "addsi3_scr"
2159  [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u,&u")
2160	(plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r,r")
2161		 (match_operand:SI 2 "arith_or_int_operand" "rI08,r,n")))
2162   (clobber (match_scratch:SI 3 "=X,X,&u"))]
2163  "TARGET_SH1"
2164  "@
2165	add	%2,%0
2166	#
2167	#"
2168  "&& reload_completed"
2169  [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
2170{
2171  if (operands[2] == const0_rtx)
2172    {
2173      emit_move_insn (operands[0], operands[1]);
2174      DONE;
2175    }
2176
2177  if (CONST_INT_P (operands[2]) && !satisfies_constraint_I08 (operands[2]))
2178    {
2179      if (reg_overlap_mentioned_p (operands[0], operands[1]))
2180	{
2181	  emit_move_insn (operands[3], operands[2]);
2182	  emit_move_insn (operands[0], operands[1]);
2183	  operands[2] = operands[3];
2184	}
2185      else
2186	{
2187	  emit_move_insn (operands[0], operands[2]);
2188	  operands[2] = operands[1];
2189	}
2190    }
2191  else if (!reg_overlap_mentioned_p (operands[0], operands[1]))
2192    {
2193      if (!reg_overlap_mentioned_p (operands[0], operands[2]))
2194	emit_move_insn (operands[0], operands[1]);
2195      else
2196	operands[2] = operands[1];
2197    }
2198}
2199  [(set_attr "type" "arith")])
2200
2201;; Old reload might generate add insns directly (not through the expander) for
2202;; address register calculations when reloading, in which case it won't try
2203;; the addsi_scr pattern.  Because reload will sometimes try to validate
2204;; the generated insns and their constraints, this pattern must be
2205;; recognizable during and after reload.  However, when reload generates
2206;; address register calculations for the stack pointer, we don't allow this
2207;; pattern.  This will make reload prefer using indexed @(reg + reg) address
2208;; modes when the displacement of a @(disp + reg) doesn't fit.
2209(define_insn_and_split "*addsi3"
2210  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2211	(plus:SI (match_operand:SI 1 "arith_reg_operand" "r")
2212		 (match_operand:SI 2 "arith_or_int_operand" "rn")))]
2213  "TARGET_SH1 && !sh_lra_p ()
2214   && (reload_completed || reload_in_progress)
2215   && !reg_overlap_mentioned_p (operands[0], operands[1])
2216   && (!reload_in_progress
2217       || ((!REG_P (operands[1]) || REGNO (operands[1]) != SP_REG)
2218	   && (!REG_P (operands[2]) || REGNO (operands[2]) != SP_REG)))"
2219  "#"
2220  "&& 1"
2221  [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
2222{
2223  if (operands[2] == const0_rtx)
2224    {
2225      emit_move_insn (operands[0], operands[1]);
2226      DONE;
2227    }
2228
2229  if (CONST_INT_P (operands[2]))
2230    {
2231      if (satisfies_constraint_I08 (operands[2]))
2232	emit_move_insn (operands[0], operands[1]);
2233      else
2234	{
2235	  emit_move_insn (operands[0], operands[2]);
2236	  operands[2] = operands[1];
2237	}
2238    }
2239  else if (!reg_overlap_mentioned_p (operands[0], operands[2]))
2240    emit_move_insn (operands[0], operands[1]);
2241  else
2242    operands[2] = operands[1];
2243})
2244
2245(define_insn_and_split "*addsi3"
2246  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
2247	(plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r")
2248		 (match_operand:SI 2 "arith_operand" "rI08,Z")))]
2249  "TARGET_SH1 && !sh_lra_p ()"
2250  "@
2251	add	%2,%0
2252	#"
2253  "&& operands[2] == const0_rtx"
2254  [(set (match_dup 0) (match_dup 1))]
2255{
2256}
2257  [(set_attr "type" "arith")])
2258
2259;; -------------------------------------------------------------------------
2260;; Subtraction instructions
2261;; -------------------------------------------------------------------------
2262
2263(define_expand "subdi3"
2264  [(set (match_operand:DI 0 "arith_reg_operand" "")
2265	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
2266		  (match_operand:DI 2 "arith_reg_operand" "")))]
2267  ""
2268{
2269  if (TARGET_SH1)
2270    {
2271      operands[1] = force_reg (DImode, operands[1]);
2272      emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
2273      DONE;
2274    }
2275})
2276
2277(define_insn "*subdi3_media"
2278  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2279	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2280		  (match_operand:DI 2 "arith_reg_operand" "r")))]
2281  "TARGET_SHMEDIA"
2282  "sub	%N1, %2, %0"
2283  [(set_attr "type" "arith_media")])
2284  
2285(define_insn "subdisi3_media"
2286  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
2287	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2288		  (match_operand:DI 2 "arith_reg_operand" "r")))]
2289  "TARGET_SHMEDIA"
2290  "sub.l	%N1, %2, %0"
2291  [(set_attr "type" "arith_media")
2292   (set_attr "highpart" "ignore")])
2293
2294(define_insn_and_split "subdi3_compact"
2295  [(set (match_operand:DI 0 "arith_reg_dest")
2296	(minus:DI (match_operand:DI 1 "arith_reg_operand")
2297		 (match_operand:DI 2 "arith_reg_operand")))
2298   (clobber (reg:SI T_REG))]
2299  "TARGET_SH1"
2300  "#"
2301  "&& can_create_pseudo_p ()"
2302  [(const_int 0)]
2303{
2304  emit_insn (gen_clrt ());
2305  emit_insn (gen_subc (gen_lowpart (SImode, operands[0]),
2306		       gen_lowpart (SImode, operands[1]),
2307		       gen_lowpart (SImode, operands[2])));
2308  emit_insn (gen_subc (gen_highpart (SImode, operands[0]),
2309		       gen_highpart (SImode, operands[1]),
2310		       gen_highpart (SImode, operands[2])));
2311  DONE;
2312})
2313
2314(define_insn "subc"
2315  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2316	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2317			    (match_operand:SI 2 "arith_reg_operand" "r"))
2318		  (reg:SI T_REG)))
2319   (set (reg:SI T_REG)
2320	(gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
2321			  (reg:SI T_REG))
2322		(match_dup 1)))]
2323  "TARGET_SH1"
2324  "subc	%2,%0"
2325  [(set_attr "type" "arith")])
2326
2327;; A simplified version of the subc insn, where the exact value of the
2328;; T bit doesn't matter.  This is easier for combine to pick up.
2329;; We allow a reg or 0 for one of the operands in order to be able to
2330;; do 'reg - T' sequences.  Reload will load the constant 0 into the reg
2331;; as needed.
2332(define_insn_and_split "*subc"
2333  [(set (match_operand:SI 0 "arith_reg_dest")
2334	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand")
2335			    (match_operand:SI 2 "arith_reg_or_0_operand"))
2336		  (match_operand 3 "treg_set_expr")))
2337   (clobber (reg:SI T_REG))]
2338  "TARGET_SH1 && can_create_pseudo_p ()"
2339  "#"
2340  "&& 1"
2341  [(const_int 0)]
2342{
2343  sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn);
2344  if (ti.has_trailing_nott ())
2345    {
2346      if (operands[2] == const0_rtx)
2347	{
2348	  /* op1 - (1 - T) = op1 - 1 + T = op1 + (-1) + T  */
2349	  remove_insn (ti.trailing_nott ());
2350	  emit_insn (gen_addc (operands[0], operands[1],
2351			       force_reg (SImode, GEN_INT (-1))));
2352	  DONE;
2353	}
2354      else if (!TARGET_SH2A)
2355	{
2356	  /* op1 - op2 - (1 - T) = op1 + (0 - op2 - 1) + T = op1 + ~op2 + T
2357	     On SH2A keep the nott insn, because nott-subc sequence doesn't
2358	     mutate the inputs.  */
2359	  remove_insn (ti.trailing_nott ());
2360	  rtx tmp = gen_reg_rtx (SImode);
2361	  emit_insn (gen_one_cmplsi2 (tmp, operands[2]));
2362	  emit_insn (gen_addc (operands[0], operands[1], tmp));
2363	  DONE;
2364	}
2365    }
2366
2367  emit_insn (gen_subc (operands[0], operands[1],
2368		       force_reg (SImode, operands[2])));
2369  DONE;
2370})
2371
2372;; Convert reg - T - reg = reg - reg - T
2373(define_insn_and_split "*subc"
2374  [(set (match_operand:SI 0 "arith_reg_dest")
2375	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand")
2376			    (match_operand 2 "treg_set_expr"))
2377		  (match_operand:SI 3 "arith_reg_operand")))
2378   (clobber (reg:SI T_REG))]
2379  "TARGET_SH1 && can_create_pseudo_p ()"
2380  "#"
2381  "&& 1"
2382  [(parallel [(set (match_dup 0)
2383		   (minus:SI (minus:SI (match_dup 1) (match_dup 3))
2384			     (match_dup 2)))
2385	      (clobber (reg:SI T_REG))])])
2386
2387;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
2388;; better, if the sett insn can be done early.
2389;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
2390(define_insn_and_split "*subc"
2391  [(set (match_operand:SI 0 "arith_reg_dest" "")
2392	(plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
2393		 (match_operand:SI 2 "arith_reg_operand" "")))
2394   (clobber (reg:SI T_REG))]
2395  "TARGET_SH1 && can_create_pseudo_p ()"
2396  "#"
2397  "&& 1"
2398  [(parallel [(set (match_dup 0)
2399		   (minus:SI (minus:SI (match_dup 2) (match_dup 1))
2400			     (const_int 1)))
2401	      (clobber (reg:SI T_REG))])])
2402
2403;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
2404;; If the 0 constant can be CSE-ed, this becomes a one instruction
2405;; operation, as opposed to sequences such as
2406;;	movt	r2
2407;;	sub	r2,r3
2408;;
2409;; Even if the constant is not CSE-ed, a sequence such as
2410;;	mov	#0,r2
2411;;	subc	r2,r3
2412;; can be scheduled much better since the load of the constant can be
2413;; done earlier, before any comparison insns that store the result in
2414;; the T bit.
2415;; However, avoid things like 'reg - 1', which would expand into a
2416;; 3 insn sequence, instead of add #imm8.
2417(define_insn_and_split "*subc"
2418  [(set (match_operand:SI 0 "arith_reg_dest" "")
2419	(minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2420		  (match_operand 2 "treg_set_expr_not_const01")))
2421   (clobber (reg:SI T_REG))]
2422  "TARGET_SH1 && can_create_pseudo_p ()"
2423  "#"
2424  "&& 1"
2425  [(parallel [(set (match_dup 0)
2426		   (minus:SI (minus:SI (match_dup 1) (const_int 0))
2427			     (match_dup 2)))
2428	      (clobber (reg:SI T_REG))])])
2429
2430;; Convert
2431;;   (1 - T) - op2 = 1 - op2 - T
2432(define_insn_and_split "*subc_negt_reg"
2433  [(set (match_operand:SI 0 "arith_reg_dest")
2434	(minus:SI (match_operand 1 "treg_set_expr_not_const01")
2435		  (match_operand:SI 2 "arith_reg_operand")))
2436   (clobber (reg:SI T_REG))]
2437  "TARGET_SH1 && can_create_pseudo_p ()"
2438  "#"
2439  "&& 1"
2440  [(const_int 0)]
2441{
2442  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
2443  if (ti.remove_trailing_nott ())
2444    {
2445      /* (1 - T) - op2 = 1 - op2 - T  */
2446      emit_insn (gen_subc (operands[0],
2447			   force_reg (SImode, GEN_INT (1)), operands[2]));
2448    }
2449  else
2450    {
2451      /* T - op2: use movt,sub sequence.  */
2452      rtx tmp = gen_reg_rtx (SImode);
2453      emit_insn (gen_movt (tmp, get_t_reg_rtx ()));
2454      emit_insn (gen_subsi3 (operands[0], tmp, operands[2]));
2455    }
2456  DONE;
2457})
2458
2459;; Convert
2460;;   op1 - (1 - T) + op3 = op1 - 1 + T + op3
2461;;   (op1 - T) + op3 = op1 - (-op3) - T
2462(define_insn_and_split "*subc_negreg_t"
2463  [(set (match_operand:SI 0 "arith_reg_dest")
2464	(plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand")
2465			   (match_operand 2 "treg_set_expr"))
2466		 (match_operand:SI 3 "arith_reg_operand")))
2467   (clobber (reg:SI T_REG))]
2468  "TARGET_SH1 && can_create_pseudo_p ()"
2469  "#"
2470  "&& 1"
2471  [(const_int 0)]
2472{
2473  sh_treg_insns ti = sh_split_treg_set_expr (operands[2], curr_insn);
2474  if (ti.remove_trailing_nott ())
2475    {
2476      /* op1 - (1 - T) + op3 = (op1 - 1) + op3 + T  */
2477      rtx tmp = gen_reg_rtx (SImode);
2478      emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (-1)));
2479      emit_insn (gen_addc (operands[0], tmp, operands[3]));
2480    }
2481  else
2482    {
2483      /* (op1 - T) + op3' = 'op1 - (-op3) - T  */
2484      rtx tmp = gen_reg_rtx (SImode);
2485      emit_insn (gen_negsi2 (tmp, operands[3]));
2486      emit_insn (gen_subc (operands[0], operands[1], tmp));
2487    }
2488  DONE;
2489})
2490
2491(define_insn "*subsi3_internal"
2492  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2493	(minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2494		  (match_operand:SI 2 "arith_reg_operand" "r")))]
2495  "TARGET_SH1"
2496  "sub	%2,%0"
2497  [(set_attr "type" "arith")])
2498
2499(define_insn_and_split "*subsi3_media"
2500  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2501	(minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2502		  (match_operand:SI 2 "extend_reg_operand" "r")))]
2503  "TARGET_SHMEDIA
2504   && (operands[1] != constm1_rtx
2505       || (GET_CODE (operands[2]) != TRUNCATE
2506	   && GET_CODE (operands[2]) != SUBREG))"
2507  "sub.l	%N1, %2, %0"
2508  "operands[1] == constm1_rtx"
2509  [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2510  ""
2511  [(set_attr "type" "arith_media")
2512   (set_attr "highpart" "ignore")])
2513
2514(define_split
2515  [(set (match_operand:SI 0 "arith_reg_dest" "")
2516	(zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2517						       "general_extend_operand"
2518						       "") 0)) 0)))]
2519  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2520  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2521   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2522  "")
2523
2524(define_split
2525  [(set (match_operand:SI 0 "arith_reg_dest" "")
2526	(zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2527						       "general_extend_operand"
2528						       "") 0)) 3)))]
2529  "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
2530  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2531   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2532  "")
2533
2534;; Convert
2535;;	constant - reg
2536;; to
2537;;	neg reg
2538;;	add reg, #const
2539;; since this will sometimes save one instruction.
2540;; Otherwise we might get a sequence like
2541;;	mov #const, rY
2542;;	sub rY, rX
2543;;	mov rX, rY
2544;; if the source and dest regs are the same.
2545(define_expand "subsi3"
2546  [(set (match_operand:SI 0 "arith_reg_operand" "")
2547	(minus:SI (match_operand:SI 1 "arith_operand" "")
2548		  (match_operand:SI 2 "arith_reg_operand" "")))]
2549  ""
2550{
2551  if (TARGET_SH1 && CONST_INT_P (operands[1]))
2552    {
2553      emit_insn (gen_negsi2 (operands[0], operands[2]));
2554      emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2555      DONE;
2556    }
2557  if (TARGET_SHMEDIA)
2558    {
2559      if (!can_create_pseudo_p ()
2560	  && ! arith_reg_or_0_operand (operands[1], SImode))
2561	FAIL;
2562      if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2563	operands[1] = force_reg (SImode, operands[1]);
2564    }
2565})
2566
2567;; -------------------------------------------------------------------------
2568;; Division instructions
2569;; -------------------------------------------------------------------------
2570
2571;; We take advantage of the library routines which don't clobber as many
2572;; registers as a normal function call would.
2573
2574;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2575;; also has an effect on the register that holds the address of the sfunc.
2576;; To make this work, we have an extra dummy insn that shows the use
2577;; of this register for reorg.
2578
2579(define_insn "use_sfunc_addr"
2580  [(set (reg:SI PR_REG)
2581	(unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2582  "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2583  ""
2584  [(set_attr "length" "0")])
2585
2586(define_insn "udivsi3_sh2a"
2587  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2588	(udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2589		(match_operand:SI 2 "arith_reg_operand" "z")))]
2590  "TARGET_SH2A"
2591  "divu	%2,%1"
2592  [(set_attr "type" "arith")
2593   (set_attr "in_delay_slot" "no")])
2594
2595;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2596;; hard register 0.  If we used hard register 0, then the next instruction
2597;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
2598;; gets allocated to a stack slot that needs its address reloaded, then
2599;; there is nothing to prevent reload from using r0 to reload the address.
2600;; This reload would clobber the value in r0 we are trying to store.
2601;; If we let reload allocate r0, then this problem can never happen.
2602(define_insn "udivsi3_i1"
2603  [(set (match_operand:SI 0 "register_operand" "=z")
2604	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2605   (clobber (reg:SI T_REG))
2606   (clobber (reg:SI PR_REG))
2607   (clobber (reg:SI R1_REG))
2608   (clobber (reg:SI R4_REG))
2609   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2610  "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2611  "jsr	@%1%#"
2612  [(set_attr "type" "sfunc")
2613   (set_attr "needs_delay_slot" "yes")])
2614
2615; Since shmedia-nofpu code could be linked against shcompact code, and
2616; the udivsi3 libcall has the same name, we must consider all registers
2617; clobbered that are in the union of the registers clobbered by the
2618; shmedia and the shcompact implementation.  Note, if the shcompact
2619; implementation actually used shcompact code, we'd need to clobber
2620; also r23 and fr23.
2621(define_insn "udivsi3_i1_media"
2622  [(set (match_operand:SI 0 "register_operand" "=z")
2623	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2624   (clobber (reg:SI T_MEDIA_REG))
2625   (clobber (reg:SI PR_MEDIA_REG))
2626   (clobber (reg:SI R20_REG))
2627   (clobber (reg:SI R21_REG))
2628   (clobber (reg:SI R22_REG))
2629   (clobber (reg:DI TR0_REG))
2630   (clobber (reg:DI TR1_REG))
2631   (clobber (reg:DI TR2_REG))
2632   (use (match_operand 1 "target_reg_operand" "b"))]
2633  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2634  "blink	%1, r18"
2635  [(set_attr "type" "sfunc")
2636   (set_attr "needs_delay_slot" "yes")])
2637
2638(define_expand "udivsi3_i4_media"
2639  [(set (match_dup 3)
2640	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2641   (set (match_dup 4)
2642	(zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2643   (set (match_dup 5) (float:DF (match_dup 3)))
2644   (set (match_dup 6) (float:DF (match_dup 4)))
2645   (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2646   (set (match_dup 8) (fix:DI (match_dup 7)))
2647   (set (match_operand:SI 0 "register_operand" "")
2648	(truncate:SI (match_dup 8)))]
2649  "TARGET_SHMEDIA_FPU"
2650{
2651  operands[3] = gen_reg_rtx (DImode);
2652  operands[4] = gen_reg_rtx (DImode);
2653  operands[5] = gen_reg_rtx (DFmode);
2654  operands[6] = gen_reg_rtx (DFmode);
2655  operands[7] = gen_reg_rtx (DFmode);
2656  operands[8] = gen_reg_rtx (DImode);
2657})
2658
2659(define_insn "udivsi3_i4"
2660  [(set (match_operand:SI 0 "register_operand" "=y")
2661	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2662   (clobber (reg:SI T_REG))
2663   (clobber (reg:SI PR_REG))
2664   (clobber (reg:DF DR0_REG))
2665   (clobber (reg:DF DR2_REG))
2666   (clobber (reg:DF DR4_REG))
2667   (clobber (reg:SI R0_REG))
2668   (clobber (reg:SI R1_REG))
2669   (clobber (reg:SI R4_REG))
2670   (clobber (reg:SI R5_REG))
2671   (clobber (reg:SI FPSCR_STAT_REG))
2672   (use (match_operand:SI 1 "arith_reg_operand" "r"))
2673   (use (reg:SI FPSCR_MODES_REG))]
2674  "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2675  "jsr	@%1%#"
2676  [(set_attr "type" "sfunc")
2677   (set_attr "fp_mode" "double")
2678   (set_attr "needs_delay_slot" "yes")])
2679
2680(define_insn "udivsi3_i4_single"
2681  [(set (match_operand:SI 0 "register_operand" "=y")
2682	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2683   (clobber (reg:SI T_REG))
2684   (clobber (reg:SI PR_REG))
2685   (clobber (reg:DF DR0_REG))
2686   (clobber (reg:DF DR2_REG))
2687   (clobber (reg:DF DR4_REG))
2688   (clobber (reg:SI R0_REG))
2689   (clobber (reg:SI R1_REG))
2690   (clobber (reg:SI R4_REG))
2691   (clobber (reg:SI R5_REG))
2692   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2693  "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2694   && TARGET_FPU_SINGLE"
2695  "jsr	@%1%#"
2696  [(set_attr "type" "sfunc")
2697   (set_attr "needs_delay_slot" "yes")])
2698
2699(define_insn "udivsi3_i4_int"
2700  [(set (match_operand:SI 0 "register_operand" "=z")
2701	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2702   (clobber (reg:SI T_REG))
2703   (clobber (reg:SI R1_REG))
2704   (clobber (reg:SI PR_REG))
2705   (clobber (reg:SI MACH_REG))
2706   (clobber (reg:SI MACL_REG))
2707   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2708  "TARGET_SH1"
2709  "jsr	@%1%#"
2710  [(set_attr "type" "sfunc")
2711   (set_attr "needs_delay_slot" "yes")])
2712
2713
2714(define_expand "udivsi3"
2715  [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2716   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2717   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2718   (parallel [(set (match_operand:SI 0 "register_operand" "")
2719		   (udiv:SI (reg:SI R4_REG)
2720			    (reg:SI R5_REG)))
2721	      (clobber (reg:SI T_REG))
2722	      (clobber (reg:SI PR_REG))
2723	      (clobber (reg:SI R4_REG))
2724	      (use (match_dup 3))])]
2725  ""
2726{
2727  rtx last;
2728
2729  operands[3] = gen_reg_rtx (Pmode);
2730  /* Emit the move of the address to a pseudo outside of the libcall.  */
2731  if (TARGET_DIVIDE_CALL_TABLE)
2732    {
2733      /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2734	 that causes problems when the divide code is supposed to come from a
2735	 separate library.  Division by zero is undefined, so dividing 1 can be
2736	 implemented by comparing with the divisor.  */
2737      if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2738	{
2739	  rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2740	  emit_insn (gen_cstoresi4 (operands[0], test,
2741				    operands[1], operands[2]));
2742	  DONE;
2743	}
2744      else if (operands[2] == const0_rtx)
2745	{
2746	  emit_move_insn (operands[0], operands[2]);
2747	  DONE;
2748	}
2749      function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2750      last = gen_udivsi3_i4_int (operands[0], operands[3]);
2751    }
2752  else if (TARGET_DIVIDE_CALL_FP)
2753    {
2754      function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
2755      if (TARGET_FPU_SINGLE)
2756	last = gen_udivsi3_i4_single (operands[0], operands[3]);
2757      else
2758	last = gen_udivsi3_i4 (operands[0], operands[3]);
2759    }
2760  else if (TARGET_SHMEDIA_FPU)
2761    {
2762      operands[1] = force_reg (SImode, operands[1]);
2763      operands[2] = force_reg (SImode, operands[2]);
2764      emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2765      DONE;
2766    }
2767  else if (TARGET_SH2A)
2768    {
2769      operands[1] = force_reg (SImode, operands[1]);
2770      operands[2] = force_reg (SImode, operands[2]);
2771      emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2772      DONE;
2773    }
2774  else if (TARGET_SH5)
2775    {
2776      function_symbol (operands[3],
2777		       TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2778		       SFUNC_STATIC);
2779
2780      if (TARGET_SHMEDIA)
2781	last = gen_udivsi3_i1_media (operands[0], operands[3]);
2782      else if (TARGET_FPU_ANY)
2783	last = gen_udivsi3_i4_single (operands[0], operands[3]);
2784      else
2785	last = gen_udivsi3_i1 (operands[0], operands[3]);
2786    }
2787  else
2788    {
2789      function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
2790      last = gen_udivsi3_i1 (operands[0], operands[3]);
2791    }
2792  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2793  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2794  emit_insn (last);
2795  DONE;
2796})
2797
2798(define_insn "divsi3_sh2a"
2799  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2800	(div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2801		(match_operand:SI 2 "arith_reg_operand" "z")))]
2802  "TARGET_SH2A"
2803  "divs	%2,%1"
2804  [(set_attr "type" "arith")
2805   (set_attr "in_delay_slot" "no")])
2806
2807(define_insn "divsi3_i1"
2808  [(set (match_operand:SI 0 "register_operand" "=z")
2809	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2810   (clobber (reg:SI T_REG))
2811   (clobber (reg:SI PR_REG))
2812   (clobber (reg:SI R1_REG))
2813   (clobber (reg:SI R2_REG))
2814   (clobber (reg:SI R3_REG))
2815   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2816  "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2817  "jsr	@%1%#"
2818  [(set_attr "type" "sfunc")
2819   (set_attr "needs_delay_slot" "yes")])
2820
2821(define_insn "divsi3_i1_media"
2822  [(set (match_operand:SI 0 "register_operand" "=z")
2823	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2824   (clobber (reg:SI T_MEDIA_REG))
2825   (clobber (reg:SI PR_MEDIA_REG))
2826   (clobber (reg:SI R1_REG))
2827   (clobber (reg:SI R20_REG))
2828   (clobber (reg:SI R21_REG))
2829   (clobber (reg:SI TR0_REG))
2830   (use (match_operand 1 "target_reg_operand" "b"))]
2831  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2832  "blink	%1, r18"
2833  [(set_attr "type" "sfunc")])
2834
2835(define_insn "divsi3_media_2"
2836  [(set (match_operand:SI 0 "register_operand" "=z")
2837	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2838   (clobber (reg:SI T_MEDIA_REG))
2839   (clobber (reg:SI PR_MEDIA_REG))
2840   (clobber (reg:SI R1_REG))
2841   (clobber (reg:SI R21_REG))
2842   (clobber (reg:SI TR0_REG))
2843   (use (reg:SI R20_REG))
2844   (use (match_operand 1 "target_reg_operand" "b"))]
2845  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2846  "blink	%1, r18"
2847  [(set_attr "type" "sfunc")])
2848
2849;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2850;; hard reg clobbers and data dependencies that we need when we want
2851;; to rematerialize the division into a call.
2852(define_insn_and_split "divsi_inv_call"
2853  [(set (match_operand:SI 0 "register_operand" "=r")
2854	(div:SI (match_operand:SI 1 "register_operand" "r")
2855		(match_operand:SI 2 "register_operand" "r")))
2856   (clobber (reg:SI R4_REG))
2857   (clobber (reg:SI R5_REG))
2858   (clobber (reg:SI T_MEDIA_REG))
2859   (clobber (reg:SI PR_MEDIA_REG))
2860   (clobber (reg:SI R1_REG))
2861   (clobber (reg:SI R21_REG))
2862   (clobber (reg:SI TR0_REG))
2863   (clobber (reg:SI R20_REG))
2864   (use (match_operand:SI 3 "register_operand" "r"))]
2865  "TARGET_SHMEDIA"
2866  "#"
2867  "&& (reload_in_progress || reload_completed)"
2868  [(set (match_dup 0) (match_dup 3))]
2869  ""
2870  [(set_attr "highpart" "must_split")])
2871
2872;; This is the combiner pattern for -mdiv=inv:call .
2873(define_insn_and_split "*divsi_inv_call_combine"
2874  [(set (match_operand:SI 0 "register_operand" "=z")
2875	(div:SI (match_operand:SI 1 "register_operand" "r")
2876		(match_operand:SI 2 "register_operand" "r")))
2877   (clobber (reg:SI R4_REG))
2878   (clobber (reg:SI R5_REG))
2879   (clobber (reg:SI T_MEDIA_REG))
2880   (clobber (reg:SI PR_MEDIA_REG))
2881   (clobber (reg:SI R1_REG))
2882   (clobber (reg:SI R21_REG))
2883   (clobber (reg:SI TR0_REG))
2884   (clobber (reg:SI R20_REG))
2885   (use (unspec:SI [(match_dup 1)
2886		    (match_operand:SI 3 "" "")
2887		    (unspec:SI [(match_operand:SI 4 "" "")
2888				(match_dup 3)
2889				(match_operand:DI 5 "" "")]
2890		     UNSPEC_DIV_INV_M2)
2891		    (match_operand:DI 6 "" "")
2892		    (const_int 0)
2893		    (const_int 0)]
2894	 UNSPEC_DIV_INV_M3))]
2895  "TARGET_SHMEDIA"
2896  "#"
2897  "&& (reload_in_progress || reload_completed)"
2898  [(pc)]
2899{
2900  const char *name = sh_divsi3_libfunc;
2901  enum sh_function_kind kind = SFUNC_GOT;
2902  rtx sym;
2903
2904  emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2905  emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2906  while (TARGET_DIVIDE_INV_CALL2)
2907    {
2908      rtx x = operands[3];
2909
2910      if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2911	break;
2912      x = XVECEXP (x, 0, 0);
2913      name = "__sdivsi3_2";
2914      kind = SFUNC_STATIC;
2915      emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2916      break;
2917    }
2918  sym = function_symbol (NULL, name, kind);
2919  emit_insn (gen_divsi3_media_2 (operands[0], sym));
2920  DONE;
2921}
2922  [(set_attr "highpart" "must_split")])
2923
2924(define_expand "divsi3_i4_media"
2925  [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2926   (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2927   (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2928   (set (match_operand:SI 0 "register_operand" "=r")
2929	(fix:SI (match_dup 5)))]
2930  "TARGET_SHMEDIA_FPU"
2931{
2932  operands[3] = gen_reg_rtx (DFmode);
2933  operands[4] = gen_reg_rtx (DFmode);
2934  operands[5] = gen_reg_rtx (DFmode);
2935})
2936
2937(define_insn "divsi3_i4"
2938  [(set (match_operand:SI 0 "register_operand" "=y")
2939	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2940   (clobber (reg:SI PR_REG))
2941   (clobber (reg:DF DR0_REG))
2942   (clobber (reg:DF DR2_REG))
2943   (clobber (reg:SI FPSCR_STAT_REG))
2944   (use (match_operand:SI 1 "arith_reg_operand" "r"))
2945   (use (reg:SI FPSCR_MODES_REG))]
2946  "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2947  "jsr	@%1%#"
2948  [(set_attr "type" "sfunc")
2949   (set_attr "fp_mode" "double")
2950   (set_attr "needs_delay_slot" "yes")])
2951
2952(define_insn "divsi3_i4_single"
2953  [(set (match_operand:SI 0 "register_operand" "=y")
2954	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2955   (clobber (reg:SI PR_REG))
2956   (clobber (reg:DF DR0_REG))
2957   (clobber (reg:DF DR2_REG))
2958   (clobber (reg:SI R2_REG))
2959   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2960  "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2961   && TARGET_FPU_SINGLE"
2962  "jsr	@%1%#"
2963  [(set_attr "type" "sfunc")
2964   (set_attr "needs_delay_slot" "yes")])
2965
2966(define_insn "divsi3_i4_int"
2967  [(set (match_operand:SI 0 "register_operand" "=z")
2968	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2969   (clobber (reg:SI T_REG))
2970   (clobber (reg:SI PR_REG))
2971   (clobber (reg:SI R1_REG))
2972   (clobber (reg:SI MACH_REG))
2973   (clobber (reg:SI MACL_REG))
2974   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2975  "TARGET_SH1"
2976  "jsr	@%1%#"
2977  [(set_attr "type" "sfunc")
2978   (set_attr "needs_delay_slot" "yes")])
2979
2980(define_expand "divsi3"
2981  [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2982   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2983   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2984   (parallel [(set (match_operand:SI 0 "register_operand" "")
2985		   (div:SI (reg:SI R4_REG)
2986			   (reg:SI R5_REG)))
2987	      (clobber (reg:SI T_REG))
2988	      (clobber (reg:SI PR_REG))
2989	      (clobber (reg:SI R1_REG))
2990	      (clobber (reg:SI R2_REG))
2991	      (clobber (reg:SI R3_REG))
2992	      (use (match_dup 3))])]
2993  ""
2994{
2995  rtx last;
2996
2997  operands[3] = gen_reg_rtx (Pmode);
2998  /* Emit the move of the address to a pseudo outside of the libcall.  */
2999  if (TARGET_DIVIDE_CALL_TABLE)
3000    {
3001      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
3002      last = gen_divsi3_i4_int (operands[0], operands[3]);
3003    }
3004  else if (TARGET_DIVIDE_CALL_FP)
3005    {
3006      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
3007      if (TARGET_FPU_SINGLE)
3008	last = gen_divsi3_i4_single (operands[0], operands[3]);
3009      else
3010	last = gen_divsi3_i4 (operands[0], operands[3]);
3011    }
3012  else if (TARGET_SH2A)
3013    {
3014      operands[1] = force_reg (SImode, operands[1]);
3015      operands[2] = force_reg (SImode, operands[2]);
3016      emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
3017      DONE;
3018    }
3019  else if (TARGET_DIVIDE_INV)
3020    {
3021      rtx dividend = operands[1];
3022      rtx divisor = operands[2];
3023      rtx tab_base;
3024      rtx nsb_res = gen_reg_rtx (DImode);
3025      rtx norm64 = gen_reg_rtx (DImode);
3026      rtx tab_ix = gen_reg_rtx (DImode);
3027      rtx norm32 = gen_reg_rtx (SImode);
3028      rtx i92 = force_reg (DImode, GEN_INT (92));
3029      rtx scratch0a = gen_reg_rtx (DImode);
3030      rtx scratch0b = gen_reg_rtx (DImode);
3031      rtx inv0 = gen_reg_rtx (SImode);
3032      rtx scratch1a = gen_reg_rtx (DImode);
3033      rtx scratch1b = gen_reg_rtx (DImode);
3034      rtx shift = gen_reg_rtx (DImode);
3035      rtx i2p27, i43;
3036      rtx inv1 = gen_reg_rtx (SImode);
3037      rtx scratch2a = gen_reg_rtx (DImode);
3038      rtx scratch2b = gen_reg_rtx (SImode);
3039      rtx inv2 = gen_reg_rtx (SImode);
3040      rtx scratch3a = gen_reg_rtx (DImode);
3041      rtx scratch3b = gen_reg_rtx (DImode);
3042      rtx scratch3c = gen_reg_rtx (DImode);
3043      rtx scratch3d = gen_reg_rtx (SImode);
3044      rtx scratch3e = gen_reg_rtx (DImode);
3045      rtx result = gen_reg_rtx (SImode);
3046
3047      if (! arith_reg_or_0_operand (dividend, SImode))
3048	dividend = force_reg (SImode, dividend);
3049      if (! arith_reg_operand (divisor, SImode))
3050	divisor = force_reg (SImode, divisor);
3051      if (flag_pic && Pmode != DImode)
3052	{
3053	  tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
3054	  tab_base = gen_datalabel_ref (tab_base);
3055	  tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
3056	}
3057      else
3058	{
3059	  tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
3060	  tab_base = gen_datalabel_ref (tab_base);
3061	  tab_base = force_reg (DImode, tab_base);
3062	}
3063      if (TARGET_DIVIDE_INV20U)
3064	i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
3065      else
3066	i2p27 = GEN_INT (0);
3067      if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
3068	i43 = force_reg (DImode, GEN_INT (43));
3069      else
3070	i43 = GEN_INT (0);
3071      emit_insn (gen_nsbdi (nsb_res,
3072			    simplify_gen_subreg (DImode, divisor, SImode, 0)));
3073      emit_insn (gen_ashldi3_media (norm64,
3074				    gen_rtx_SUBREG (DImode, divisor, 0),
3075				    nsb_res));
3076      emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
3077      emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
3078      emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
3079				   inv0, scratch0a, scratch0b,
3080				   scratch1a, scratch1b));
3081      emit_insn (gen_subdi3 (shift, i92, nsb_res));
3082      emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
3083				   scratch2a));
3084      emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
3085				   i2p27, i43,
3086				   scratch3a, scratch3b, scratch3c,
3087				   scratch2a, scratch2b, scratch3d, scratch3e));
3088      if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
3089	emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
3090      else if (TARGET_DIVIDE_INV_FP)
3091	emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
3092				     gen_reg_rtx (SImode), gen_reg_rtx (SImode),
3093				     gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
3094				     gen_reg_rtx (DFmode)));
3095      else
3096	emit_move_insn (operands[0], result);
3097      DONE;
3098    }
3099  else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
3100    {
3101      operands[1] = force_reg (SImode, operands[1]);
3102      operands[2] = force_reg (SImode, operands[2]);
3103      emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
3104      DONE;
3105    }
3106  else if (TARGET_SH5)
3107    {
3108      if (TARGET_DIVIDE_CALL2)
3109	{
3110	  rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
3111	  tab_base = gen_datalabel_ref (tab_base);
3112	  emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
3113	}
3114      if (TARGET_FPU_ANY && TARGET_SH1)
3115	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
3116      else if (TARGET_DIVIDE_CALL2)
3117	function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
3118      else
3119	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
3120
3121      if (TARGET_SHMEDIA)
3122	last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
3123		(operands[0], operands[3]));
3124      else if (TARGET_FPU_ANY)
3125	last = gen_divsi3_i4_single (operands[0], operands[3]);
3126      else
3127	last = gen_divsi3_i1 (operands[0], operands[3]);
3128    }
3129  else
3130    {
3131      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
3132      last = gen_divsi3_i1 (operands[0], operands[3]);
3133    }
3134  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
3135  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
3136  emit_insn (last);
3137  DONE;
3138})
3139
3140;; operands: scratch, tab_base, tab_ix
3141;; These are unspecs because we could generate an indexed addressing mode
3142;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
3143;; confuse reload.  See PR27117.
3144(define_insn "divsi_inv_qitable"
3145  [(set (match_operand:DI 0 "register_operand" "=r")
3146	(zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
3147				    (match_operand:DI 2 "register_operand" "r")]
3148			 UNSPEC_DIV_INV_TABLE)))]
3149  "TARGET_SHMEDIA"
3150  "ldx.ub	%1, %2, %0"
3151  [(set_attr "type" "load_media")
3152   (set_attr "highpart" "user")])
3153
3154;; operands: scratch, tab_base, tab_ix
3155(define_insn "divsi_inv_hitable"
3156  [(set (match_operand:DI 0 "register_operand" "=r")
3157	(sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
3158				    (match_operand:DI 2 "register_operand" "r")]
3159			 UNSPEC_DIV_INV_TABLE)))]
3160  "TARGET_SHMEDIA"
3161  "ldx.w	%1, %2, %0"
3162  [(set_attr "type" "load_media")
3163   (set_attr "highpart" "user")])
3164
3165;; operands: inv0, tab_base, tab_ix, norm32
3166;; scratch equiv in sdivsi3_2: r19, r21
3167(define_expand "divsi_inv_m0"
3168  [(set (match_operand:SI 0 "register_operand" "=r")
3169	(unspec:SI [(match_operand:DI 1 "register_operand" "r")
3170		    (match_operand:DI 2 "register_operand" "r")
3171		    (match_operand:SI 3 "register_operand" "r")]
3172	 UNSPEC_DIV_INV_M0))
3173   (clobber (match_operand:DI 4 "register_operand" "=r"))
3174   (clobber (match_operand:DI 5 "register_operand" "=r"))]
3175  "TARGET_SHMEDIA"
3176{
3177/*
3178tab_base: r20
3179tab_ix: r21
3180norm32: r25
3181 ldx.ub r20, r21, r19 // u0.8
3182 shlli r21, 1, r21
3183 muls.l r25, r19, r19 // s2.38
3184 ldx.w r20, r21, r21  // s2.14
3185 shari r19, 24, r19   // truncate to s2.14
3186 sub r21, r19, r19    // some 11 bit inverse in s1.14
3187*/
3188
3189  rtx inv0 = operands[0];
3190  rtx tab_base = operands[1];
3191  rtx tab_ix = operands[2];
3192  rtx norm32 = operands[3];
3193  rtx scratch0 = operands[4];
3194  rtx scratch0_si = gen_lowpart (SImode, scratch0);
3195  rtx scratch1 = operands[5];
3196
3197  emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
3198  emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
3199  emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
3200  emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
3201  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
3202  emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
3203  DONE;
3204})
3205
3206;; operands: inv1, tab_base, tab_ix, norm32
3207(define_insn_and_split "divsi_inv_m1"
3208  [(set (match_operand:SI 0 "register_operand" "=r")
3209	(unspec:SI [(match_operand:DI 1 "register_operand" "r")
3210		    (match_operand:DI 2 "register_operand" "r")
3211		    (match_operand:SI 3 "register_operand" "r")]
3212	 UNSPEC_DIV_INV_M1))
3213   (clobber (match_operand:SI 4 "register_operand" "=r"))
3214   (clobber (match_operand:DI 5 "register_operand" "=r"))
3215   (clobber (match_operand:DI 6 "register_operand" "=r"))
3216   (clobber (match_operand:DI 7 "register_operand" "=r"))
3217   (clobber (match_operand:DI 8 "register_operand" "=r"))]
3218  "TARGET_SHMEDIA"
3219  "#"
3220  "&& !can_create_pseudo_p ()"
3221  [(pc)]
3222{
3223/* inv0: r19
3224 muls.l r19, r19, r18 // u0.28
3225 muls.l r25, r18, r18 // s2.58
3226 shlli r19, 45, r0    // multiply by two and convert to s2.58
3227 sub r0, r18, r18
3228 shari r18, 28, r18   // some 18 bit inverse in s1.30
3229*/
3230
3231  rtx inv1 = operands[0];
3232  rtx tab_base = operands[1];
3233  rtx tab_ix = operands[2];
3234  rtx norm32 = operands[3];
3235  rtx inv0 = operands[4];
3236  rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
3237  rtx scratch0a = operands[5];
3238  rtx scratch0b = operands[6];
3239  rtx scratch0 = operands[7];
3240  rtx scratch1 = operands[8];
3241  rtx scratch1_si = gen_lowpart (SImode, scratch1);
3242
3243  emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
3244			       scratch0a, scratch0b));
3245  emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
3246  emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3247  emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
3248  emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
3249  emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
3250  DONE;
3251})
3252
3253;; operands: inv2, norm32, inv1, i92
3254(define_insn_and_split "divsi_inv_m2"
3255  [(set (match_operand:SI 0 "register_operand" "=r")
3256	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
3257		    (match_operand:SI 2 "register_operand" "r")
3258		    (match_operand:DI 3 "register_operand" "r")]
3259	 UNSPEC_DIV_INV_M2))
3260   (clobber (match_operand:DI 4 "register_operand" "=r"))]
3261  "TARGET_SHMEDIA"
3262  "#"
3263  "&& !can_create_pseudo_p ()"
3264  [(pc)]
3265{
3266/*
3267 muls.l r18, r25, r0  // s2.60
3268 shari r0, 16, r0     // s-16.44
3269  sub
3270 muls.l r0, r18, r19  // s-16.74
3271 shari r19, 30, r19   // s-16.44
3272*/
3273  rtx inv2 = operands[0];
3274  rtx norm32 = operands[1];
3275  rtx inv1 = operands[2];
3276  rtx i92 = operands[3];
3277  rtx scratch0 = operands[4];
3278  rtx scratch0_si = gen_lowpart (SImode, scratch0);
3279
3280  emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
3281  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
3282  emit_insn (gen_subdi3 (scratch0, i92, scratch0));
3283  emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
3284  emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
3285  DONE;
3286})
3287
3288(define_insn_and_split "divsi_inv_m3"
3289  [(set (match_operand:SI 0 "register_operand" "=r")
3290	(unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3291		    (match_operand:SI 2 "register_operand" "r")
3292		    (match_operand:SI 3 "register_operand" "r")
3293		    (match_operand:DI 4 "register_operand" "r")
3294		    (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
3295		    (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
3296	 UNSPEC_DIV_INV_M3))
3297   (clobber (match_operand:DI 7 "register_operand" "=r"))
3298   (clobber (match_operand:DI 8 "register_operand" "=r"))
3299   (clobber (match_operand:DI 9 "register_operand" "=r"))
3300   (clobber (match_operand:DI 10 "register_operand" "=r"))
3301   (clobber (match_operand:SI 11 "register_operand" "=r"))
3302   (clobber (match_operand:SI 12 "register_operand" "=r"))
3303   (clobber (match_operand:DI 13 "register_operand" "=r"))]
3304  "TARGET_SHMEDIA"
3305  "#"
3306  "&& !can_create_pseudo_p ()"
3307  [(pc)]
3308{
3309/*
3310  r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
3311  r0: scratch0  r19: scratch1 r21: scratch2
3312
3313  muls.l r18, r4, r25 // s32.30
3314 muls.l r19, r4, r19  // s15.30
3315 shari r25, 63, r21
3316  shari r19, 14, r19  // s18.-14
3317 sub r25, r19, r0
3318 shard r0, r1, r0
3319 sub r0, r21, r0
3320*/
3321
3322  rtx result = operands[0];
3323  rtx dividend = operands[1];
3324  rtx inv1 = operands[2];
3325  rtx inv2 = operands[3];
3326  rtx shift = operands[4];
3327  rtx scratch0 = operands[7];
3328  rtx scratch1 = operands[8];
3329  rtx scratch2 = operands[9];
3330
3331  if (satisfies_constraint_N (dividend))
3332    {
3333      emit_move_insn (result, dividend);
3334      DONE;
3335    }
3336
3337  emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
3338  emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
3339  emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
3340  emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
3341  emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
3342  emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
3343  emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
3344  DONE;
3345})
3346
3347;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
3348;; inv1: tab_base, tab_ix, norm32
3349;; inv2: norm32, inv1, i92
3350(define_insn_and_split "divsi_inv_m1_3"
3351  [(set (match_operand:SI 0 "register_operand" "=r")
3352	(unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3353		    (unspec:SI [(match_operand:DI 2 "register_operand" "r")
3354				(match_operand:DI 3 "register_operand" "r")
3355				(match_operand:SI 4 "register_operand" "r")]
3356		     UNSPEC_DIV_INV_M1)
3357		    (unspec:SI [(match_dup 4)
3358				(unspec:SI [(match_dup 2)
3359					    (match_dup 3)
3360					    (match_dup 4)] UNSPEC_DIV_INV_M1)
3361				(match_operand:SI 5 "" "")]
3362		     UNSPEC_DIV_INV_M2)
3363		    (match_operand:DI 6 "register_operand" "r")
3364		    (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
3365		    (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
3366	 UNSPEC_DIV_INV_M3))
3367   (clobber (match_operand:DI 9 "register_operand" "=r"))
3368   (clobber (match_operand:DI 10 "register_operand" "=r"))
3369   (clobber (match_operand:DI 11 "register_operand" "=r"))
3370   (clobber (match_operand:DI 12 "register_operand" "=r"))
3371   (clobber (match_operand:SI 13 "register_operand" "=r"))
3372   (clobber (match_operand:SI 14 "register_operand" "=r"))
3373   (clobber (match_operand:DI 15 "register_operand" "=r"))]
3374  "TARGET_SHMEDIA
3375   && (TARGET_DIVIDE_INV_MINLAT
3376       || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3377  "#"
3378  "&& !can_create_pseudo_p ()"
3379  [(pc)]
3380{
3381  rtx result = operands[0];
3382  rtx dividend = operands[1];
3383  rtx tab_base = operands[2];
3384  rtx tab_ix = operands[3];
3385  rtx norm32 = operands[4];
3386  /* rtx i92 = operands[5]; */
3387  rtx shift = operands[6];
3388  rtx i2p27 = operands[7];
3389  rtx i43 = operands[8];
3390  rtx scratch0 = operands[9];
3391  rtx scratch0_si = gen_lowpart (SImode, scratch0);
3392  rtx scratch1 = operands[10];
3393  rtx scratch1_si = gen_lowpart (SImode, scratch1);
3394  rtx scratch2 = operands[11];
3395  rtx scratch3 = operands[12];
3396  rtx scratch4 = operands[13];
3397  rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
3398  rtx scratch5 = operands[14];
3399  rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
3400  rtx scratch6 = operands[15];
3401
3402  emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
3403			       scratch0, scratch1));
3404  /* inv0 == scratch4 */
3405  if (! TARGET_DIVIDE_INV20U)
3406    {
3407      emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
3408      i2p27 = scratch0;
3409      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
3410    }
3411  else
3412    {
3413      emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
3414      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3415    }
3416  emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
3417  emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
3418  emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
3419  /* inv1 == scratch4 */
3420
3421  if (TARGET_DIVIDE_INV_MINLAT)
3422    {
3423      emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
3424      emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
3425      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
3426      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
3427      emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
3428      emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
3429      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
3430      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
3431      emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
3432      emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
3433      emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
3434    }
3435  else
3436    {
3437      rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
3438      /* Use separate scratch regs for nsb and sign to allow scheduling.  */
3439      emit_insn (gen_nsbdi (scratch6,
3440			    simplify_gen_subreg (DImode, dividend, SImode, 0)));
3441      emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
3442      emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
3443      emit_insn (gen_divsi_inv20 (scratch2,
3444				  norm32, scratch4, dividend,
3445				  scratch6, scratch3, i43,
3446				  /* scratch0 may be shared with i2p27.  */
3447				  scratch0, scratch1, scratch5,
3448				  label, label, i2p27));
3449    }
3450  emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
3451  emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
3452  DONE;
3453})
3454
3455(define_insn "divsi_inv20"
3456  [(set (match_operand:DI 0 "register_operand" "=&r")
3457	(unspec:DI [(match_operand:SI 1 "register_operand" "r")
3458		    (match_operand:SI 2 "register_operand" "r")
3459		    (match_operand:SI 3 "register_operand" "r")
3460		    (match_operand:DI 4 "register_operand" "r")
3461		    (match_operand:DI 5 "register_operand" "r")
3462		    (match_operand:DI 6 "register_operand" "r")
3463		    (match_operand:DI 12 "register_operand" "r")
3464		    (match_operand 10 "target_operand" "b")
3465		    (match_operand 11 "immediate_operand" "i")]
3466	 UNSPEC_DIV_INV20))
3467   (clobber (match_operand:DI 7 "register_operand" "=&r"))
3468   (clobber (match_operand:DI 8 "register_operand" "=&r"))
3469   (clobber (match_operand:SI 9 "register_operand" "=r"))]
3470  "TARGET_SHMEDIA
3471   && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3472{
3473/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
3474	     %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
3475	     %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
3476	     %10 label (tr), %11 label (imm)
3477
3478 muls.l inv1, norm32, scratch0  // s2.60
3479  muls.l inv1, dividend, result // s32.30
3480  xor i2p27, result_sign, round_scratch
3481 bge/u dividend_nsb, i43, tr.. (label)
3482 shari scratch0, 16, scratch0   // s-16.44
3483 muls.l sratch0_si, inv1, scratch0 // s-16.74
3484  sub result, round_scratch, result
3485  shari dividend, 14, scratch1   // s19.-14
3486 shari scratch0, 30, scratch0   // s-16.44
3487 muls.l scratch0, scratch1, round_scratch // s15.30
3488label:
3489 sub result, round_scratch, result */
3490
3491  const bool likely = TARGET_DIVIDE_INV20L;
3492  if (likely)
3493    return
3494	       "muls.l	%2, %3, %0"	"\n"
3495	"	xor	%12, %5, %7"	"\n"
3496	"	bge/l	%4, %6, %10"	"\n"
3497	"	muls.l	%2, %1, %8"	"\n"
3498	"	shari	%8, 16, %8"	"\n"
3499	"	muls.l	%8, %2, %8"	"\n"
3500	"	shari	%3, 14, %9"	"\n"
3501	"	shari	%8, 30, %8"	"\n"
3502	"	muls.l	%8, %9, %8"	"\n"
3503	"	sub	%0, %8, %0"	"\n"
3504	"%11:	add	%0, %7, %0";
3505  else
3506    return
3507	       "muls.l	%2, %1, %8"	"\n"
3508	"	muls.l	%2, %3, %0"	"\n"
3509	"	xor	%12, %5, %7"	"\n"
3510	"	bge/u	%4, %6, %10"	"\n"
3511	"	shari	%8, 16, %8"	"\n"
3512	"	muls.l	%8, %2, %8"	"\n"
3513	"	sub	%0, %7, %0"	"\n"
3514	"	shari	%3, 14, %9"	"\n"
3515	"	shari	%8, 30, %8"	"\n"
3516	"	muls.l	%8, %9, %7"	"\n"
3517	"%11:	sub	%0, %7, %0";
3518})
3519
3520(define_insn_and_split "divsi_inv_fp"
3521  [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3522	(div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3523		(match_operand:SI 2 "register_operand" "rf")))
3524   (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3525   (clobber (match_operand:SI 4 "register_operand" "=r"))
3526   (clobber (match_operand:SI 5 "register_operand" "=r"))
3527   (clobber (match_operand:DF 6 "register_operand" "=r"))
3528   (clobber (match_operand:DF 7 "register_operand" "=r"))
3529   (clobber (match_operand:DF 8 "register_operand" "=r"))]
3530  "TARGET_SHMEDIA_FPU"
3531  "#"
3532  "&& (reload_in_progress || reload_completed)"
3533  [(set (match_dup 0) (match_dup 3))]
3534  ""
3535  [(set_attr "highpart" "must_split")])
3536
3537;; If a matching group of divide-by-inverse instructions is in the same
3538;; basic block after gcse & loop optimizations, we want to transform them
3539;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3540(define_insn_and_split "*divsi_inv_fp_combine"
3541  [(set (match_operand:SI 0 "register_operand" "=f")
3542	(div:SI (match_operand:SI 1 "register_operand" "f")
3543		(match_operand:SI 2 "register_operand" "f")))
3544   (use (unspec:SI [(match_dup 1)
3545		    (match_operand:SI 3 "" "")
3546		    (unspec:SI [(match_operand:SI 4 "" "")
3547				(match_dup 3)
3548				(match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3549		    (match_operand:DI 6 "" "")
3550		    (const_int 0)
3551		    (const_int 0)] UNSPEC_DIV_INV_M3))
3552   (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3553   (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3554   (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3555   (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3556   (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3557  "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3558  "#"
3559  "&& 1"
3560  [(set (match_dup 9) (float:DF (match_dup 1)))
3561   (set (match_dup 10) (float:DF (match_dup 2)))
3562   (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3563   (set (match_dup 8)
3564	(fix:SI (match_dup 11)))
3565   (set (match_dup 0) (match_dup 8))]
3566{
3567  if (! fp_arith_reg_operand (operands[1], SImode))
3568    {
3569      emit_move_insn (operands[7], operands[1]);
3570      operands[1] = operands[7];
3571    }
3572  if (! fp_arith_reg_operand (operands[2], SImode))
3573    {
3574      emit_move_insn (operands[8], operands[2]);
3575      operands[2] = operands[8];
3576    }
3577}
3578  [(set_attr "highpart" "must_split")])
3579
3580;; -------------------------------------------------------------------------
3581;; Multiplication instructions
3582;; -------------------------------------------------------------------------
3583
3584(define_insn "umulhisi3_i"
3585  [(set (reg:SI MACL_REG)
3586	(mult:SI (zero_extend:SI
3587		  (match_operand:HI 0 "arith_reg_operand" "r"))
3588		 (zero_extend:SI
3589		  (match_operand:HI 1 "arith_reg_operand" "r"))))]
3590  "TARGET_SH1"
3591  "mulu.w	%1,%0"
3592  [(set_attr "type" "smpy")])
3593
3594(define_insn "mulhisi3_i"
3595  [(set (reg:SI MACL_REG)
3596	(mult:SI (sign_extend:SI
3597		  (match_operand:HI 0 "arith_reg_operand" "r"))
3598		 (sign_extend:SI
3599		  (match_operand:HI 1 "arith_reg_operand" "r"))))]
3600  "TARGET_SH1"
3601  "muls.w	%1,%0"
3602  [(set_attr "type" "smpy")])
3603
3604(define_expand "mulhisi3"
3605  [(set (reg:SI MACL_REG)
3606	(mult:SI (sign_extend:SI
3607		  (match_operand:HI 1 "arith_reg_operand" ""))
3608		 (sign_extend:SI
3609		  (match_operand:HI 2 "arith_reg_operand" ""))))
3610   (set (match_operand:SI 0 "arith_reg_operand" "")
3611	(reg:SI MACL_REG))]
3612  "TARGET_SH1"
3613{
3614  rtx_insn *insn;
3615  rtx macl;
3616
3617  macl = gen_rtx_REG (SImode, MACL_REG);
3618  start_sequence ();
3619  emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3620  insn = get_insns ();  
3621  end_sequence ();
3622  /* expand_binop can't find a suitable code in umul_widen_optab to
3623     make a REG_EQUAL note from, so make one here.
3624     See also smulsi3_highpart.
3625     ??? Alternatively, we could put this at the calling site of expand_binop,
3626     i.e. expand_expr.  */
3627  /* Use emit_libcall_block for loop invariant code motion and to make
3628     a REG_EQUAL note.  */
3629  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3630
3631  DONE;
3632})
3633
3634(define_expand "umulhisi3"
3635  [(set (reg:SI MACL_REG)
3636	(mult:SI (zero_extend:SI
3637		  (match_operand:HI 1 "arith_reg_operand" ""))
3638		 (zero_extend:SI
3639		  (match_operand:HI 2 "arith_reg_operand" ""))))
3640   (set (match_operand:SI 0 "arith_reg_operand" "")
3641	(reg:SI MACL_REG))]
3642  "TARGET_SH1"
3643{
3644  rtx_insn *insn;
3645  rtx macl;
3646
3647  macl = gen_rtx_REG (SImode, MACL_REG);
3648  start_sequence ();
3649  emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3650  insn = get_insns ();  
3651  end_sequence ();
3652  /* expand_binop can't find a suitable code in umul_widen_optab to
3653     make a REG_EQUAL note from, so make one here.
3654     See also smulsi3_highpart.
3655     ??? Alternatively, we could put this at the calling site of expand_binop,
3656     i.e. expand_expr.  */
3657  /* Use emit_libcall_block for loop invariant code motion and to make
3658     a REG_EQUAL note.  */
3659  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3660
3661  DONE;
3662})
3663
3664;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3665;; a call to a routine which clobbers known registers.
3666(define_insn ""
3667  [(set (match_operand:SI 1 "register_operand" "=z")
3668	(mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3669   (clobber (reg:SI MACL_REG))
3670   (clobber (reg:SI T_REG))
3671   (clobber (reg:SI PR_REG))
3672   (clobber (reg:SI R3_REG))
3673   (clobber (reg:SI R2_REG))
3674   (clobber (reg:SI R1_REG))
3675   (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3676  "TARGET_SH1"
3677  "jsr	@%0%#"
3678  [(set_attr "type" "sfunc")
3679   (set_attr "needs_delay_slot" "yes")])
3680
3681(define_expand "mulsi3_call"
3682  [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3683   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3684   (parallel[(set (match_operand:SI 0 "register_operand" "")
3685		  (mult:SI (reg:SI R4_REG)
3686			   (reg:SI R5_REG)))
3687	     (clobber (reg:SI MACL_REG))
3688	     (clobber (reg:SI T_REG))
3689	     (clobber (reg:SI PR_REG))
3690	     (clobber (reg:SI R3_REG))
3691	     (clobber (reg:SI R2_REG))
3692	     (clobber (reg:SI R1_REG))
3693	     (use (match_operand:SI 3 "register_operand" ""))])]
3694  "TARGET_SH1"
3695  "")
3696
3697(define_insn "mul_r"
3698  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3699	(mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3700		 (match_operand:SI 2 "arith_reg_operand" "z")))]
3701  "TARGET_SH2A"
3702  "mulr	%2,%0"
3703  [(set_attr "type" "dmpy")])
3704
3705(define_insn "mul_l"
3706  [(set (reg:SI MACL_REG)
3707	(mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3708		 (match_operand:SI 1 "arith_reg_operand" "r")))]
3709  "TARGET_SH2"
3710  "mul.l	%1,%0"
3711  [(set_attr "type" "dmpy")])
3712
3713(define_expand "mulsi3"
3714  [(set (reg:SI MACL_REG)
3715	(mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
3716		  (match_operand:SI 2 "arith_reg_operand" "")))
3717   (set (match_operand:SI 0 "arith_reg_operand" "")
3718	(reg:SI MACL_REG))]
3719  "TARGET_SH1"
3720{
3721  if (!TARGET_SH2)
3722    {
3723      /* The address must be set outside the libcall,
3724	 since it goes into a pseudo.  */
3725      rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
3726      rtx addr = force_reg (SImode, sym);
3727      rtx insns = gen_mulsi3_call (operands[0], operands[1],
3728				   operands[2], addr);
3729      emit_insn (insns);
3730    }
3731  else
3732    {
3733      rtx macl = gen_rtx_REG (SImode, MACL_REG);
3734
3735      emit_insn (gen_mul_l (operands[1], operands[2]));
3736      /* consec_sets_giv can only recognize the first insn that sets a
3737	 giv as the giv insn.  So we must tag this also with a REG_EQUAL
3738	 note.  */
3739      emit_insn (gen_movsi_i ((operands[0]), macl));
3740    }
3741  DONE;
3742})
3743
3744(define_insn "mulsidi3_i"
3745  [(set (reg:SI MACH_REG)
3746	(truncate:SI
3747	 (lshiftrt:DI
3748	  (mult:DI
3749	   (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3750	   (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3751	  (const_int 32))))
3752   (set (reg:SI MACL_REG)
3753	(mult:SI (match_dup 0)
3754		 (match_dup 1)))]
3755  "TARGET_SH2"
3756  "dmuls.l	%1,%0"
3757  [(set_attr "type" "dmpy")])
3758
3759(define_expand "mulsidi3"
3760  [(set (match_operand:DI 0 "arith_reg_dest" "")
3761	(mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3762		 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3763  "TARGET_SH2 || TARGET_SHMEDIA"
3764{
3765  if (TARGET_SH2)
3766    {
3767      emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3768      DONE;
3769    }
3770})
3771
3772(define_insn "mulsidi3_media"
3773  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3774	(mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3775		 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3776  "TARGET_SHMEDIA"
3777  "muls.l	%1, %2, %0"
3778  [(set_attr "type" "dmpy_media")
3779   (set_attr "highpart" "ignore")])
3780
3781(define_insn_and_split "mulsidi3_compact"
3782  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3783	(mult:DI
3784	 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3785	 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3786   (clobber (reg:SI MACH_REG))
3787   (clobber (reg:SI MACL_REG))]
3788  "TARGET_SH2"
3789  "#"
3790  "&& 1"
3791  [(const_int 0)]
3792{
3793  rtx low_dst = gen_lowpart (SImode, operands[0]);
3794  rtx high_dst = gen_highpart (SImode, operands[0]);
3795
3796  emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3797
3798  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3799  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3800  /* We need something to tag the possible REG_EQUAL notes on to.  */
3801  emit_move_insn (operands[0], operands[0]);
3802  DONE;
3803})
3804
3805(define_insn "umulsidi3_i"
3806  [(set (reg:SI MACH_REG)
3807	(truncate:SI
3808	 (lshiftrt:DI
3809	  (mult:DI
3810	   (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3811	   (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3812	  (const_int 32))))
3813   (set (reg:SI MACL_REG)
3814	(mult:SI (match_dup 0)
3815		 (match_dup 1)))]
3816  "TARGET_SH2"
3817  "dmulu.l	%1,%0"
3818  [(set_attr "type" "dmpy")])
3819
3820(define_expand "umulsidi3"
3821  [(set (match_operand:DI 0 "arith_reg_dest" "")
3822	(mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3823		 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3824  "TARGET_SH2 || TARGET_SHMEDIA"
3825{
3826  if (TARGET_SH2)
3827    {
3828      emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3829      DONE;
3830    }
3831})
3832
3833(define_insn "umulsidi3_media"
3834  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3835	(mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3836		 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3837  "TARGET_SHMEDIA"
3838  "mulu.l	%1, %2, %0"
3839  [(set_attr "type" "dmpy_media")
3840   (set_attr "highpart" "ignore")])
3841
3842(define_insn_and_split "umulsidi3_compact"
3843  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3844	(mult:DI
3845	 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3846	 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3847   (clobber (reg:SI MACH_REG))
3848   (clobber (reg:SI MACL_REG))]
3849  "TARGET_SH2"
3850  "#"
3851  "&& 1"
3852  [(const_int 0)]
3853{
3854  rtx low_dst = gen_lowpart (SImode, operands[0]);
3855  rtx high_dst = gen_highpart (SImode, operands[0]);
3856
3857  emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3858
3859  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3860  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3861  /* We need something to tag the possible REG_EQUAL notes on to.  */
3862  emit_move_insn (operands[0], operands[0]);
3863  DONE;
3864})
3865
3866(define_insn "smulsi3_highpart_i"
3867  [(set (reg:SI MACH_REG)
3868	(truncate:SI
3869	 (lshiftrt:DI
3870	  (mult:DI
3871	   (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3872	   (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3873	  (const_int 32))))
3874   (clobber (reg:SI MACL_REG))]
3875  "TARGET_SH2"
3876  "dmuls.l	%1,%0"
3877  [(set_attr "type" "dmpy")])
3878
3879(define_expand "smulsi3_highpart"
3880  [(parallel
3881    [(set (reg:SI MACH_REG)
3882	  (truncate:SI
3883	   (lshiftrt:DI
3884	    (mult:DI
3885	     (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3886	     (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3887	    (const_int 32))))
3888    (clobber (reg:SI MACL_REG))])
3889   (set (match_operand:SI 0 "arith_reg_operand" "")
3890	(reg:SI MACH_REG))]
3891  "TARGET_SH2"
3892{
3893  rtx_insn *insn;
3894  rtx mach;
3895
3896  mach = gen_rtx_REG (SImode, MACH_REG);
3897  start_sequence ();
3898  emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3899  insn = get_insns ();  
3900  end_sequence ();
3901  /* expand_binop can't find a suitable code in mul_highpart_optab to
3902     make a REG_EQUAL note from, so make one here.
3903     See also {,u}mulhisi.
3904     ??? Alternatively, we could put this at the calling site of expand_binop,
3905     i.e. expand_mult_highpart.  */
3906  /* Use emit_libcall_block for loop invariant code motion and to make
3907     a REG_EQUAL note.  */
3908  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3909
3910  DONE;
3911})
3912
3913(define_insn "umulsi3_highpart_i"
3914  [(set (reg:SI MACH_REG)
3915	(truncate:SI
3916	 (lshiftrt:DI
3917	  (mult:DI
3918	   (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3919	   (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3920	  (const_int 32))))
3921   (clobber (reg:SI MACL_REG))]
3922  "TARGET_SH2"
3923  "dmulu.l	%1,%0"
3924  [(set_attr "type" "dmpy")])
3925
3926(define_expand "umulsi3_highpart"
3927  [(parallel
3928    [(set (reg:SI MACH_REG)
3929	  (truncate:SI
3930	   (lshiftrt:DI
3931	    (mult:DI
3932	     (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3933	     (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3934	    (const_int 32))))
3935    (clobber (reg:SI MACL_REG))])
3936   (set (match_operand:SI 0 "arith_reg_operand" "")
3937	(reg:SI MACH_REG))]
3938  "TARGET_SH2"
3939{
3940  rtx_insn *insn;
3941  rtx mach;
3942
3943  mach = gen_rtx_REG (SImode, MACH_REG);
3944  start_sequence ();
3945  emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3946  insn = get_insns ();  
3947  end_sequence ();
3948  /* Use emit_libcall_block for loop invariant code motion and to make
3949     a REG_EQUAL note.  */
3950  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3951
3952  DONE;
3953})
3954
3955(define_insn_and_split "muldi3"
3956  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3957	(mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3958		 (match_operand:DI 2 "arith_reg_operand" "r")))
3959   (clobber (match_scratch:DI 3 "=&r"))
3960   (clobber (match_scratch:DI 4 "=r"))]
3961  "TARGET_SHMEDIA"
3962  "#"
3963  "reload_completed"
3964  [(const_int 0)]
3965{
3966  rtx op3_v2si, op2_v2si;
3967
3968  op3_v2si = operands[3];
3969  if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3970    {
3971      op3_v2si = XEXP (op3_v2si, 0);
3972      op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3973    }
3974  op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3975  op2_v2si = operands[2];
3976  if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3977    {
3978      op2_v2si = XEXP (op2_v2si, 0);
3979      op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3980    }
3981  op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3982  emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3983  emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3984  emit_insn (gen_umulsidi3_media (operands[4],
3985				 sh_gen_truncate (SImode, operands[1], 0),
3986				 sh_gen_truncate (SImode, operands[2], 0)));
3987  emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3988  emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3989  emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3990  emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3991  DONE;
3992})
3993
3994;; -------------------------------------------------------------------------
3995;; Logical operations
3996;; -------------------------------------------------------------------------
3997
3998(define_expand "andsi3"
3999  [(set (match_operand:SI 0 "arith_reg_operand" "")
4000	(and:SI (match_operand:SI 1 "logical_reg_operand" "")
4001		(match_operand:SI 2 "logical_and_operand" "")))]
4002  ""
4003{
4004  /* If it is possible to turn the and insn into a zero extension
4005     already, redundant zero extensions will be folded, which results
4006     in better code.  
4007     Ideally the splitter of *andsi_compact would be enough, if redundant
4008     zero extensions were detected after the combine pass, which does not
4009     happen at the moment.  */
4010  if (TARGET_SH1)
4011    {
4012      if (satisfies_constraint_Jmb (operands[2]))
4013	{
4014	  emit_insn (gen_zero_extendqisi2 (operands[0],
4015					   gen_lowpart (QImode, operands[1])));
4016	  DONE;
4017	}
4018      else if (satisfies_constraint_Jmw (operands[2]))
4019	{
4020	  emit_insn (gen_zero_extendhisi2 (operands[0],
4021					   gen_lowpart (HImode, operands[1])));
4022	  DONE;
4023	}
4024    }
4025})
4026
4027(define_insn_and_split "*andsi_compact"
4028  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
4029	(and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
4030		(match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
4031  "TARGET_SH1"
4032  "@
4033	extu.b	%1,%0
4034	extu.w	%1,%0
4035	and	%2,%0
4036	and	%2,%0"
4037  "&& 1"
4038 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
4039{
4040  if (satisfies_constraint_Jmb (operands[2]))
4041    operands[1] = gen_lowpart (QImode, operands[1]);
4042  else if (satisfies_constraint_Jmw (operands[2]))
4043    operands[1] = gen_lowpart (HImode, operands[1]);
4044  else
4045    FAIL;
4046}
4047  [(set_attr "type" "arith")])
4048
4049(define_insn "*andsi3_media"
4050  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4051	(and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
4052		(match_operand:SI 2 "logical_operand" "r,I10")))]
4053  "TARGET_SHMEDIA"
4054  "@
4055	and	%1, %2, %0
4056	andi	%1, %2, %0"
4057  [(set_attr "type" "arith_media")])
4058
4059(define_insn "*andsi3_bclr"
4060  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4061	(and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
4062		(match_operand:SI 2 "const_int_operand" "Psz")))]
4063  "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
4064  "bclr	%W2,%0"
4065  [(set_attr "type" "arith")])
4066
4067(define_insn_and_split "anddi3"
4068  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
4069	(and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
4070		(match_operand:DI 2 "and_operand" "r,I10,J16")))]
4071  "TARGET_SHMEDIA"
4072  "@
4073	and	%1, %2, %0
4074	andi	%1, %2, %0
4075	#"
4076  "reload_completed
4077   && ! logical_operand (operands[2], DImode)"
4078  [(const_int 0)]
4079{
4080  if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
4081    emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
4082  else
4083    emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
4084  DONE;
4085}
4086  [(set_attr "type" "arith_media")])
4087
4088(define_insn "andcsi3"
4089  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4090	(and:SI (match_operand:SI 1 "arith_reg_operand" "r")
4091		(not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4092  "TARGET_SHMEDIA"
4093  "andc	%1,%2,%0"
4094  [(set_attr "type" "arith_media")])
4095
4096(define_insn "andcdi3"
4097  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4098	(and:DI (match_operand:DI 1 "arith_reg_operand" "r")
4099		(not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
4100  "TARGET_SHMEDIA"
4101  "andc	%1,%2,%0"
4102  [(set_attr "type" "arith_media")])
4103
4104(define_expand "iorsi3"
4105  [(set (match_operand:SI 0 "arith_reg_operand" "")
4106	(ior:SI (match_operand:SI 1 "logical_reg_operand" "")
4107		(match_operand:SI 2 "logical_operand" "")))]
4108  ""
4109  "")
4110
4111(define_insn "*iorsi3_compact"
4112  [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
4113	(ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
4114		(match_operand:SI 2 "logical_operand" "r,K08")))]
4115  "TARGET_SH1
4116   && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
4117  "or	%2,%0"
4118  [(set_attr "type" "arith")])
4119
4120(define_insn "*iorsi3_media"
4121  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4122	(ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
4123		(match_operand:SI 2 "logical_operand" "r,I10")))]
4124  "TARGET_SHMEDIA"
4125  "@
4126	or	%1, %2, %0
4127	ori	%1, %2, %0"
4128  [(set_attr "type" "arith_media")])
4129
4130(define_insn "*iorsi3_bset"
4131  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4132	(ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
4133	(match_operand:SI 2 "const_int_operand" "Pso")))]
4134  "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
4135  "bset	%V2,%0"
4136  [(set_attr "type" "arith")])
4137
4138(define_insn "iordi3"
4139  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4140	(ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
4141		(match_operand:DI 2 "logical_operand" "r,I10")))]
4142  "TARGET_SHMEDIA"
4143  "@
4144	or	%1, %2, %0
4145	ori	%1, %2, %0"
4146  [(set_attr "type" "arith_media")])
4147
4148(define_insn_and_split "*logical_sidi3"
4149  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4150	(sign_extend:DI (match_operator:SI 3 "logical_operator"
4151			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
4152			   (match_operand:SI 2 "logical_operand" "r,I10")])))]
4153  "TARGET_SHMEDIA"
4154  "#"
4155  "&& reload_completed"
4156  [(set (match_dup 0) (match_dup 3))]
4157{
4158  operands[3]
4159    = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
4160		      simplify_gen_subreg (DImode, operands[1], SImode, 0),
4161		      simplify_gen_subreg (DImode, operands[2], SImode, 0));
4162})
4163
4164(define_insn_and_split "*logical_sidisi3"
4165  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4166	(truncate:SI (sign_extend:DI
4167			(match_operator:SI 3 "logical_operator"
4168			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
4169			   (match_operand:SI 2 "logical_operand" "r,I10")]))))]
4170  "TARGET_SHMEDIA"
4171  "#"
4172  "&& 1"
4173  [(set (match_dup 0) (match_dup 3))])
4174
4175(define_insn_and_split "*logical_sidi3_2"
4176  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4177	(sign_extend:DI (truncate:SI (sign_extend:DI
4178			(match_operator:SI 3 "logical_operator"
4179			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
4180			   (match_operand:SI 2 "logical_operand" "r,I10")])))))]
4181  "TARGET_SHMEDIA"
4182  "#"
4183  "&& 1"
4184  [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
4185
4186(define_expand "xorsi3"
4187  [(set (match_operand:SI 0 "arith_reg_operand" "")
4188	(xor:SI (match_operand:SI 1 "logical_reg_operand" "")
4189		(match_operand:SI 2 "xor_operand" "")))]
4190  ""
4191  "")
4192
4193(define_insn "*xorsi3_compact"
4194  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
4195	(xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
4196		(match_operand:SI 2 "logical_operand" "K08,r")))]
4197  "TARGET_SH1"
4198  "xor	%2,%0"
4199  [(set_attr "type" "arith")])
4200
4201;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
4202;; of results where one of the inputs is a T bit store.  Notice that this
4203;; pattern must not match during reload.  If reload picks this pattern it
4204;; will be impossible to split it afterwards.
4205(define_insn_and_split "*logical_op_t"
4206  [(set (match_operand:SI 0 "arith_reg_dest")
4207	(match_operator:SI 3 "logical_operator"
4208	  [(match_operand:SI 1 "arith_reg_operand")
4209	   (match_operand:SI 2 "t_reg_operand")]))]
4210  "TARGET_SH1 && can_create_pseudo_p ()"
4211  "#"
4212  "&& 1"
4213  [(set (match_dup 4) (reg:SI T_REG))
4214   (set (match_dup 0) (match_dup 3))]
4215{
4216  operands[4] = gen_reg_rtx (SImode);
4217  operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
4218				operands[1], operands[4]);
4219})
4220
4221(define_insn "*xorsi3_media"
4222  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4223	(xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
4224		(match_operand:SI 2 "xor_operand" "r,I06")))]
4225  "TARGET_SHMEDIA"
4226  "@
4227	xor	%1, %2, %0
4228	xori	%1, %2, %0"
4229  [(set_attr "type" "arith_media")])
4230
4231(define_insn "xordi3"
4232  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4233	(xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
4234		(match_operand:DI 2 "xor_operand" "r,I06")))]
4235  "TARGET_SHMEDIA"
4236  "@
4237	xor	%1, %2, %0
4238	xori	%1, %2, %0"
4239  [(set_attr "type" "arith_media")])
4240
4241;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
4242;; converts 2 * sign extend -> logical op into logical op -> sign extend
4243(define_split
4244  [(set (match_operand:DI 0 "arith_reg_dest" "")
4245	(sign_extend:DI (match_operator 4 "binary_logical_operator"
4246			  [(match_operand 1 "any_register_operand" "")
4247			   (match_operand 2 "any_register_operand" "")])))]
4248  "TARGET_SHMEDIA"
4249  [(set (match_dup 5) (match_dup 4))
4250   (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
4251{
4252  machine_mode inmode = GET_MODE (operands[1]);
4253  int offset = 0;
4254
4255  if (GET_CODE (operands[0]) == SUBREG)
4256    {
4257      offset = SUBREG_BYTE (operands[0]);
4258      operands[0] = SUBREG_REG (operands[0]);
4259    }
4260  gcc_assert (REG_P (operands[0]));
4261  if (TARGET_BIG_ENDIAN)
4262    offset += 8 - GET_MODE_SIZE (inmode);
4263  operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
4264})
4265
4266;; -------------------------------------------------------------------------
4267;; Shifts and rotates
4268;; -------------------------------------------------------------------------
4269
4270;; Let combine see that we can get the MSB and LSB into the T bit
4271;; via shll and shlr.  This allows it to plug it into insns that can have
4272;; the T bit as an input (e.g. addc).
4273;; FIXME: On SH2A use bld #0,Rn instead of shlr to avoid mutating the input.
4274(define_insn_and_split "*reg_lsb_t"
4275  [(set (reg:SI T_REG)
4276	(and:SI (match_operand:SI 0 "arith_reg_operand")
4277		(const_int 1)))]
4278  "TARGET_SH1 && can_create_pseudo_p ()"
4279  "#"
4280  "&& 1"
4281  [(const_int 0)]
4282{
4283  emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[0]));
4284})
4285
4286(define_insn_and_split "*reg_msb_t"
4287  [(set (reg:SI T_REG)
4288	(lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
4289		     (const_int 31)))]
4290  "TARGET_SH1 && can_create_pseudo_p ()"
4291  "#"
4292  "&& 1"
4293  [(const_int 0)]
4294{
4295  emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
4296})
4297
4298(define_expand "rotldi3"
4299  [(set (match_operand:DI 0 "arith_reg_dest" "")
4300	(rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
4301		   (match_operand:HI 2 "mextr_bit_offset" "")))]
4302  "TARGET_SHMEDIA"
4303{
4304  if (! mextr_bit_offset (operands[2], HImode))
4305    FAIL;
4306})
4307
4308(define_insn "rotldi3_mextr"
4309  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4310	(rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
4311		   (match_operand:HI 2 "mextr_bit_offset" "i")))]
4312  "TARGET_SHMEDIA"
4313{
4314  static char templ[16];
4315  sprintf (templ, "mextr%d	%%1,%%1,%%0",
4316	   8 - (int) (INTVAL (operands[2]) >> 3));
4317  return templ;
4318}
4319  [(set_attr "type" "arith_media")])
4320
4321(define_expand "rotrdi3"
4322  [(set (match_operand:DI 0 "arith_reg_dest" "")
4323	(rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
4324		     (match_operand:HI 2 "mextr_bit_offset" "")))]
4325  "TARGET_SHMEDIA"
4326{
4327  if (! mextr_bit_offset (operands[2], HImode))
4328    FAIL;
4329})
4330
4331(define_insn "rotrdi3_mextr"
4332  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4333	(rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
4334		     (match_operand:HI 2 "mextr_bit_offset" "i")))]
4335  "TARGET_SHMEDIA"
4336{
4337  static char templ[16];
4338  sprintf (templ, "mextr%d	%%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
4339  return templ;
4340}
4341  [(set_attr "type" "arith_media")])
4342
4343(define_split
4344  [(set (match_operand:DI 0 "arith_reg_dest" "")
4345	(ior:DI (zero_extend:DI (mem:QI (match_operand 1
4346					 "ua_address_operand" "")))
4347		(ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
4348			   (const_int 8))))
4349   (clobber (match_operand:DI 3 "register_operand" ""))]
4350  "TARGET_SHMEDIA"
4351  [(match_dup 4) (match_dup 5)]
4352{
4353  operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
4354		 (operands[3], operands[1]));
4355  operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
4356			      GEN_INT (56), GEN_INT (8));
4357})
4358
4359(define_expand "rotrsi3"
4360  [(set (match_operand:SI 0 "arith_reg_dest")
4361	(rotatert:SI (match_operand:SI 1 "arith_reg_operand")
4362		     (match_operand:SI 2 "const_int_operand")))]
4363  "TARGET_SH1"
4364{
4365  HOST_WIDE_INT ival = INTVAL (operands[2]);
4366  if (ival == 1)
4367    {
4368      emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
4369      DONE;
4370    }
4371
4372  FAIL;
4373})
4374
4375(define_insn "rotrsi3_1"
4376  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4377	(rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4378		     (const_int 1)))
4379   (set (reg:SI T_REG)
4380	(and:SI (match_dup 1) (const_int 1)))]
4381  "TARGET_SH1"
4382  "rotr	%0"
4383  [(set_attr "type" "arith")])
4384
4385;; A slimplified version of rotr for combine.
4386(define_insn "*rotrsi3_1"
4387  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4388	(rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4389		     (const_int 1)))
4390   (clobber (reg:SI T_REG))]
4391  "TARGET_SH1"
4392  "rotr	%0"
4393  [(set_attr "type" "arith")])
4394
4395(define_insn "rotlsi3_1"
4396  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4397	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4398		   (const_int 1)))
4399   (set (reg:SI T_REG)
4400	(lshiftrt:SI (match_dup 1) (const_int 31)))]
4401  "TARGET_SH1"
4402  "rotl	%0"
4403  [(set_attr "type" "arith")])
4404
4405;; A simplified version of rotl for combine.
4406(define_insn "*rotlsi3_1"
4407  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4408	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4409		   (const_int 1)))
4410   (clobber (reg:SI T_REG))]
4411  "TARGET_SH1"
4412  "rotl	%0"
4413  [(set_attr "type" "arith")])
4414
4415(define_insn "rotlsi3_31"
4416  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4417	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4418		   (const_int 31)))
4419   (clobber (reg:SI T_REG))]
4420  "TARGET_SH1"
4421  "rotr	%0"
4422  [(set_attr "type" "arith")])
4423
4424(define_insn "rotlsi3_16"
4425  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4426	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
4427		   (const_int 16)))]
4428  "TARGET_SH1"
4429  "swap.w	%1,%0"
4430  [(set_attr "type" "arith")])
4431
4432(define_expand "rotlsi3"
4433  [(set (match_operand:SI 0 "arith_reg_dest")
4434	(rotate:SI (match_operand:SI 1 "arith_reg_operand")
4435		   (match_operand:SI 2 "const_int_operand")))]
4436  "TARGET_SH1"
4437{
4438  static const char rot_tab[] = {
4439    000, 000, 000, 000, 000, 000, 010, 001,
4440    001, 001, 011, 013, 003, 003, 003, 003,
4441    003, 003, 003, 003, 003, 013, 012, 002,
4442    002, 002, 010, 000, 000, 000, 000, 000,
4443  };
4444
4445  int count = INTVAL (operands[2]);
4446  int choice = rot_tab[count];
4447  if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
4448    FAIL;
4449  choice &= 7;
4450  switch (choice)
4451    {
4452    case 0:
4453      emit_move_insn (operands[0], operands[1]);
4454      count -= (count & 16) * 2;
4455      break;
4456    case 3:
4457     emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
4458     count -= 16;
4459     break;
4460    case 1:
4461    case 2:
4462      {
4463	rtx parts[2];
4464	parts[0] = gen_reg_rtx (SImode);
4465	parts[1] = gen_reg_rtx (SImode);
4466	emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
4467	emit_move_insn (parts[choice-1], operands[1]);
4468	emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
4469	emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
4470	emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
4471	count = (count & ~16) - 8;
4472      }
4473    }
4474
4475  for (; count > 0; count--)
4476    emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
4477  for (; count < 0; count++)
4478    emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4479
4480  DONE;
4481})
4482
4483(define_insn "rotlhi3_8"
4484  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4485	(rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
4486		   (const_int 8)))]
4487  "TARGET_SH1"
4488  "swap.b	%1,%0"
4489  [(set_attr "type" "arith")])
4490
4491(define_expand "rotlhi3"
4492  [(set (match_operand:HI 0 "arith_reg_operand")
4493	(rotate:HI (match_operand:HI 1 "arith_reg_operand")
4494		   (match_operand:HI 2 "const_int_operand")))]
4495  "TARGET_SH1"
4496{
4497  if (INTVAL (operands[2]) != 8)
4498    FAIL;
4499})
4500
4501;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
4502;; They can also be used to implement things like
4503;;	bool t = a == b;
4504;;	int x0 = (y >> 1) | (t << 31);	// rotcr
4505;;	int x1 = (y << 1) | t;		// rotcl
4506(define_insn "rotcr"
4507  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4508	(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4509			     (const_int 1))
4510		(ashift:SI (match_operand:SI 2 "t_reg_operand")
4511			   (const_int 31))))
4512   (set (reg:SI T_REG)
4513	(and:SI (match_dup 1) (const_int 1)))]
4514  "TARGET_SH1"
4515  "rotcr	%0"
4516  [(set_attr "type" "arith")])
4517
4518(define_insn "rotcl"
4519  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4520	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4521			   (const_int 1))
4522		(match_operand:SI 2 "t_reg_operand")))
4523   (set (reg:SI T_REG)
4524	(lshiftrt:SI (match_dup 1) (const_int 31)))]
4525  "TARGET_SH1"
4526  "rotcl	%0"
4527  [(set_attr "type" "arith")])
4528
4529;; Simplified rotcr version for combine, which allows arbitrary shift
4530;; amounts for the reg.  If the shift amount is '1' rotcr can be used
4531;; directly.  Otherwise we have to insert a shift in between.
4532(define_insn_and_split "*rotcr"
4533  [(set (match_operand:SI 0 "arith_reg_dest")
4534	(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_or_0_operand")
4535			     (match_operand:SI 2 "const_int_operand"))
4536		(ashift:SI (match_operand 3 "arith_reg_or_treg_set_expr")
4537			   (const_int 31))))
4538   (clobber (reg:SI T_REG))]
4539  "TARGET_SH1 && can_create_pseudo_p ()"
4540  "#"
4541  "&& 1"
4542  [(const_int 0)]
4543{
4544  rtx prev_set_t_insn = NULL_RTX;
4545
4546  if (!arith_reg_operand (operands[3], SImode))
4547    {
4548      sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn);
4549      if (!ti.was_treg_operand ())
4550	prev_set_t_insn = ti.first_insn ();
4551
4552      operands[3] = get_t_reg_rtx ();
4553
4554      if (TARGET_SH2A && ti.has_trailing_nott () && operands[1] == const0_rtx)
4555	{
4556	  /* Convert to a movrt, rotr sequence.  */
4557	  remove_insn (ti.trailing_nott ());
4558	  rtx tmp = gen_reg_rtx (SImode);
4559	  emit_insn (gen_movnegt (tmp, get_t_reg_rtx ()));
4560	  emit_insn (gen_rotrsi3_1 (operands[0], tmp));
4561	  DONE;
4562	}
4563    }
4564
4565  if (operands[1] == const0_rtx)
4566    {
4567      operands[1] = gen_reg_rtx (SImode);
4568      emit_insn (gen_movt (operands[1], get_t_reg_rtx ()));
4569    }
4570
4571  if (INTVAL (operands[2]) > 1)
4572    {
4573      const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4574      rtx tmp_t_reg = NULL_RTX;
4575
4576      /* If we're going to emit a shift sequence that clobbers the T_REG,
4577	 try to find the previous insn that sets the T_REG and emit the 
4578	 shift insn before that insn, to remove the T_REG dependency.
4579	 If the insn that sets the T_REG cannot be found, store the T_REG
4580	 in a temporary reg and restore it after the shift.  */
4581      if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4582	  && ! sh_dynamicalize_shift_p (shift_count))
4583	{
4584	  if (prev_set_t_insn == NULL)
4585	    prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4586
4587	  /* Skip the nott insn, which was probably inserted by the splitter
4588	     of *rotcr_neg_t.  Don't use one of the recog functions
4589	     here during insn splitting, since that causes problems in later
4590	     passes.  */
4591	  if (prev_set_t_insn != NULL_RTX)
4592	    {
4593	      rtx pat = PATTERN (prev_set_t_insn);
4594	      if (GET_CODE (pat) == SET
4595		  && t_reg_operand (XEXP (pat, 0), SImode)
4596		  && negt_reg_operand (XEXP (pat, 1), SImode))
4597	      prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4598	    }
4599
4600	  if (! (prev_set_t_insn != NULL_RTX
4601		 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4602		 && ! reg_referenced_p (get_t_reg_rtx (),
4603					PATTERN (prev_set_t_insn))))
4604	    {
4605	      prev_set_t_insn = NULL_RTX;
4606	      tmp_t_reg = gen_reg_rtx (SImode);
4607	      emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4608	    } 
4609	}
4610
4611      rtx shift_result = gen_reg_rtx (SImode);
4612      rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4613      operands[1] = shift_result;
4614
4615      /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4616      if (prev_set_t_insn != NULL_RTX)
4617	emit_insn_before (shift_insn, prev_set_t_insn);
4618      else
4619	emit_insn (shift_insn);
4620
4621      /* Restore T_REG if it has been saved before.  */
4622      if (tmp_t_reg != NULL_RTX)
4623	emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4624    }
4625
4626  /* For the rotcr insn to work, operands[3] must be in T_REG.
4627     If it is not we can get it there by shifting it right one bit.
4628     In this case T_REG is not an input for this insn, thus we don't have to
4629     pay attention as of where to insert the shlr insn.  */
4630  if (! t_reg_operand (operands[3], SImode))
4631    {
4632      /* We don't care about the shifted result here, only the T_REG.  */
4633      emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4634      operands[3] = get_t_reg_rtx ();
4635    }
4636
4637  emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4638  DONE;
4639})
4640
4641;; If combine tries the same as above but with swapped operands, split
4642;; it so that it will try the pattern above.
4643(define_split
4644  [(set (match_operand:SI 0 "arith_reg_dest")
4645	(ior:SI (ashift:SI (match_operand 1 "arith_reg_or_treg_set_expr")
4646			   (const_int 31))
4647		(lshiftrt:SI (match_operand:SI 2 "arith_reg_or_0_operand")
4648			     (match_operand:SI 3 "const_int_operand"))))]
4649  "TARGET_SH1 && can_create_pseudo_p ()"
4650  [(parallel [(set (match_dup 0)
4651		   (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4652			   (ashift:SI (match_dup 1) (const_int 31))))
4653	      (clobber (reg:SI T_REG))])])
4654
4655;; Basically the same as the rotcr pattern above, but for rotcl.
4656;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4657(define_insn_and_split "*rotcl"
4658  [(set (match_operand:SI 0 "arith_reg_dest")
4659	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4660			   (match_operand:SI 2 "const_int_operand"))
4661		(and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4662			(const_int 1))))
4663   (clobber (reg:SI T_REG))]
4664  "TARGET_SH1"
4665  "#"
4666  "&& can_create_pseudo_p ()"
4667  [(const_int 0)]
4668{
4669  gcc_assert (INTVAL (operands[2]) > 0);
4670
4671  if (INTVAL (operands[2]) > 1)
4672    {
4673      const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4674      rtx prev_set_t_insn = NULL_RTX;
4675      rtx tmp_t_reg = NULL_RTX;
4676
4677      /* If we're going to emit a shift sequence that clobbers the T_REG,
4678	 try to find the previous insn that sets the T_REG and emit the 
4679	 shift insn before that insn, to remove the T_REG dependency.
4680	 If the insn that sets the T_REG cannot be found, store the T_REG
4681	 in a temporary reg and restore it after the shift.  */
4682      if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4683	  && ! sh_dynamicalize_shift_p (shift_count))
4684	{
4685	  prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4686
4687	  /* Skip the nott insn, which was probably inserted by the splitter
4688	     of *rotcl_neg_t.  Don't use one of the recog functions
4689	     here during insn splitting, since that causes problems in later
4690	     passes.  */
4691	  if (prev_set_t_insn != NULL_RTX)
4692	    {
4693	      rtx pat = PATTERN (prev_set_t_insn);
4694	      if (GET_CODE (pat) == SET
4695		  && t_reg_operand (XEXP (pat, 0), SImode)
4696		  && negt_reg_operand (XEXP (pat, 1), SImode))
4697	      prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4698	    }
4699
4700	  if (! (prev_set_t_insn != NULL_RTX
4701		 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4702		 && ! reg_referenced_p (get_t_reg_rtx (),
4703					PATTERN (prev_set_t_insn))))
4704	    {
4705	      prev_set_t_insn = NULL_RTX;
4706	      tmp_t_reg = gen_reg_rtx (SImode);
4707	      emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4708	    } 
4709	}
4710
4711      rtx shift_result = gen_reg_rtx (SImode);
4712      rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4713      operands[1] = shift_result;
4714
4715      /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4716      if (prev_set_t_insn != NULL_RTX)
4717	emit_insn_before (shift_insn, prev_set_t_insn);
4718      else
4719	emit_insn (shift_insn);
4720
4721      /* Restore T_REG if it has been saved before.  */
4722      if (tmp_t_reg != NULL_RTX)
4723	emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4724    }
4725
4726  /* For the rotcl insn to work, operands[3] must be in T_REG.
4727     If it is not we can get it there by shifting it right one bit.
4728     In this case T_REG is not an input for this insn, thus we don't have to
4729     pay attention as of where to insert the shlr insn.  */
4730  if (! t_reg_operand (operands[3], SImode))
4731    {
4732      /* We don't care about the shifted result here, only the T_REG.  */
4733      emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4734      operands[3] = get_t_reg_rtx ();
4735    }
4736
4737  emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4738  DONE;
4739})
4740
4741;; rotcl combine pattern variations
4742(define_insn_and_split "*rotcl"
4743  [(set (match_operand:SI 0 "arith_reg_dest")
4744	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4745			   (match_operand:SI 2 "const_int_operand"))
4746		(match_operand 3 "treg_set_expr")))
4747   (clobber (reg:SI T_REG))]
4748  "TARGET_SH1"
4749  "#"
4750  "&& can_create_pseudo_p ()"
4751  [(parallel [(set (match_dup 0)
4752		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4753			   (and:SI (match_dup 3) (const_int 1))))
4754	      (clobber (reg:SI T_REG))])]
4755{
4756  sh_split_treg_set_expr (operands[3], curr_insn);
4757  operands[3] = get_t_reg_rtx ();
4758})
4759
4760(define_insn_and_split "*rotcl"
4761  [(set (match_operand:SI 0 "arith_reg_dest")
4762	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4763			(const_int 1))
4764		(ashift:SI (match_operand:SI 2 "arith_reg_operand")
4765			   (match_operand:SI 3 "const_int_operand"))))
4766   (clobber (reg:SI T_REG))]
4767  "TARGET_SH1"
4768  "#"
4769  "&& can_create_pseudo_p ()"
4770  [(parallel [(set (match_dup 0)
4771		   (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4772			   (and:SI (match_dup 1) (const_int 1))))
4773	      (clobber (reg:SI T_REG))])])
4774
4775(define_insn_and_split "*rotcl"
4776  [(set (match_operand:SI 0 "arith_reg_dest")
4777	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4778			   (match_operand:SI 2 "const_int_operand"))
4779		(lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4780			     (const_int 31))))
4781   (clobber (reg:SI T_REG))]
4782  "TARGET_SH1"
4783  "#"
4784  "&& can_create_pseudo_p ()"
4785  [(parallel [(set (match_dup 0)
4786		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4787			   (and:SI (reg:SI T_REG) (const_int 1))))
4788	      (clobber (reg:SI T_REG))])]
4789{
4790  /* We don't care about the result of the left shift, only the T_REG.  */
4791  emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4792})
4793
4794(define_insn_and_split "*rotcl"
4795  [(set (match_operand:SI 0 "arith_reg_dest")
4796	(ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4797			     (const_int 31))
4798		(ashift:SI (match_operand:SI 1 "arith_reg_operand")
4799			   (match_operand:SI 2 "const_int_operand"))))
4800   (clobber (reg:SI T_REG))]
4801  "TARGET_SH1"
4802  "#"
4803  "&& can_create_pseudo_p ()"
4804  [(parallel [(set (match_dup 0)
4805		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4806			   (and:SI (reg:SI T_REG) (const_int 1))))
4807	      (clobber (reg:SI T_REG))])]
4808{
4809  /* We don't care about the result of the left shift, only the T_REG.  */
4810  emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4811})
4812
4813(define_insn_and_split "*rotcl"
4814  [(set (match_operand:SI 0 "arith_reg_dest")
4815	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4816			   (match_operand 2 "const_int_operand"))
4817		(zero_extract:SI (match_operand:SI 3 "arith_reg_operand")
4818				 (const_int 1)
4819				 (match_operand 4 "const_int_operand"))))
4820   (clobber (reg:SI T_REG))]
4821  "TARGET_SH1"
4822  "#"
4823  "&& can_create_pseudo_p ()"
4824  [(parallel [(set (match_dup 0)
4825		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4826			   (and:SI (match_dup 5) (const_int 1))))
4827	      (clobber (reg:SI T_REG))])]
4828{
4829  if (TARGET_SH2A && satisfies_constraint_K03 (operands[4]))
4830    {
4831      /* On SH2A we can use the bld insn to zero extract a single bit
4832	 into the T bit.  */
4833      operands[5] = get_t_reg_rtx ();
4834      emit_insn (gen_bldsi_reg (operands[3], operands[4]));
4835    }
4836  else
4837    {
4838      /* If we can't use the bld insn we have to emit a tst + nott sequence
4839	 to get the extracted bit into the T bit.
4840	 This will probably be worse than pre-shifting the operand.  */
4841      operands[5] = gen_reg_rtx (SImode);
4842      emit_insn (gen_lshrsi3 (operands[5], operands[3], operands[4]));
4843    }
4844})
4845
4846;; rotcr combine bridge pattern which will make combine try out more
4847;; complex patterns.
4848(define_insn_and_split "*rotcr"
4849  [(set (match_operand:SI 0 "arith_reg_dest")
4850	(ashift:SI (match_operand 1 "treg_set_expr") (const_int 31)))]
4851  "TARGET_SH1 && can_create_pseudo_p ()"
4852  "#"
4853  "&& 1"
4854  [(parallel [(set (match_dup 0)
4855		   (ior:SI (lshiftrt:SI (const_int 0) (const_int 1))
4856			   (ashift:SI (match_dup 1) (const_int 31))))
4857	      (clobber (reg:SI T_REG))])])
4858
4859(define_insn_and_split "*rotcr"
4860  [(set (match_operand:SI 0 "arith_reg_dest")
4861	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4862			(const_int -2147483648)) ;; 0xffffffff80000000
4863		(lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4864			     (const_int 1))))
4865   (clobber (reg:SI T_REG))]
4866  "TARGET_SH1"
4867  "#"
4868  "&& can_create_pseudo_p ()"
4869  [(const_int 0)]
4870{
4871  rtx tmp = gen_reg_rtx (SImode);
4872  emit_insn (gen_shll (tmp, operands[1]));
4873  emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4874  DONE;
4875})
4876
4877;; rotcr combine patterns for rotating in the negated T_REG value.
4878(define_insn_and_split "*rotcr_neg_t"
4879  [(set (match_operand:SI 0 "arith_reg_dest")
4880	(ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4881		(lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4882			     (match_operand:SI 3 "const_int_operand"))))
4883   (clobber (reg:SI T_REG))]
4884  "TARGET_SH1"
4885  "#"
4886  "&& can_create_pseudo_p ()"
4887  [(parallel [(set (match_dup 0)
4888		   (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4889			   (ashift:SI (reg:SI T_REG) (const_int 31))))
4890	      (clobber (reg:SI T_REG))])]
4891{
4892  emit_insn (gen_nott (get_t_reg_rtx ()));
4893})
4894
4895(define_insn_and_split "*rotcr_neg_t"
4896  [(set (match_operand:SI 0 "arith_reg_dest")
4897	(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4898			     (match_operand:SI 2 "const_int_operand"))
4899		(match_operand:SI 3 "negt_reg_shl31_operand")))
4900   (clobber (reg:SI T_REG))]
4901  "TARGET_SH1"
4902  "#"
4903  "&& can_create_pseudo_p ()"
4904  [(parallel [(set (match_dup 0)
4905		   (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4906			   (ashift:SI (reg:SI T_REG) (const_int 31))))
4907	      (clobber (reg:SI T_REG))])]
4908{
4909  emit_insn (gen_nott (get_t_reg_rtx ()));
4910})
4911
4912;; rotcl combine patterns for rotating in the negated T_REG value.
4913;; For some strange reason these have to be specified as splits which combine
4914;; will pick up.  If they are specified as insn_and_split like the
4915;; *rotcr_neg_t patterns above, combine would recognize them successfully
4916;; but not emit them on non-SH2A targets.
4917(define_split
4918  [(set (match_operand:SI 0 "arith_reg_dest")
4919	(ior:SI (match_operand:SI 1 "negt_reg_operand")
4920		(ashift:SI (match_operand:SI 2 "arith_reg_operand")
4921			   (match_operand:SI 3 "const_int_operand"))))]
4922  "TARGET_SH1"
4923  [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4924   (parallel [(set (match_dup 0)
4925		   (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4926			   (and:SI (reg:SI T_REG) (const_int 1))))
4927	      (clobber (reg:SI T_REG))])])
4928
4929(define_split
4930  [(set (match_operand:SI 0 "arith_reg_dest")
4931	(ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4932			   (match_operand:SI 3 "const_int_operand"))
4933		(match_operand:SI 1 "negt_reg_operand")))]
4934  "TARGET_SH1"
4935  [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4936   (parallel [(set (match_dup 0)
4937		   (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4938			   (and:SI (reg:SI T_REG) (const_int 1))))
4939	      (clobber (reg:SI T_REG))])])
4940
4941;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4942;; SImode shift left
4943
4944(define_expand "ashlsi3"
4945  [(set (match_operand:SI 0 "arith_reg_operand" "")
4946	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4947		   (match_operand:SI 2 "shift_count_operand" "")))]
4948  ""
4949{
4950  if (TARGET_SHMEDIA)
4951    {
4952       if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4953	{
4954	  operands[2] = GEN_INT (-INTVAL (operands[2]));
4955	  emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4956	  DONE;
4957	}
4958      emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4959      DONE;
4960    }
4961  if (TARGET_DYNSHIFT
4962      && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4963      operands[2] = force_reg (SImode, operands[2]);
4964
4965  /*  If the ashlsi3_* insn is going to clobber the T_REG it must be
4966      expanded here.  */
4967  if (CONST_INT_P (operands[2])
4968      && sh_ashlsi_clobbers_t_reg_p (operands[2])
4969      && ! sh_dynamicalize_shift_p (operands[2]))
4970    {
4971      emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4972					   operands[2]));
4973      DONE;
4974    }
4975
4976  /* Expand a library call for the dynamic shift.  */
4977  if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4978    {
4979      emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4980      rtx funcaddr = gen_reg_rtx (Pmode);
4981      function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4982      emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4983
4984      DONE;
4985    }
4986})
4987
4988(define_insn "ashlsi3_k"
4989  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4990	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4991		   (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4992  "TARGET_SH1"
4993  "@
4994	add	%0,%0
4995	shll%O2	%0"
4996  [(set_attr "type" "arith")])
4997
4998(define_insn_and_split "ashlsi3_d"
4999  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5000	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5001		   (match_operand:SI 2 "shift_count_operand" "r")))]
5002  "TARGET_DYNSHIFT"
5003  "shld	%2,%0"
5004  "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
5005   && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
5006  [(const_int 0)]
5007{
5008  if (satisfies_constraint_P27 (operands[2]))
5009    {
5010      emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
5011      DONE;
5012    }
5013  else if (! satisfies_constraint_P27 (operands[2]))
5014    {
5015      /* This must happen before reload, otherwise the constant will be moved
5016	 into a register due to the "r" constraint, after which this split
5017	 cannot be done anymore.
5018	 Unfortunately the move insn will not always be eliminated.
5019	 Also, here we must not create a shift sequence that clobbers the
5020	 T_REG.  */
5021      emit_move_insn (operands[0], operands[1]);
5022      gen_shifty_op (ASHIFT, operands);
5023      DONE;
5024    }
5025
5026  FAIL;
5027}
5028  [(set_attr "type" "dyn_shift")])
5029
5030;; If dynamic shifts are not available use a library function.
5031;; By specifying the pattern we reduce the number of call clobbered regs.
5032;; In order to make combine understand the truncation of the shift amount
5033;; operand we have to allow it to use pseudo regs for the shift operands.
5034(define_insn "ashlsi3_d_call"
5035  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
5036	(ashift:SI (reg:SI R4_REG)
5037		   (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
5038			   (const_int 31))))
5039   (use (match_operand:SI 2 "arith_reg_operand" "r"))
5040   (clobber (reg:SI T_REG))
5041   (clobber (reg:SI PR_REG))]
5042  "TARGET_SH1 && !TARGET_DYNSHIFT"
5043  "jsr	@%2%#"
5044  [(set_attr "type" "sfunc")
5045   (set_attr "needs_delay_slot" "yes")])
5046
5047(define_insn_and_split "ashlsi3_n"
5048  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5049	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5050		   (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
5051  "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
5052  "#"
5053  "&& (reload_completed
5054       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5055  [(const_int 0)]
5056{
5057  if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5058    {
5059      /* If this pattern was picked and dynamic shifts are supported, switch
5060	 to dynamic shift pattern before reload.  */
5061      operands[2] = force_reg (SImode, operands[2]);
5062      emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
5063    }
5064  else
5065    gen_shifty_op (ASHIFT, operands);
5066
5067  DONE;
5068})
5069
5070(define_insn_and_split "ashlsi3_n_clobbers_t"
5071  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5072	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5073		   (match_operand:SI 2 "not_p27_shift_count_operand" "")))
5074   (clobber (reg:SI T_REG))]
5075  "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
5076  "#"
5077  "&& (reload_completed || INTVAL (operands[2]) == 31
5078       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5079  [(const_int 0)]
5080{
5081  if (INTVAL (operands[2]) == 31)
5082    {
5083      /* If the shift amount is 31 we split into a different sequence before
5084	 reload so that it gets a chance to allocate R0 for the sequence.
5085	 If it fails to do so (due to pressure on R0), it will take one insn
5086	 more for the and.  */
5087      emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
5088      emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
5089    }
5090  else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5091    {
5092      /* If this pattern was picked and dynamic shifts are supported, switch
5093	 to dynamic shift pattern before reload.  */
5094      operands[2] = force_reg (SImode, operands[2]);
5095      emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
5096    }
5097  else
5098    gen_shifty_op (ASHIFT, operands);
5099
5100  DONE;
5101})
5102
5103(define_insn "shll"
5104  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5105	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
5106   (set (reg:SI T_REG)
5107	(lt:SI (match_dup 1) (const_int 0)))]
5108  "TARGET_SH1"
5109  "shll	%0"
5110  [(set_attr "type" "arith")])
5111
5112(define_insn "*ashlsi_c_void"
5113  [(set (reg:SI T_REG)
5114	(lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
5115   (clobber (match_scratch:SI 1 "=0"))]
5116  "TARGET_SH1 && cse_not_expected"
5117  "shll	%0"
5118  [(set_attr "type" "arith")])
5119
5120(define_peephole2
5121  [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
5122   (set (reg:SI T_REG)
5123	(gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
5124  "TARGET_SH1
5125   && peep2_reg_dead_p (2, operands[0])
5126   && peep2_reg_dead_p (2, operands[1])"
5127  [(const_int 0)]
5128{
5129  emit_insn (gen_shll (operands[1], operands[1]));
5130  DONE;
5131})
5132
5133(define_insn "ashlsi3_media"
5134  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5135	(ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5136		   (match_operand:SI 2 "shift_count_operand" "r,n")))]
5137  "TARGET_SHMEDIA"
5138  "@
5139	shlld.l	%1, %2, %0
5140	shlli.l	%1, %2, %0"
5141  [(set_attr "type" "arith_media")
5142   (set_attr "highpart" "ignore")])
5143
5144;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5145;; HImode shift left
5146
5147(define_expand "ashlhi3"
5148  [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
5149		   (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
5150			      (match_operand:SI 2 "nonmemory_operand" "")))
5151	      (clobber (reg:SI T_REG))])]
5152  "TARGET_SH1"
5153{
5154  if (!CONST_INT_P (operands[2]))
5155    FAIL;
5156  /* It may be possible to call gen_ashlhi3 directly with more generic
5157     operands.  Make sure operands[1] is a HImode register here.  */
5158  if (!arith_reg_operand (operands[1], HImode))
5159    operands[1] = copy_to_mode_reg (HImode, operands[1]);
5160})
5161
5162(define_insn "ashlhi3_k"
5163  [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
5164	(ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
5165		   (match_operand:HI 2 "const_int_operand" "M,P27")))]
5166  "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
5167  "@
5168	add	%0,%0
5169	shll%O2	%0"
5170  [(set_attr "type" "arith")])
5171
5172(define_insn_and_split "*ashlhi3_n"
5173  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
5174	(ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
5175		   (match_operand:HI 2 "const_int_operand" "n")))
5176   (clobber (reg:SI T_REG))]
5177  "TARGET_SH1"
5178  "#"
5179  "&& reload_completed"
5180  [(use (reg:SI R0_REG))]
5181{
5182  gen_shifty_hi_op (ASHIFT, operands);
5183  DONE;
5184})
5185
5186;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5187;; DImode shift left
5188
5189(define_expand "ashldi3"
5190  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5191		   (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
5192			      (match_operand:DI 2 "immediate_operand" "")))
5193	      (clobber (reg:SI T_REG))])]
5194  ""
5195{
5196  if (TARGET_SHMEDIA)
5197    {
5198       if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5199	{
5200	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5201	  emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
5202	  DONE;
5203	}
5204      emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5205      DONE;
5206    }
5207  if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
5208    {
5209      emit_insn (gen_ashldi3_k (operands[0], operands[1]));
5210      DONE;
5211    }
5212  else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
5213    {
5214      emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
5215      DONE;
5216    }
5217  else
5218    FAIL;
5219})
5220
5221;; Expander for DImode shift left with SImode operations.
5222(define_expand "ashldi3_std"
5223  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5224	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
5225                   (match_operand:DI 2 "const_int_operand" "n")))]
5226  "TARGET_SH1 && INTVAL (operands[2]) < 32"
5227{
5228  rtx low_src = gen_lowpart (SImode, operands[1]);
5229  rtx high_src = gen_highpart (SImode, operands[1]);
5230  rtx dst = gen_reg_rtx (DImode);
5231  rtx low_dst = gen_lowpart (SImode, dst);
5232  rtx high_dst = gen_highpart (SImode, dst);
5233  rtx tmp0 = gen_reg_rtx (SImode);
5234  rtx tmp1 = gen_reg_rtx (SImode);
5235
5236  emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
5237  emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));  
5238  emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));  
5239  emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
5240  emit_move_insn (operands[0], dst);
5241  DONE;
5242})
5243
5244(define_insn_and_split "ashldi3_k"
5245  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5246	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
5247		   (const_int 1)))
5248   (clobber (reg:SI T_REG))]
5249  "TARGET_SH1"
5250  "#"
5251  "&& reload_completed"
5252  [(const_int 0)]
5253{
5254  rtx high = gen_highpart (SImode, operands[0]);
5255  rtx low = gen_lowpart (SImode, operands[0]);
5256  emit_insn (gen_shll (low, low));
5257  emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
5258  DONE;
5259})
5260
5261(define_insn "ashldi3_media"
5262  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
5263	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5264		   (match_operand:DI 2 "shift_count_operand" "r,n")))]
5265  "TARGET_SHMEDIA"
5266  "@
5267	shlld	%1, %2, %0
5268	shlli	%1, %2, %0"
5269  [(set_attr "type" "arith_media")])
5270
5271(define_insn "*ashldisi3_media"
5272  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5273	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
5274		   (match_operand:DI 2 "const_int_operand" "n")))]
5275  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5276  "shlli.l	%1, %2, %0"
5277  [(set_attr "type" "arith_media")
5278   (set_attr "highpart" "ignore")])
5279
5280;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5281;; SImode arithmetic shift right
5282;;
5283;; We can't do HImode right shifts correctly unless we start out with an
5284;; explicit zero / sign extension; doing that would result in worse overall
5285;; code, so just let the machine independent code widen the mode.
5286;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
5287
5288(define_expand "ashrsi3"
5289  [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
5290		   (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
5291				(match_operand:SI 2 "nonmemory_operand" "")))
5292	      (clobber (reg:SI T_REG))])]
5293  ""
5294{
5295  if (TARGET_SHMEDIA)
5296    {
5297      if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5298	{
5299	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5300	  emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
5301	  DONE;
5302	}
5303      emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
5304      DONE;
5305    }
5306  if (expand_ashiftrt (operands))
5307    DONE;
5308  else
5309    FAIL;
5310})
5311
5312(define_insn "shar"
5313  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5314	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5315		     (const_int 1)))
5316   (set (reg:SI T_REG)
5317	(and:SI (match_dup 1) (const_int 1)))]
5318  "TARGET_SH1"
5319  "shar	%0"
5320  [(set_attr "type" "arith")])
5321
5322(define_insn "ashrsi3_k"
5323  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5324	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5325		     (match_operand:SI 2 "const_int_operand" "M")))
5326   (clobber (reg:SI T_REG))]
5327  "TARGET_SH1 && INTVAL (operands[2]) == 1"
5328  "shar	%0"
5329  [(set_attr "type" "arith")])
5330
5331(define_insn_and_split "ashrsi2_16"
5332  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5333        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
5334                     (const_int 16)))]
5335  "TARGET_SH1"
5336  "#"
5337  "&& 1"
5338  [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
5339   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
5340{
5341  operands[2] = gen_lowpart (HImode, operands[0]);
5342})
5343
5344(define_insn_and_split "ashrsi2_31"
5345  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5346	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5347		     (const_int 31)))
5348   (clobber (reg:SI T_REG))]
5349  "TARGET_SH1"
5350  "#"
5351  "&& 1"
5352  [(const_int 0)]
5353{
5354  emit_insn (gen_shll (operands[0], operands[1]));
5355  emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
5356  DONE;
5357})
5358
5359;; If the shift amount is changed by combine it will try to plug the
5360;; use on the symbol of the library function and the PR clobber.
5361(define_insn_and_split "*ashrsi2_31"
5362  [(set (match_operand:SI 0 "arith_reg_dest")
5363	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand")
5364		     (const_int 31)))
5365   (clobber (reg:SI T_REG))
5366   (clobber (reg:SI PR_REG))
5367   (use (match_operand:SI 2 "symbol_ref_operand"))]
5368  "TARGET_SH1"
5369  "#"
5370  "&& 1"
5371  [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))
5372	      (clobber (reg:SI T_REG))])])
5373
5374(define_insn "ashrsi3_d"
5375  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5376	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5377		     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
5378  "TARGET_DYNSHIFT"
5379  "shad	%2,%0"
5380  [(set_attr "type" "dyn_shift")])
5381
5382(define_insn "ashrsi3_n"
5383  [(set (reg:SI R4_REG)
5384	(ashiftrt:SI (reg:SI R4_REG)
5385		     (match_operand:SI 0 "const_int_operand" "i")))
5386   (clobber (reg:SI T_REG))
5387   (clobber (reg:SI PR_REG))
5388   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
5389  "TARGET_SH1"
5390  "jsr	@%1%#"
5391  [(set_attr "type" "sfunc")
5392   (set_attr "needs_delay_slot" "yes")])
5393
5394(define_insn "ashrsi3_media"
5395  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5396	(ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5397		     (match_operand:SI 2 "shift_count_operand" "r,n")))]
5398  "TARGET_SHMEDIA"
5399  "@
5400	shard.l	%1, %2, %0
5401	shari.l	%1, %2, %0"
5402  [(set_attr "type" "arith_media")
5403   (set_attr "highpart" "ignore")])
5404
5405;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5406;; DImode arithmetic shift right
5407
5408(define_expand "ashrdi3"
5409  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5410		   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5411				(match_operand:DI 2 "immediate_operand" "")))
5412	      (clobber (reg:SI T_REG))])]
5413  ""
5414{
5415  if (TARGET_SHMEDIA)
5416    {
5417      if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5418	{
5419	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5420	  emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5421	  DONE;
5422	}
5423      emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
5424      DONE;
5425    }
5426  if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5427    FAIL;
5428})
5429
5430(define_insn_and_split "ashrdi3_k"
5431  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5432	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5433		     (const_int 1)))
5434   (clobber (reg:SI T_REG))]
5435  "TARGET_SH1"
5436  "#"
5437  "&& reload_completed"
5438  [(const_int 0)]
5439{
5440  rtx high = gen_highpart (SImode, operands[0]);
5441  rtx low = gen_lowpart (SImode, operands[0]);
5442  emit_insn (gen_shar (high, high));
5443  emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5444  DONE;
5445})
5446
5447(define_insn "ashrdi3_media"
5448  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5449	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5450		     (match_operand:DI 2 "shift_count_operand" "r,n")))]
5451  "TARGET_SHMEDIA
5452   && (arith_reg_dest (operands[0], DImode)
5453       || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
5454  "@
5455	shard	%1, %2, %0
5456	shari	%1, %2, %0"
5457  [(set_attr "type" "arith_media")])
5458
5459(define_insn "*ashrdisi3_media"
5460  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5461	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5462		     (match_operand:DI 2 "const_int_operand" "n")))]
5463  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5464  "shari.l	%1, %2, %0"
5465  [(set_attr "type" "arith_media")
5466   (set_attr "highpart" "ignore")])
5467
5468(define_insn "ashrdisi3_media_high"
5469  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5470	(truncate:SI
5471	   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5472			(match_operand:DI 2 "const_int_operand" "n"))))]
5473  "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
5474  "shari	%1, %2, %0"
5475  [(set_attr "type" "arith_media")])
5476
5477(define_insn "ashrdisi3_media_opaque"
5478  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5479	(unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
5480		    (match_operand:DI 2 "const_int_operand" "n")]
5481	 UNSPEC_ASHIFTRT))]
5482  "TARGET_SHMEDIA"
5483  "shari	%1, %2, %0"
5484  [(set_attr "type" "arith_media")])
5485
5486;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5487;; SImode logical shift right
5488
5489(define_expand "lshrsi3"
5490  [(set (match_operand:SI 0 "arith_reg_dest" "")
5491	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
5492		     (match_operand:SI 2 "shift_count_operand" "")))]
5493  ""
5494{
5495  if (TARGET_SHMEDIA)
5496    {
5497      if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5498	{
5499	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5500	  emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
5501	  DONE;
5502	}
5503      emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
5504      DONE;
5505    }
5506
5507  /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
5508     here, otherwise the pattern will never match due to the shift amount reg
5509     negation.  */
5510  if (TARGET_DYNSHIFT
5511      && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
5512    {
5513      rtx neg_count = force_reg (SImode,
5514			         gen_int_mode (- INTVAL (operands[2]), SImode));
5515      emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5516      DONE;
5517    }
5518
5519  if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
5520    {
5521      rtx neg_count = gen_reg_rtx (SImode);
5522      emit_insn (gen_negsi2 (neg_count, operands[2]));
5523      emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5524      DONE;
5525    }
5526
5527  /* If the lshrsi3_* insn is going to clobber the T_REG it must be
5528     expanded here.  */
5529  if (CONST_INT_P (operands[2])
5530      && sh_lshrsi_clobbers_t_reg_p (operands[2])
5531      && ! sh_dynamicalize_shift_p (operands[2]))
5532    {
5533      emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
5534		 operands[2]));
5535      DONE;
5536    }
5537
5538  /* Expand a library call for the dynamic shift.  */
5539  if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
5540    {
5541      emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
5542      rtx funcaddr = gen_reg_rtx (Pmode);
5543      function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
5544      emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
5545      DONE;
5546    }
5547})
5548
5549(define_insn "lshrsi3_k"
5550  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5551	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5552		     (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
5553  "TARGET_SH1"
5554  "shlr%O2	%0"
5555  [(set_attr "type" "arith")])
5556
5557(define_insn_and_split "lshrsi3_d"
5558  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5559	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5560		     (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
5561  "TARGET_DYNSHIFT"
5562  "shld	%2,%0"
5563  "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
5564   && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5565  [(const_int 0)]
5566{
5567  if (satisfies_constraint_P27 (operands[2]))
5568    {
5569      /* This will not be done for a shift amount of 1, because it would
5570	 clobber the T_REG.  */
5571      emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
5572      DONE;
5573    }
5574  else if (! satisfies_constraint_P27 (operands[2]))
5575    {
5576      /* This must happen before reload, otherwise the constant will be moved
5577	 into a register due to the "r" constraint, after which this split
5578	 cannot be done anymore.
5579	 Unfortunately the move insn will not always be eliminated.
5580	 Also, here we must not create a shift sequence that clobbers the
5581	 T_REG.  */
5582      emit_move_insn (operands[0], operands[1]);
5583      gen_shifty_op (LSHIFTRT, operands);
5584      DONE;
5585    }
5586
5587  FAIL;
5588}
5589  [(set_attr "type" "dyn_shift")])
5590
5591;; If dynamic shifts are not available use a library function.
5592;; By specifying the pattern we reduce the number of call clobbered regs.
5593;; In order to make combine understand the truncation of the shift amount
5594;; operand we have to allow it to use pseudo regs for the shift operands.
5595(define_insn "lshrsi3_d_call"
5596  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
5597	(lshiftrt:SI (reg:SI R4_REG)
5598		     (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
5599			     (const_int 31))))
5600   (use (match_operand:SI 2 "arith_reg_operand" "r"))
5601   (clobber (reg:SI T_REG))
5602   (clobber (reg:SI PR_REG))]
5603  "TARGET_SH1 && !TARGET_DYNSHIFT"
5604  "jsr	@%2%#"
5605  [(set_attr "type" "sfunc")
5606   (set_attr "needs_delay_slot" "yes")])
5607
5608(define_insn_and_split "lshrsi3_n"
5609  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5610	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5611		     (match_operand:SI 2 "not_p27_rshift_count_operand")))]
5612  "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5613  "#"
5614  "&& (reload_completed
5615       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5616  [(const_int 0)]
5617{
5618  if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5619    {
5620      /* If this pattern was picked and dynamic shifts are supported, switch
5621	 to dynamic shift pattern before reload.  */
5622      operands[2] = force_reg (SImode,
5623			       gen_int_mode (- INTVAL (operands[2]), SImode));
5624      emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5625    }
5626  else
5627    gen_shifty_op (LSHIFTRT, operands);
5628
5629  DONE;
5630})
5631
5632;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5633;; the shlr pattern.
5634(define_insn_and_split "lshrsi3_n_clobbers_t"
5635  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5636	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5637		     (match_operand:SI 2 "not_p27_rshift_count_operand")))
5638   (clobber (reg:SI T_REG))]
5639  "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
5640  "#"
5641  "&& (reload_completed || INTVAL (operands[2]) == 31
5642       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5643  [(const_int 0)]
5644{
5645  if (INTVAL (operands[2]) == 31)
5646    {
5647      emit_insn (gen_shll (operands[0], operands[1]));
5648      emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5649    }
5650  else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5651    {
5652      /* If this pattern was picked and dynamic shifts are supported, switch
5653	 to dynamic shift pattern before reload.  */
5654      operands[2] = force_reg (SImode,
5655			       gen_int_mode (- INTVAL (operands[2]), SImode));
5656      emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5657    }
5658  else
5659    gen_shifty_op (LSHIFTRT, operands);
5660
5661  DONE;
5662})
5663
5664(define_insn "shlr"
5665  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5666	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5667		     (const_int 1)))
5668   (set (reg:SI T_REG)
5669	(and:SI (match_dup 1) (const_int 1)))]
5670  "TARGET_SH1"
5671  "shlr	%0"
5672  [(set_attr "type" "arith")])
5673
5674(define_insn "lshrsi3_media"
5675  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5676	(lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5677		     (match_operand:SI 2 "shift_count_operand" "r,n")))]
5678  "TARGET_SHMEDIA"
5679  "@
5680	shlrd.l	%1, %2, %0
5681	shlri.l	%1, %2, %0"
5682  [(set_attr "type" "arith_media")
5683   (set_attr "highpart" "ignore")])
5684
5685;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5686;; DImode logical shift right
5687
5688(define_expand "lshrdi3"
5689  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5690		   (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5691			       (match_operand:DI 2 "immediate_operand" "")))
5692	     (clobber (reg:SI T_REG))])]
5693  ""
5694{
5695  if (TARGET_SHMEDIA)
5696    {
5697      if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5698	{
5699	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5700	  emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5701	  DONE;
5702	}
5703      emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
5704      DONE;
5705    }
5706  if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5707    FAIL;
5708})
5709
5710(define_insn_and_split "lshrdi3_k"
5711  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5712	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5713		     (const_int 1)))
5714   (clobber (reg:SI T_REG))]
5715  "TARGET_SH1"
5716  "#"
5717  "&& reload_completed"
5718  [(const_int 0)]
5719{
5720  rtx high = gen_highpart (SImode, operands[0]);
5721  rtx low = gen_lowpart (SImode, operands[0]);
5722  emit_insn (gen_shlr (high, high));
5723  emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5724  DONE;
5725})
5726
5727(define_insn "lshrdi3_media"
5728  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5729	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5730		     (match_operand:DI 2 "shift_count_operand" "r,n")))]
5731  "TARGET_SHMEDIA
5732   && (arith_reg_dest (operands[0], DImode)
5733       || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
5734  "@
5735	shlrd	%1, %2, %0
5736	shlri	%1, %2, %0"
5737  [(set_attr "type" "arith_media")])
5738
5739(define_insn "*lshrdisi3_media"
5740  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5741	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5742		     (match_operand:DI 2 "const_int_operand" "n")))]
5743  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5744  "shlri.l	%1, %2, %0"
5745  [(set_attr "type" "arith_media")
5746   (set_attr "highpart" "ignore")])
5747
5748;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5749;; Combined left/right shifts
5750
5751(define_split
5752  [(set (match_operand:SI 0 "register_operand" "")
5753	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5754			   (match_operand:SI 2 "const_int_operand" ""))
5755		(match_operand:SI 3 "const_int_operand" "")))]
5756  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5757  [(use (reg:SI R0_REG))]
5758{
5759  if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5760    FAIL;
5761  DONE;
5762})
5763
5764(define_split
5765  [(set (match_operand:SI 0 "register_operand" "")
5766	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5767			   (match_operand:SI 2 "const_int_operand" ""))
5768		(match_operand:SI 3 "const_int_operand" "")))
5769   (clobber (reg:SI T_REG))]
5770  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5771  [(use (reg:SI R0_REG))]
5772{
5773  if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5774    FAIL;
5775  DONE;
5776})
5777
5778(define_insn ""
5779  [(set (match_operand:SI 0 "register_operand" "=r")
5780	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5781			   (match_operand:SI 2 "const_int_operand" "n"))
5782		(match_operand:SI 3 "const_int_operand" "n")))
5783   (clobber (reg:SI T_REG))]
5784  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
5785  "#"
5786  [(set (attr "length")
5787	(cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5788	       (const_string "4")
5789	       (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5790	       (const_string "6")
5791	       (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5792	       (const_string "8")
5793	       (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5794	       (const_string "10")
5795	       (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5796	       (const_string "12")
5797	       (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5798	       (const_string "14")
5799	       (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5800	       (const_string "16")]
5801	      (const_string "18")))
5802   (set_attr "type" "arith")])
5803
5804(define_insn ""
5805  [(set (match_operand:SI 0 "register_operand" "=z")
5806	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5807			   (match_operand:SI 2 "const_int_operand" "n"))
5808		(match_operand:SI 3 "const_int_operand" "n")))
5809   (clobber (reg:SI T_REG))]
5810  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
5811  "#"
5812  [(set (attr "length")
5813	(cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5814	       (const_string "4")
5815	       (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5816	       (const_string "6")
5817	       (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5818	       (const_string "8")]
5819	      (const_string "10")))
5820   (set_attr "type" "arith")])
5821
5822;; shift left / and combination with a scratch register: The combine pass
5823;; does not accept the individual instructions, even though they are
5824;; cheap.  But it needs a precise description so that it is usable after
5825;; reload.
5826(define_insn "and_shl_scratch"
5827  [(set (match_operand:SI 0 "register_operand" "=r,&r")
5828	(lshiftrt:SI
5829	 (ashift:SI
5830	  (and:SI
5831	   (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5832			(match_operand:SI 2 "const_int_operand" "N,n"))
5833	   (match_operand:SI 3 "" "0,r"))
5834	  (match_operand:SI 4 "const_int_operand" "n,n"))
5835	 (match_operand:SI 5 "const_int_operand" "n,n")))
5836   (clobber (reg:SI T_REG))]
5837  "TARGET_SH1"
5838  "#"
5839  [(set (attr "length")
5840	(cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5841	       (const_string "4")
5842	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5843	       (const_string "6")
5844	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5845	       (const_string "8")
5846	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5847	       (const_string "10")]
5848	      (const_string "12")))
5849   (set_attr "type" "arith")])
5850
5851(define_split
5852  [(set (match_operand:SI 0 "register_operand" "")
5853	(lshiftrt:SI
5854	 (ashift:SI
5855	  (and:SI
5856	   (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5857			(match_operand:SI 2 "const_int_operand" ""))
5858	   (match_operand:SI 3 "register_operand" ""))
5859	  (match_operand:SI 4 "const_int_operand" ""))
5860	 (match_operand:SI 5 "const_int_operand" "")))
5861   (clobber (reg:SI T_REG))]
5862  "TARGET_SH1"
5863  [(use (reg:SI R0_REG))]
5864{
5865  rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5866
5867  if (INTVAL (operands[2]))
5868    {
5869      gen_shifty_op (LSHIFTRT, operands);
5870    }
5871  emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5872  operands[2] = operands[4];
5873  gen_shifty_op (ASHIFT, operands);
5874  if (INTVAL (operands[5]))
5875    {
5876      operands[2] = operands[5];
5877      gen_shifty_op (LSHIFTRT, operands);
5878    }
5879  DONE;
5880})
5881
5882;; signed left/right shift combination.
5883(define_split
5884  [(set (match_operand:SI 0 "register_operand" "")
5885        (sign_extract:SI
5886	 (ashift:SI (match_operand:SI 1 "register_operand" "")
5887		    (match_operand:SI 2 "const_int_operand" ""))
5888	 (match_operand:SI 3 "const_int_operand" "")
5889	 (const_int 0)))
5890   (clobber (reg:SI T_REG))]
5891  "TARGET_SH1"
5892  [(use (reg:SI R0_REG))]
5893{
5894  if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5895    FAIL;
5896  DONE;
5897})
5898
5899(define_insn "shl_sext_ext"
5900  [(set (match_operand:SI 0 "register_operand" "=r")
5901        (sign_extract:SI
5902	 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5903		    (match_operand:SI 2 "const_int_operand" "n"))
5904	 (match_operand:SI 3 "const_int_operand" "n")
5905	 (const_int 0)))
5906   (clobber (reg:SI T_REG))]
5907  "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5908  "#"
5909  [(set (attr "length")
5910	(cond [(match_test "shl_sext_length (insn)")
5911	       (const_string "2")
5912	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5913	       (const_string "4")
5914	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5915	       (const_string "6")
5916	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5917	       (const_string "8")
5918	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5919	       (const_string "10")
5920	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5921	       (const_string "12")
5922	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5923	       (const_string "14")
5924	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5925	       (const_string "16")]
5926	      (const_string "18")))
5927    (set_attr "type" "arith")])
5928
5929(define_insn "shl_sext_sub"
5930  [(set (match_operand:SI 0 "register_operand" "=z")
5931        (sign_extract:SI
5932	 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5933		    (match_operand:SI 2 "const_int_operand" "n"))
5934	 (match_operand:SI 3 "const_int_operand" "n")
5935	 (const_int 0)))
5936   (clobber (reg:SI T_REG))]
5937  "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
5938  "#"
5939  [(set (attr "length")
5940	(cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5941	       (const_string "6")
5942	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5943	       (const_string "8")
5944	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5945	       (const_string "10")
5946	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5947	       (const_string "12")]
5948	      (const_string "14")))
5949    (set_attr "type" "arith")])
5950
5951;; The xtrct_left and xtrct_right patterns are used in expansions of DImode
5952;; shifts by 16, and allow the xtrct instruction to be generated from C
5953;; source.
5954(define_insn "xtrct_left"
5955  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5956        (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5957			   (const_int 16))
5958 	        (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5959			     (const_int 16))))]
5960  "TARGET_SH1"
5961  "xtrct	%1,%0"
5962  [(set_attr "type" "arith")])
5963
5964(define_insn "xtrct_right"
5965  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5966        (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5967			     (const_int 16))
5968 	        (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5969			   (const_int 16))))]
5970  "TARGET_SH1"
5971  "xtrct	%2,%0"
5972  [(set_attr "type" "arith")])
5973
5974;; -------------------------------------------------------------------------
5975;; Unary arithmetic
5976;; -------------------------------------------------------------------------
5977
5978(define_insn "negc"
5979  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5980	(neg:SI (plus:SI (reg:SI T_REG)
5981			 (match_operand:SI 1 "arith_reg_operand" "r"))))
5982   (set (reg:SI T_REG)
5983	(ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
5984	       (const_int 0)))]
5985  "TARGET_SH1"
5986  "negc	%1,%0"
5987  [(set_attr "type" "arith")])
5988
5989;; A simplified version of the negc insn, where the exact value of the
5990;; T bit doesn't matter.  This is easier for combine to pick up.
5991;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5992;; extra patterns for this case.
5993(define_insn_and_split "*negc"
5994  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5995	(minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5996		  (match_operand 2 "treg_set_expr")))
5997   (clobber (reg:SI T_REG))]
5998  "TARGET_SH1 && can_create_pseudo_p ()"
5999  "#"
6000  "&& 1"
6001  [(const_int 0)]
6002{
6003  sh_split_treg_set_expr (operands[2], curr_insn);
6004  emit_insn (gen_negc (operands[0], operands[1]));
6005  DONE;
6006});
6007
6008(define_insn "*negdi_media"
6009  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
6010	(neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
6011  "TARGET_SHMEDIA"
6012  "sub	r63, %1, %0"
6013  [(set_attr "type" "arith_media")])
6014
6015;; Don't split into individual negc insns immediately so that neg:DI (abs:DI)
6016;; can be combined.
6017(define_expand "negdi2"
6018  [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
6019		   (neg:DI (match_operand:DI 1 "arith_reg_operand")))
6020	      (clobber (reg:SI T_REG))])]
6021  "TARGET_SH1")
6022
6023(define_insn_and_split "*negdi2"
6024  [(set (match_operand:DI 0 "arith_reg_dest")
6025	(neg:DI (match_operand:DI 1 "arith_reg_operand")))
6026   (clobber (reg:SI T_REG))]
6027  "TARGET_SH1"
6028  "#"
6029  "&& can_create_pseudo_p ()"
6030  [(const_int 0)]
6031{
6032  emit_insn (gen_clrt ());
6033  emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
6034		       gen_lowpart (SImode, operands[1])));
6035  emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
6036		       gen_highpart (SImode, operands[1])));
6037  DONE;
6038})
6039
6040(define_insn "negsi2"
6041  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6042	(neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
6043  "TARGET_SH1"
6044  "neg	%1,%0"
6045  [(set_attr "type" "arith")])
6046
6047(define_insn_and_split "one_cmplsi2"
6048  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6049	(not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
6050  "TARGET_SH1"
6051  "not	%1,%0"
6052  "&& can_create_pseudo_p ()"
6053  [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
6054   (set (match_dup 0) (reg:SI T_REG))]
6055{
6056/* PR 54685
6057   If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
6058   sequence:
6059
6060     (set (reg0) (not:SI (reg0) (reg1)))
6061     (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
6062		(clobber (reg:SI T_REG))])
6063
6064   ... match and combine the sequence manually in the split pass after the
6065   combine pass.  Notice that combine does try the target pattern of this
6066   split, but if the pattern is added it interferes with other patterns, in
6067   particular with the div0s comparisons.
6068   This could also be done with a peephole but doing it here before register
6069   allocation can save one temporary.
6070   When we're here, the not:SI pattern obviously has been matched already
6071   and we only have to see whether the following insn is the left shift.  */
6072
6073  rtx i = next_nonnote_insn_bb (curr_insn);
6074  if (i == NULL_RTX || !NONJUMP_INSN_P (i))
6075    FAIL;
6076
6077  rtx p = PATTERN (i);
6078  if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
6079    FAIL;
6080
6081  rtx p0 = XVECEXP (p, 0, 0);
6082  rtx p1 = XVECEXP (p, 0, 1);
6083
6084  if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31)))  */
6085      GET_CODE (p0) == SET
6086      && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
6087      && REG_P (XEXP (XEXP (p0, 1), 0))
6088      && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
6089      && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
6090      && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
6091
6092      /* (clobber (reg:SI T_REG))  */
6093      && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
6094      && REGNO (XEXP (p1, 0)) == T_REG)
6095    {
6096      operands[0] = XEXP (p0, 0);
6097      set_insn_deleted (i);
6098    }
6099  else
6100    FAIL;
6101}
6102  [(set_attr "type" "arith")])
6103
6104(define_expand "one_cmpldi2"
6105  [(set (match_operand:DI 0 "arith_reg_dest" "")
6106	(xor:DI (match_operand:DI 1 "arith_reg_operand" "")
6107		(const_int -1)))]
6108  "TARGET_SHMEDIA" "")
6109
6110(define_expand "abs<mode>2"
6111  [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
6112		   (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
6113	      (clobber (reg:SI T_REG))])]
6114  "TARGET_SH1")
6115
6116(define_insn_and_split "*abs<mode>2"
6117  [(set (match_operand:SIDI 0 "arith_reg_dest")
6118  	(abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
6119   (clobber (reg:SI T_REG))]
6120  "TARGET_SH1"
6121  "#"
6122  "&& can_create_pseudo_p ()"
6123  [(const_int 0)]
6124{
6125  if (<MODE>mode == SImode)
6126    emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
6127  else
6128    {
6129      rtx high_src = gen_highpart (SImode, operands[1]);
6130      emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
6131    }
6132
6133  emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
6134				 const1_rtx));
6135  DONE;
6136})
6137
6138(define_insn_and_split "*negabs<mode>2"
6139  [(set (match_operand:SIDI 0 "arith_reg_dest")
6140	(neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
6141   (clobber (reg:SI T_REG))]
6142  "TARGET_SH1"
6143  "#"
6144  "&& can_create_pseudo_p ()"
6145  [(const_int 0)]
6146{
6147  if (<MODE>mode == SImode)
6148    emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
6149  else
6150    {
6151      rtx high_src = gen_highpart (SImode, operands[1]);
6152      emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
6153    }
6154
6155  emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
6156				 const0_rtx));
6157  DONE;
6158})
6159
6160;; The SH4 202 can do zero-offset branches without pipeline stalls.
6161;; This can be used as some kind of conditional execution, which is useful
6162;; for abs.
6163;; Actually the instruction scheduling should decide whether to use a
6164;; zero-offset branch or not for any generic case involving a single
6165;; instruction on SH4 202.
6166(define_insn_and_split "negsi_cond"
6167  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
6168	(if_then_else
6169	  (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
6170	  (match_operand:SI 1 "arith_reg_operand" "0,0")
6171	  (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
6172  "TARGET_SH1 && TARGET_ZDCBRANCH"
6173{
6174  static const char* alt[] =
6175  {
6176       "bt	0f"	"\n"
6177    "	neg	%2,%0"	"\n"
6178    "0:",
6179
6180       "bf	0f"	"\n"
6181    "	neg	%2,%0"	"\n"
6182    "0:"
6183  };
6184  return alt[which_alternative];
6185}
6186  "TARGET_SH1 && ! TARGET_ZDCBRANCH"
6187  [(const_int 0)]
6188{
6189  rtx skip_neg_label = gen_label_rtx ();
6190
6191  emit_move_insn (operands[0], operands[1]);
6192
6193  emit_jump_insn (INTVAL (operands[3])
6194		  ? gen_branch_true (skip_neg_label)
6195		  : gen_branch_false (skip_neg_label));
6196
6197  emit_label_after (skip_neg_label,
6198		    emit_insn (gen_negsi2 (operands[0], operands[1])));
6199  DONE;
6200}
6201  [(set_attr "type" "arith") ;; poor approximation
6202   (set_attr "length" "4")])
6203
6204(define_insn_and_split "negdi_cond"
6205  [(set (match_operand:DI 0 "arith_reg_dest")
6206	(if_then_else
6207	  (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
6208	  (match_operand:DI 1 "arith_reg_operand")
6209	  (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
6210   (clobber (reg:SI T_REG))]
6211  "TARGET_SH1"
6212  "#"
6213  "&& can_create_pseudo_p ()"
6214  [(const_int 0)]
6215{
6216  rtx skip_neg_label = gen_label_rtx ();
6217
6218  emit_move_insn (operands[0], operands[1]);
6219
6220  emit_jump_insn (INTVAL (operands[3]) 
6221		  ? gen_branch_true (skip_neg_label)
6222		  : gen_branch_false (skip_neg_label));
6223
6224  if (!INTVAL (operands[3]))
6225    emit_insn (gen_clrt ());
6226
6227  emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
6228		       gen_lowpart (SImode, operands[1])));
6229  emit_label_after (skip_neg_label,
6230		    emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
6231					 gen_highpart (SImode, operands[1]))));
6232  DONE;
6233})
6234
6235(define_expand "bswapsi2"
6236  [(set (match_operand:SI 0 "arith_reg_dest" "")
6237	(bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
6238  "TARGET_SH1"
6239{
6240  if (! can_create_pseudo_p ())
6241    FAIL;
6242  else
6243    {
6244      rtx tmp0 = gen_reg_rtx (SImode);
6245      rtx tmp1 = gen_reg_rtx (SImode);
6246
6247      emit_insn (gen_swapbsi2 (tmp0, operands[1]));
6248      emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
6249      emit_insn (gen_swapbsi2 (operands[0], tmp1));
6250      DONE;
6251    }
6252})
6253
6254(define_insn "swapbsi2"
6255  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6256	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
6257			(const_int -65536)) ;; 0xFFFF0000
6258		(ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
6259				(const_int 65280))
6260			(and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
6261				(const_int 255)))))]
6262  "TARGET_SH1"
6263  "swap.b	%1,%0"
6264  [(set_attr "type" "arith")])
6265
6266;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
6267;; partial byte swap expressions such as...
6268;;   ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
6269;; ...which are currently not handled by the tree optimizers.
6270;; The combine pass will not initially try to combine the full expression,
6271;; but only some sub-expressions.  In such a case the *swapbisi2_and_shl8
6272;; pattern acts as an intermediate pattern that will eventually lead combine
6273;; to the swapbsi2 pattern above.
6274;; As a side effect this also improves code that does (x & 0xFF) << 8
6275;; or (x << 8) & 0xFF00.
6276(define_insn_and_split "*swapbisi2_and_shl8"
6277  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6278	(ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
6279				   (const_int 8))
6280			(const_int 65280))
6281		(match_operand:SI 2 "arith_reg_operand" "r")))]
6282  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
6283  "#"
6284  "&& can_create_pseudo_p ()"
6285  [(const_int 0)]
6286{
6287  rtx tmp0 = gen_reg_rtx (SImode);
6288  rtx tmp1 = gen_reg_rtx (SImode);
6289
6290  emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
6291  emit_insn (gen_swapbsi2 (tmp1, tmp0));
6292  emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
6293  DONE;
6294})
6295
6296;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
6297;; intermediate pattern that will help the combine pass arriving at swapbsi2.
6298(define_insn_and_split "*swapbhisi2"
6299  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6300	(ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
6301				   (const_int 8))
6302			(const_int 65280))
6303		(zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
6304  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
6305  "#"
6306  "&& can_create_pseudo_p ()"
6307  [(const_int 0)]
6308{
6309  rtx tmp = gen_reg_rtx (SImode);
6310
6311  emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
6312  emit_insn (gen_swapbsi2 (operands[0], tmp));
6313  DONE;
6314})
6315
6316;; In some cases the swapbsi2 pattern might leave a sequence such as...
6317;;   swap.b  r4,r4
6318;;   mov     r4,r0
6319;;
6320;; which can be simplified to...
6321;;   swap.b  r4,r0
6322(define_peephole2
6323  [(set (match_operand:SI 0 "arith_reg_dest" "")
6324	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
6325			(const_int -65536)) ;; 0xFFFF0000
6326		(ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
6327				(const_int 65280))
6328			(and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
6329				(const_int 255)))))
6330   (set (match_operand:SI 2 "arith_reg_dest" "")
6331	(match_dup 0))]
6332  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
6333  [(set (match_dup 2)
6334	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
6335			(const_int -65536)) ;; 0xFFFF0000
6336		(ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
6337				(const_int 65280))
6338			(and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
6339				(const_int 255)))))])
6340
6341;; -------------------------------------------------------------------------
6342;; Zero extension instructions
6343;; -------------------------------------------------------------------------
6344
6345(define_insn "zero_extendsidi2"
6346  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
6347	(zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
6348  "TARGET_SHMEDIA"
6349  "addz.l	%1, r63, %0"
6350  [(set_attr "type" "arith_media")
6351   (set_attr "highpart" "extend")])
6352
6353(define_insn "zero_extendhidi2"
6354  [(set (match_operand:DI 0 "register_operand" "=r,r")
6355	(zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6356  "TARGET_SHMEDIA"
6357  "@
6358	#
6359	ld%M1.uw	%m1, %0"
6360  [(set_attr "type" "*,load_media")
6361   (set (attr "highpart")
6362	(cond [(match_test "sh_contains_memref_p (insn)")
6363	       (const_string "user")]
6364	      (const_string "ignore")))])
6365
6366(define_split
6367  [(set (match_operand:DI 0 "register_operand" "")
6368	(zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6369  "TARGET_SHMEDIA && reload_completed"
6370  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6371   (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
6372{
6373  if (GET_CODE (operands[1]) == TRUNCATE)
6374    operands[1] = XEXP (operands[1], 0);
6375})
6376
6377;; ??? when a truncated input to a zero_extend is reloaded, reload will
6378;; reload the entire truncate expression.
6379(define_insn_and_split "*loaddi_trunc"
6380  [(set (match_operand 0 "any_register_operand" "=r")
6381	(truncate (match_operand:DI 1 "memory_operand" "m")))]
6382  "TARGET_SHMEDIA && reload_completed"
6383  "#"
6384  "TARGET_SHMEDIA && reload_completed"
6385  [(set (match_dup 0) (match_dup 1))]
6386{
6387  operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6388})
6389
6390(define_insn "zero_extendqidi2"
6391  [(set (match_operand:DI 0 "register_operand" "=r,r")
6392	(zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6393  "TARGET_SHMEDIA"
6394  "@
6395	andi	%1, 255, %0
6396	ld%M1.ub	%m1, %0"
6397  [(set_attr "type" "arith_media,load_media")
6398   (set (attr "highpart")
6399	(cond [(match_test "sh_contains_memref_p (insn)")
6400	       (const_string "user")]
6401	      (const_string "ignore")))])
6402
6403(define_expand "zero_extend<mode>si2"
6404  [(set (match_operand:SI 0 "arith_reg_dest")
6405	(zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
6406
6407(define_insn_and_split "*zero_extend<mode>si2_compact"
6408  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6409	(zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6410  "TARGET_SH1"
6411  "extu.<bw>	%1,%0"
6412  "&& can_create_pseudo_p ()"
6413  [(set (match_dup 0) (match_dup 2))]
6414{
6415  /* Sometimes combine fails to combine a T bit or negated T bit store to a
6416     reg with a following zero extension.  In the split pass after combine,
6417     try to figure out how the extended reg was set.  If it originated from
6418     the T bit we can replace the zero extension with a reg move, which will
6419     be eliminated.  Notice that this also helps the *cbranch_t splitter when
6420     it tries to post-combine tests and conditional branches, as it does not
6421     check for zero extensions.  */
6422  operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6423  if (operands[2] == NULL_RTX)
6424    FAIL;
6425}
6426  [(set_attr "type" "arith")])
6427
6428(define_insn "*zero_extendhisi2_media"
6429  [(set (match_operand:SI 0 "register_operand" "=r,r")
6430	(zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6431  "TARGET_SHMEDIA"
6432  "@
6433	#
6434	ld%M1.uw	%m1, %0"
6435  [(set_attr "type" "arith_media,load_media")
6436   (set (attr "highpart")
6437	(cond [(match_test "sh_contains_memref_p (insn)")
6438	       (const_string "user")]
6439	      (const_string "ignore")))])
6440
6441(define_split
6442  [(set (match_operand:SI 0 "register_operand" "")
6443	(zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6444  "TARGET_SHMEDIA && reload_completed"
6445  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6446   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
6447{
6448  rtx op1 = operands[1];
6449
6450  if (GET_CODE (op1) == TRUNCATE)
6451    op1 = XEXP (op1, 0);
6452  operands[2]
6453    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6454			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
6455})
6456
6457(define_insn "*zero_extendqisi2_media"
6458  [(set (match_operand:SI 0 "register_operand" "=r,r")
6459	(zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6460  "TARGET_SHMEDIA"
6461  "@
6462	andi	%1, 255, %0
6463	ld%M1.ub	%m1, %0"
6464  [(set_attr "type" "arith_media,load_media")
6465   (set (attr "highpart")
6466	(cond [(match_test "sh_contains_memref_p (insn)")
6467	       (const_string "user")]
6468	      (const_string "ignore")))])
6469
6470(define_insn "zero_extendqihi2"
6471  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6472	(zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6473  "TARGET_SH1"
6474  "extu.b	%1,%0"
6475  [(set_attr "type" "arith")])
6476
6477;; SH2A supports two zero extending load instructions: movu.b and movu.w.
6478;; They could also be used for simple memory addresses like @Rn by setting
6479;; the displacement value to zero.  However, doing so too early results in
6480;; missed opportunities for other optimizations such as post-inc or index
6481;; addressing loads.
6482;; We don't allow the zero extending loads to match during RTL expansion
6483;; (see zero_extend_operand predicate), as this would pessimize other
6484;; optimization opportunities such as bit extractions of unsigned mems,
6485;; where the zero extraction is irrelevant.  If the zero extracting mem
6486;; loads are emitted early it will be more difficult to change them back
6487;; to sign extending loads (which are preferred).
6488;; The combine pass will also try to combine mem loads and zero extends,
6489;; which is prevented by 'sh_legitimate_combined_insn'.
6490(define_insn "*zero_extend<mode>si2_disp_mem"
6491  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
6492	(zero_extend:SI
6493	  (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
6494  "TARGET_SH2A"
6495  "@
6496	movu.<bw>	%1,%0
6497	movu.<bw>	@(0,%t1),%0"
6498  [(set_attr "type" "load")
6499   (set_attr "length" "4")])
6500
6501;; Convert the zero extending loads in sequences such as:
6502;;	movu.b	@(1,r5),r0	movu.w	@(2,r5),r0
6503;;	mov.b	r0,@(1,r4)	mov.b	r0,@(1,r4)
6504;;
6505;; back to sign extending loads like:
6506;;	mov.b	@(1,r5),r0	mov.w	@(2,r5),r0
6507;;	mov.b	r0,@(1,r4)	mov.b	r0,@(1,r4)
6508;;
6509;; if the extension type is irrelevant.  The sign extending mov.{b|w} insn
6510;; is only 2 bytes in size if the displacement is {K04|K05}.
6511;; If the displacement is greater it doesn't matter, so we convert anyways.
6512(define_peephole2
6513  [(set (match_operand:SI 0 "arith_reg_dest" "")
6514	(zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
6515   (set (match_operand 2 "nonimmediate_operand" "")
6516	(match_operand 3 "arith_reg_operand" ""))]
6517  "TARGET_SH2A
6518   && REGNO (operands[0]) == REGNO (operands[3])
6519   && peep2_reg_dead_p (2, operands[0])
6520   && GET_MODE_SIZE (GET_MODE (operands[2]))
6521      <= GET_MODE_SIZE (GET_MODE (operands[1]))"
6522  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
6523   (set (match_dup 2) (match_dup 3))])
6524
6525;; Fold sequences such as
6526;;	mov.b	@r3,r7
6527;;	extu.b	r7,r7
6528;; into
6529;;	movu.b	@(0,r3),r7
6530;; This does not reduce the code size but the number of instructions is
6531;; halved, which results in faster code.
6532(define_peephole2
6533  [(set (match_operand:SI 0 "arith_reg_dest" "")
6534	(sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
6535   (set (match_operand:SI 2 "arith_reg_dest" "")
6536	(zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
6537  "TARGET_SH2A
6538   && GET_MODE (operands[1]) == GET_MODE (operands[3])
6539   && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
6540   && REGNO (operands[0]) == REGNO (operands[3])
6541   && (REGNO (operands[2]) == REGNO (operands[0])
6542       || peep2_reg_dead_p (2, operands[0]))"
6543  [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
6544{
6545  operands[4]
6546    = replace_equiv_address (operands[1],
6547			     gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
6548					   const0_rtx));
6549})
6550
6551;; -------------------------------------------------------------------------
6552;; Sign extension instructions
6553;; -------------------------------------------------------------------------
6554
6555;; ??? This should be a define expand.
6556;; ??? Or perhaps it should be dropped?
6557
6558;; convert_move generates good code for SH[1-4].
6559(define_insn "extendsidi2"
6560  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6561	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
6562  "TARGET_SHMEDIA"
6563  "@
6564	add.l	%1, r63, %0
6565	ld%M1.l	%m1, %0
6566	fmov.sl	%1, %0"
6567  [(set_attr "type" "arith_media,load_media,fpconv_media")
6568   (set (attr "highpart")
6569	(cond [(match_test "sh_contains_memref_p (insn)")
6570	       (const_string "user")]
6571	      (const_string "extend")))])
6572
6573(define_insn "extendhidi2"
6574  [(set (match_operand:DI 0 "register_operand" "=r,r")
6575	(sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6576  "TARGET_SHMEDIA"
6577  "@
6578	#
6579	ld%M1.w	%m1, %0"
6580  [(set_attr "type" "*,load_media")
6581   (set (attr "highpart")
6582	(cond [(match_test "sh_contains_memref_p (insn)")
6583	       (const_string "user")]
6584	      (const_string "ignore")))])
6585
6586(define_split
6587  [(set (match_operand:DI 0 "register_operand" "")
6588	(sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6589  "TARGET_SHMEDIA && reload_completed"
6590  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6591   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
6592{
6593  if (GET_CODE (operands[1]) == TRUNCATE)
6594    operands[1] = XEXP (operands[1], 0);
6595})
6596
6597(define_insn "extendqidi2"
6598  [(set (match_operand:DI 0 "register_operand" "=r,r")
6599	(sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6600  "TARGET_SHMEDIA"
6601  "@
6602	#
6603	ld%M1.b	%m1, %0"
6604  [(set_attr "type" "*,load_media")
6605   (set (attr "highpart")
6606	(cond [(match_test "sh_contains_memref_p (insn)")
6607	       (const_string "user")]
6608	      (const_string "ignore")))])
6609
6610(define_split
6611  [(set (match_operand:DI 0 "register_operand" "")
6612	(sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
6613  "TARGET_SHMEDIA && reload_completed"
6614  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
6615   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
6616{
6617  if (GET_CODE (operands[1]) == TRUNCATE)
6618    operands[1] = XEXP (operands[1], 0);
6619})
6620
6621(define_expand "extend<mode>si2"
6622  [(set (match_operand:SI 0 "arith_reg_dest")
6623	(sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
6624
6625(define_insn "*extendhisi2_media"
6626  [(set (match_operand:SI 0 "register_operand" "=r,r")
6627	(sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6628  "TARGET_SHMEDIA"
6629  "@
6630	#
6631	ld%M1.w	%m1, %0"
6632  [(set_attr "type" "arith_media,load_media")
6633   (set (attr "highpart")
6634	(cond [(match_test "sh_contains_memref_p (insn)")
6635	       (const_string "user")]
6636	      (const_string "ignore")))])
6637
6638(define_split
6639  [(set (match_operand:SI 0 "register_operand" "")
6640	(sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6641  "TARGET_SHMEDIA && reload_completed"
6642  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6643   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
6644{
6645  rtx op1 = operands[1];
6646  if (GET_CODE (op1) == TRUNCATE)
6647    op1 = XEXP (op1, 0);
6648  operands[2]
6649    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6650			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
6651})
6652
6653(define_insn_and_split "*extend<mode>si2_compact_reg"
6654  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6655	(sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6656  "TARGET_SH1"
6657  "exts.<bw>	%1,%0"
6658  "&& can_create_pseudo_p ()"
6659  [(set (match_dup 0) (match_dup 2))]
6660{
6661  /* Sometimes combine fails to combine a T bit or negated T bit store to a
6662     reg with a following sign extension.  In the split pass after combine,
6663     try to figure the extended reg was set.  If it originated from the T
6664     bit we can replace the sign extension with a reg move, which will be
6665     eliminated.  */
6666  operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6667  if (operands[2] == NULL_RTX)
6668    FAIL;
6669}
6670  [(set_attr "type" "arith")])
6671
6672;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6673;; See movqi insns.
6674(define_insn "*extend<mode>si2_compact_mem_disp"
6675  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6676	(sign_extend:SI
6677	  (mem:QIHI
6678	    (plus:SI
6679	      (match_operand:SI 1 "arith_reg_operand" "%r,r")
6680	      (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
6681  "TARGET_SH1 && ! TARGET_SH2A
6682   && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6683  "@
6684	mov.<bw>	@(%O2,%1),%0
6685	mov.<bw>	@%1,%0"
6686  [(set_attr "type" "load")])
6687
6688(define_insn "*extend<mode>si2_compact_mem_disp"
6689  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6690	(sign_extend:SI
6691	  (mem:QIHI
6692	    (plus:SI
6693	      (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6694	      (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
6695  "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6696  "@
6697	mov.<bw>	@(%O2,%1),%0
6698	mov.<bw>	@%1,%0
6699	mov.<bw>	@(%O2,%1),%0"
6700  [(set_attr "type" "load")
6701   (set_attr "length" "2,2,4")])
6702
6703;; The *_snd patterns will take care of other QImode/HImode addressing
6704;; modes than displacement addressing.  They must be defined _after_ the
6705;; displacement addressing patterns.  Otherwise the displacement addressing
6706;; patterns will not be picked.
6707(define_insn "*extend<mode>si2_compact_snd"
6708  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6709	(sign_extend:SI
6710	  (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
6711  "TARGET_SH1"
6712  "mov.<bw>	%1,%0"
6713  [(set_attr "type" "load")])
6714
6715(define_insn "*extendqisi2_media"
6716  [(set (match_operand:SI 0 "register_operand" "=r,r")
6717	(sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6718  "TARGET_SHMEDIA"
6719  "@
6720	#
6721	ld%M1.b	%m1, %0"
6722  [(set_attr "type" "arith_media,load_media")
6723   (set (attr "highpart")
6724	(cond [(match_test "sh_contains_memref_p (insn)")
6725	       (const_string "user")]
6726	      (const_string "ignore")))])
6727
6728(define_split
6729  [(set (match_operand:SI 0 "register_operand" "")
6730	(sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
6731  "TARGET_SHMEDIA && reload_completed"
6732  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6733   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6734{
6735  rtx op1 = operands[1];
6736  if (GET_CODE (op1) == TRUNCATE)
6737    op1 = XEXP (op1, 0);
6738  operands[2]
6739    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6740			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
6741})
6742
6743(define_expand "extendqihi2"
6744  [(set (match_operand:HI 0 "arith_reg_dest")
6745	(sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))]
6746  "TARGET_SH1")
6747
6748(define_insn "*extendqihi2_compact_reg"
6749  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6750	(sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6751  "TARGET_SH1"
6752  "exts.b	%1,%0"
6753  [(set_attr "type" "arith")])
6754
6755;; It would seem useful to combine the truncXi patterns into the movXi
6756;; patterns, but unary operators are ignored when matching constraints,
6757;; so we need separate patterns.
6758(define_insn "truncdisi2"
6759  [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
6760	(truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6761  "TARGET_SHMEDIA"
6762  "@
6763	add.l	%1, r63, %0
6764	st%M0.l	%m0, %1
6765	fst%M0.s	%m0, %T1
6766	fmov.ls	%1, %0
6767	fmov.sl	%T1, %0
6768	fmov.s	%T1, %0"
6769  [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,
6770		     fpconv_media,fmove_media")
6771   (set (attr "highpart")
6772	(cond [(match_test "sh_contains_memref_p (insn)")
6773	       (const_string "user")]
6774	      (const_string "extend")))])
6775
6776(define_insn "truncdihi2"
6777  [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
6778	(truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6779  "TARGET_SHMEDIA"
6780{
6781  static const char* alt[] =
6782  {
6783       "shlli	%1,48,%0"	"\n"
6784    "	shlri	%0,48,%0",
6785
6786       "st%M0.w	%m0, %1"
6787  };
6788  return alt[which_alternative];
6789}
6790  [(set_attr "type"   "arith_media,store_media")
6791   (set_attr "length" "8,4")
6792   (set (attr "highpart")
6793	(cond [(match_test "sh_contains_memref_p (insn)")
6794	       (const_string "user")]
6795	      (const_string "extend")))])
6796
6797; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6798; Because we use zero extension, we can't provide signed QImode compares
6799; using a simple compare or conditional branch insn.
6800(define_insn "truncdiqi2"
6801  [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6802	(truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6803  "TARGET_SHMEDIA"
6804  "@
6805	andi	%1, 255, %0
6806	st%M0.b	%m0, %1"
6807  [(set_attr "type"   "arith_media,store")
6808   (set (attr "highpart")
6809	(cond [(match_test "sh_contains_memref_p (insn)")
6810	       (const_string "user")]
6811	      (const_string "extend")))])
6812
6813;; -------------------------------------------------------------------------
6814;; Move instructions
6815;; -------------------------------------------------------------------------
6816
6817;; define push and pop so it is easy for sh.c
6818;; We can't use push and pop on SHcompact because the stack must always
6819;; be 8-byte aligned.
6820(define_expand "push"
6821  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6822	(match_operand:SI 0 "register_operand" "r,l,x"))]
6823  "TARGET_SH1 && ! TARGET_SH5"
6824  "")
6825
6826(define_expand "pop"
6827  [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6828	(mem:SI (post_inc:SI (reg:SI SP_REG))))]
6829  "TARGET_SH1 && ! TARGET_SH5"
6830  "")
6831
6832(define_expand "push_e"
6833  [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6834		   (match_operand:SF 0 "" ""))
6835	      (use (reg:SI FPSCR_MODES_REG))
6836	      (clobber (scratch:SI))])]
6837  "TARGET_SH1 && ! TARGET_SH5"
6838  "")
6839
6840(define_insn "push_fpul"
6841  [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6842  "TARGET_SH2E && ! TARGET_SH5"
6843  "sts.l	fpul,@-r15"
6844  [(set_attr "type" "fstore")
6845   (set_attr "late_fp_use" "yes")
6846   (set_attr "hit_stack" "yes")])
6847
6848;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6849;; so use that.
6850(define_expand "push_4"
6851  [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6852		   (match_operand:DF 0 "" ""))
6853	      (use (reg:SI FPSCR_MODES_REG))
6854	      (clobber (scratch:SI))])]
6855  "TARGET_SH1 && ! TARGET_SH5"
6856  "")
6857
6858(define_expand "pop_e"
6859  [(parallel [(set (match_operand:SF 0 "" "")
6860	      (mem:SF (post_inc:SI (reg:SI SP_REG))))
6861	      (use (reg:SI FPSCR_MODES_REG))
6862	      (clobber (scratch:SI))])]
6863  "TARGET_SH1 && ! TARGET_SH5"
6864  "")
6865
6866(define_insn "pop_fpul"
6867  [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6868  "TARGET_SH2E && ! TARGET_SH5"
6869  "lds.l	@r15+,fpul"
6870  [(set_attr "type" "load")
6871   (set_attr "hit_stack" "yes")])
6872
6873(define_expand "pop_4"
6874  [(parallel [(set (match_operand:DF 0 "" "")
6875		   (mem:DF (post_inc:SI (reg:SI SP_REG))))
6876	      (use (reg:SI FPSCR_MODES_REG))
6877	      (clobber (scratch:SI))])]
6878  "TARGET_SH1 && ! TARGET_SH5"
6879  "")
6880
6881(define_expand "push_fpscr"
6882  [(const_int 0)]
6883  "TARGET_SH2E"
6884{
6885  add_reg_note (
6886    emit_insn (
6887      gen_sts_fpscr (
6888	gen_frame_mem (SImode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx)))),
6889    REG_INC, stack_pointer_rtx);
6890  DONE;
6891})
6892
6893(define_expand "pop_fpscr"
6894  [(const_int 0)]
6895  "TARGET_SH2E"
6896{
6897  add_reg_note (
6898    emit_insn (
6899      gen_lds_fpscr (
6900	gen_frame_mem (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)))),
6901    REG_INC, stack_pointer_rtx);
6902  DONE;
6903})
6904
6905;; The clrt and sett patterns can happen as the result of optimization and
6906;; insn expansion.
6907;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6908;; In this case they might not disappear completely, because the T reg is
6909;; a fixed hard reg.
6910;; When DImode operations that use the T reg as carry/borrow are split into
6911;; individual SImode operations, the T reg is usually cleared before the
6912;; first SImode insn.
6913(define_insn "clrt"
6914  [(set (reg:SI T_REG) (const_int 0))]
6915  "TARGET_SH1"
6916  "clrt"
6917  [(set_attr "type" "mt_group")])
6918
6919(define_insn "sett"
6920  [(set (reg:SI T_REG) (const_int 1))]
6921  "TARGET_SH1"
6922  "sett"
6923  [(set_attr "type" "mt_group")])
6924
6925;; Use the combine pass to transform sequences such as
6926;;	mov	r5,r0
6927;;	add	#1,r0
6928;;	shll2	r0
6929;;	mov.l	@(r0,r4),r0
6930;; into
6931;;	shll2	r5
6932;;	add	r4,r5
6933;;	mov.l	@(4,r5),r0
6934;;
6935;; See also PR 39423.
6936;; Notice that these patterns have a T_REG clobber, because the shift
6937;; sequence that will be split out might clobber the T_REG.  Ideally, the
6938;; clobber would be added conditionally, depending on the result of
6939;; sh_ashlsi_clobbers_t_reg_p.  When splitting out the shifts we must go
6940;; through the ashlsi3 expander in order to get the right shift insn --
6941;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
6942;; FIXME: Combine never tries this kind of patterns for DImode.
6943(define_insn_and_split "*movsi_index_disp_load"
6944  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6945	(match_operand:SI 1 "mem_index_disp_operand" "m"))
6946   (clobber (reg:SI T_REG))]
6947  "TARGET_SH1"
6948  "#"
6949  "&& can_create_pseudo_p ()"
6950  [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6951   (set (match_dup 0) (match_dup 7))]
6952{
6953  rtx mem = operands[1];
6954  rtx plus0_rtx = XEXP (mem, 0);
6955  rtx plus1_rtx = XEXP (plus0_rtx, 0);
6956  rtx mult_rtx = XEXP (plus1_rtx, 0);
6957
6958  operands[1] = XEXP (mult_rtx, 0);
6959  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6960  operands[3] = XEXP (plus1_rtx, 1);
6961  operands[4] = XEXP (plus0_rtx, 1);
6962  operands[5] = gen_reg_rtx (SImode);
6963  operands[6] = gen_reg_rtx (SImode);
6964  operands[7] =
6965    replace_equiv_address (mem,
6966			   gen_rtx_PLUS (SImode, operands[6], operands[4]));
6967
6968  emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
6969})
6970
6971(define_insn_and_split "*movhi_index_disp_load"
6972  [(set (match_operand:SI 0 "arith_reg_dest")
6973	(SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
6974   (clobber (reg:SI T_REG))]
6975  "TARGET_SH1"
6976  "#"
6977  "&& can_create_pseudo_p ()"
6978  [(const_int 0)]
6979{
6980  rtx mem = operands[1];
6981  rtx plus0_rtx = XEXP (mem, 0);
6982  rtx plus1_rtx = XEXP (plus0_rtx, 0);
6983  rtx mult_rtx = XEXP (plus1_rtx, 0);
6984
6985  rtx op_1 = XEXP (mult_rtx, 0);
6986  rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6987  rtx op_3 = XEXP (plus1_rtx, 1);
6988  rtx op_4 = XEXP (plus0_rtx, 1);
6989  rtx op_5 = gen_reg_rtx (SImode);
6990  rtx op_6 = gen_reg_rtx (SImode);
6991  rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6992
6993  emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6994  emit_insn (gen_addsi3 (op_6, op_5, op_3));
6995
6996  if (<CODE> == SIGN_EXTEND)
6997    {
6998      emit_insn (gen_extendhisi2 (operands[0], op_7));
6999      DONE;
7000    }
7001  else if (<CODE> == ZERO_EXTEND)
7002    {
7003      /* On SH2A the movu.w insn can be used for zero extending loads.  */
7004      if (TARGET_SH2A)
7005	emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
7006      else
7007	{
7008	  emit_insn (gen_extendhisi2 (operands[0], op_7));
7009	  emit_insn (gen_zero_extendhisi2 (operands[0],
7010				           gen_lowpart (HImode, operands[0])));
7011	}
7012      DONE;
7013    }
7014  else
7015    FAIL;
7016})
7017
7018(define_insn_and_split "*mov<mode>_index_disp_store"
7019  [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
7020	(match_operand:HISI 1 "arith_reg_operand" "r"))
7021   (clobber (reg:SI T_REG))]
7022  "TARGET_SH1"
7023  "#"
7024  "&& can_create_pseudo_p ()"
7025  [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
7026   (set (match_dup 7) (match_dup 1))]
7027{
7028  rtx mem = operands[0];
7029  rtx plus0_rtx = XEXP (mem, 0);
7030  rtx plus1_rtx = XEXP (plus0_rtx, 0);
7031  rtx mult_rtx = XEXP (plus1_rtx, 0);
7032
7033  operands[0] = XEXP (mult_rtx, 0);
7034  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
7035  operands[3] = XEXP (plus1_rtx, 1);
7036  operands[4] = XEXP (plus0_rtx, 1);
7037  operands[5] = gen_reg_rtx (SImode);
7038  operands[6] = gen_reg_rtx (SImode);
7039  operands[7] =
7040    replace_equiv_address (mem,
7041			   gen_rtx_PLUS (SImode, operands[6], operands[4]));
7042
7043  emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
7044})
7045
7046;; t/r must come after r/r, lest reload will try to reload stuff like
7047;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
7048;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
7049(define_insn "movsi_i"
7050  [(set (match_operand:SI 0 "general_movdst_operand"
7051	    "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
7052	(match_operand:SI 1 "general_movsrc_operand"
7053	 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
7054  "TARGET_SH1
7055   && ! TARGET_SH2E
7056   && ! TARGET_SH2A
7057   && (register_operand (operands[0], SImode)
7058       || register_operand (operands[1], SImode))"
7059  "@
7060	mov.l	%1,%0
7061	mov	%1,%0
7062	mov	%1,%0
7063	mov.l	%1,%0
7064	sts	%1,%0
7065	sts	%1,%0
7066	mov.l	%1,%0
7067	sts.l	%1,%0
7068	sts.l	%1,%0
7069	lds	%1,%0
7070	lds	%1,%0
7071	lds.l	%1,%0
7072	lds.l	%1,%0
7073	fake	%1,%0"
7074  [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,
7075		     pstore,gp_mac,prset,mem_mac,pload,pcload_si")
7076   (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
7077
7078;; t/r must come after r/r, lest reload will try to reload stuff like
7079;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
7080;; ??? This allows moves from macl to fpul to be recognized, but these moves
7081;; will require a reload.
7082;; ??? We can't include f/f because we need the proper FPSCR setting when
7083;; TARGET_FMOVD is in effect, and mode switching is done before reload.
7084(define_insn "movsi_ie"
7085  [(set (match_operand:SI 0 "general_movdst_operand"
7086	    "=r,r,r,r,r,r,r,r,mr,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
7087	(match_operand:SI 1 "general_movsrc_operand"
7088	 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
7089  "(TARGET_SH2E || TARGET_SH2A)
7090   && ((register_operand (operands[0], SImode)
7091	&& !fpscr_operand (operands[0], SImode))
7092       || (register_operand (operands[1], SImode)
7093	   && !fpscr_operand (operands[1], SImode)))"
7094  "@
7095	mov.l	%1,%0
7096	mov	%1,%0
7097	mov	%1,%0
7098	movi20	%1,%0
7099	movi20s	%1,%0
7100	mov.l	%1,%0
7101	sts	%1,%0
7102	sts	%1,%0
7103	mov.l	%1,%0
7104	sts.l	%1,%0
7105	sts.l	%1,%0
7106	lds	%1,%0
7107	lds	%1,%0
7108	lds.l	%1,%0
7109	lds.l	%1,%0
7110	lds.l	%1,%0
7111	sts.l	%1,%0
7112	fake	%1,%0
7113	lds	%1,%0
7114	sts	%1,%0
7115	fsts	fpul,%0
7116	flds	%1,fpul
7117	fmov	%1,%0
7118	! move optimized away"
7119  [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,
7120		     mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,
7121		     pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
7122   (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
7123   (set_attr_alternative "length"
7124     [(const_int 2)
7125      (const_int 2)
7126      (const_int 2)
7127      (const_int 4)
7128      (const_int 4)
7129      (if_then_else
7130	(match_test "TARGET_SH2A")
7131	(const_int 4) (const_int 2))
7132      (const_int 2)
7133      (const_int 2)
7134      (if_then_else
7135	(match_test "TARGET_SH2A")
7136	(const_int 4) (const_int 2))
7137      (const_int 2)
7138      (const_int 2)
7139      (const_int 2)
7140      (const_int 2)
7141      (const_int 2)
7142      (const_int 2)
7143      (const_int 2)
7144      (const_int 2)
7145      (const_int 2)
7146      (const_int 2)
7147      (const_int 2)
7148      (const_int 2)
7149      (const_int 2)
7150      (const_int 2)
7151      (const_int 0)])])
7152
7153(define_insn "movsi_i_lowpart"
7154  [(set (strict_low_part
7155	  (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
7156	(match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
7157   "TARGET_SH1
7158    && (register_operand (operands[0], SImode)
7159        || register_operand (operands[1], SImode))"
7160  "@
7161	mov.l	%1,%0
7162	mov	%1,%0
7163	mov	%1,%0
7164	mov.l	%1,%0
7165	sts	%1,%0
7166	sts	%1,%0
7167	mov.l	%1,%0
7168	fake	%1,%0"
7169  [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
7170
7171(define_insn_and_split "load_ra"
7172  [(set (match_operand:SI 0 "general_movdst_operand" "")
7173	(unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
7174  "TARGET_SH1"
7175  "#"
7176  "&& ! currently_expanding_to_rtl"
7177  [(set (match_dup 0) (match_dup 1))]
7178{
7179  if (TARGET_SHCOMPACT && crtl->saves_all_registers)
7180    operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
7181})
7182
7183;; The '?'s in the following constraints may not reflect the time taken
7184;; to perform the move. They are there to discourage the use of floating-
7185;; point registers for storing integer values.
7186(define_insn "*movsi_media"
7187  [(set (match_operand:SI 0 "general_movdst_operand"
7188	        "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
7189	(match_operand:SI 1 "general_movsrc_operand"
7190	 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7191  "TARGET_SHMEDIA_FPU
7192   && (register_operand (operands[0], SImode)
7193       || sh_register_operand (operands[1], SImode)
7194       || GET_CODE (operands[1]) == TRUNCATE)"
7195  "@
7196	add.l	%1, r63, %0
7197	movi	%1, %0
7198	#
7199	ld%M1.l	%m1, %0
7200	st%M0.l	%m0, %N1
7201	fld%M1.s	%m1, %0
7202	fst%M0.s	%m0, %1
7203	fmov.ls	%N1, %0
7204	fmov.sl	%1, %0
7205	fmov.s	%1, %0
7206	ptabs	%1, %0
7207	gettr	%1, %0
7208	pt	%1, %0"
7209  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,
7210		       fload_media,fstore_media,fload_media,fpconv_media,
7211		       fmove_media,ptabs_media,gettr_media,pt_media")
7212   (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
7213   (set (attr "highpart")
7214	(cond [(match_test "sh_contains_memref_p (insn)")
7215	       (const_string "user")]
7216	      (const_string "ignore")))])
7217
7218(define_insn "*movsi_media_nofpu"
7219  [(set (match_operand:SI 0 "general_movdst_operand"
7220	        "=r,r,r,r,m,*b,r,*b")
7221	(match_operand:SI 1 "general_movsrc_operand"
7222	 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
7223  "TARGET_SHMEDIA
7224   && (register_operand (operands[0], SImode)
7225       || sh_register_operand (operands[1], SImode)
7226       || GET_CODE (operands[1]) == TRUNCATE)"
7227  "@
7228	add.l	%1, r63, %0
7229	movi	%1, %0
7230	#
7231	ld%M1.l	%m1, %0
7232	st%M0.l	%m0, %N1
7233	ptabs	%1, %0
7234	gettr	%1, %0
7235	pt	%1, %0"
7236  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7237		     ptabs_media,gettr_media,pt_media")
7238   (set_attr "length" "4,4,8,4,4,4,4,12")
7239   (set (attr "highpart")
7240	(cond [(match_test "sh_contains_memref_p (insn)")
7241	       (const_string "user")]
7242	      (const_string "ignore")))])
7243
7244(define_expand "movsi_const"
7245  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7246	(const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
7247			      (const_int 16)] UNSPEC_EXTRACT_S16)))
7248   (set (match_dup 0)
7249	(ior:SI (ashift:SI (match_dup 0) (const_int 16))
7250		(const:SI (unspec:SI [(match_dup 1)
7251				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
7252  "TARGET_SHMEDIA && reload_completed
7253   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7254{
7255  if (GET_CODE (operands[1]) == LABEL_REF
7256      && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
7257    LABEL_NUSES (XEXP (operands[1], 0)) += 2;
7258  else if (GOTOFF_P (operands[1]))
7259    {
7260      rtx unspec = XEXP (operands[1], 0);
7261
7262      if (! UNSPEC_GOTOFF_P (unspec))
7263	{
7264	  unspec = XEXP (unspec, 0);
7265	  if (! UNSPEC_GOTOFF_P (unspec))
7266	    abort ();
7267	}
7268      if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
7269	  && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
7270	LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
7271    }
7272})
7273
7274(define_expand "movsi_const_16bit"
7275  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7276	(const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
7277			      (const_int 0)] UNSPEC_EXTRACT_S16)))]
7278  "TARGET_SHMEDIA && flag_pic && reload_completed
7279   && GET_CODE (operands[1]) == SYMBOL_REF"
7280  "")
7281
7282(define_split
7283  [(set (match_operand:SI 0 "arith_reg_dest" "")
7284	(match_operand:SI 1 "immediate_operand" ""))]
7285  "TARGET_SHMEDIA && reload_completed
7286   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7287  [(const_int 0)]
7288{
7289  rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
7290
7291  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7292
7293  DONE;
7294})
7295
7296(define_split
7297  [(set (match_operand:SI 0 "register_operand" "")
7298	(match_operand:SI 1 "immediate_operand" ""))]
7299  "TARGET_SHMEDIA && reload_completed
7300   && ((CONST_INT_P (operands[1])
7301	&& ! satisfies_constraint_I16 (operands[1]))
7302       || GET_CODE (operands[1]) == CONST_DOUBLE)"
7303  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7304
7305(define_expand "movsi"
7306  [(set (match_operand:SI 0 "general_movdst_operand" "")
7307	(match_operand:SI 1 "general_movsrc_operand" ""))]
7308  ""
7309{
7310  prepare_move_operands (operands, SImode);
7311})
7312
7313(define_expand "ic_invalidate_line"
7314  [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
7315				(match_dup 1)] UNSPEC_ICACHE)
7316	      (clobber (scratch:SI))])]
7317  "TARGET_HARD_SH4 || TARGET_SH5"
7318{
7319  if (TARGET_SHMEDIA)
7320    {
7321      emit_insn (gen_ic_invalidate_line_media (operands[0]));
7322      DONE;
7323    }
7324  else if (TARGET_SHCOMPACT)
7325    {
7326      operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
7327      operands[1] = force_reg (Pmode, operands[1]);
7328      emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
7329      DONE;
7330    }
7331  else if (TARGET_SH4A || TARGET_SH4_300)
7332    {
7333      emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
7334      DONE;
7335    }
7336  operands[0] = force_reg (Pmode, operands[0]);
7337  operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
7338							       Pmode)));
7339})
7340
7341;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
7342;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
7343;; the requirement *1*00 for associative address writes.  The alignment of
7344;; %0 implies that its least significant bit is cleared,
7345;; thus we clear the V bit of a matching entry if there is one.
7346(define_insn "ic_invalidate_line_i"
7347  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
7348		     (match_operand:SI 1 "register_operand" "r")]
7349		     UNSPEC_ICACHE)
7350   (clobber (match_scratch:SI 2 "=&r"))]
7351  "TARGET_HARD_SH4"
7352{
7353  return       "ocbwb	@%0"	"\n"
7354	 "	extu.w	%0,%2"	"\n"
7355	 "	or	%1,%2"	"\n"
7356	 "	mov.l	%0,@%2";
7357}
7358  [(set_attr "length" "8")
7359   (set_attr "type" "cwb")])
7360
7361(define_insn "ic_invalidate_line_sh4a"
7362  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
7363		    UNSPEC_ICACHE)]
7364  "TARGET_SH4A || TARGET_SH4_300"
7365{
7366  return       "ocbwb	@%0"	"\n"
7367	 "	synco"		"\n"
7368	 "	icbi	@%0";
7369}
7370  [(set_attr "length" "16")	;; FIXME: Why 16 and not 6?  Looks like typo.
7371   (set_attr "type" "cwb")])
7372
7373;; ??? could make arg 0 an offsettable memory operand to allow to save
7374;; an add in the code that calculates the address.
7375(define_insn "ic_invalidate_line_media"
7376  [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
7377		    UNSPEC_ICACHE)]
7378  "TARGET_SHMEDIA"
7379{
7380  return       "ocbwb	%0,0"	"\n"
7381	 "	synco"		"\n"
7382	 "	icbi	%0,0"	"\n"
7383	 "	synci";
7384}
7385  [(set_attr "length" "16")
7386   (set_attr "type" "invalidate_line_media")])
7387
7388(define_insn "ic_invalidate_line_compact"
7389  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
7390		     (match_operand:SI 1 "register_operand" "r")]
7391		    UNSPEC_ICACHE)
7392   (clobber (reg:SI PR_REG))]
7393  "TARGET_SHCOMPACT"
7394  "jsr @%1%#"
7395  [(set_attr "type" "sfunc")
7396   (set_attr "needs_delay_slot" "yes")])
7397
7398(define_expand "initialize_trampoline"
7399  [(match_operand:SI 0 "" "")
7400   (match_operand:SI 1 "" "")
7401   (match_operand:SI 2 "" "")]
7402  "TARGET_SHCOMPACT"
7403{
7404  rtx sfun, tramp;
7405
7406  tramp = force_reg (Pmode, operands[0]);
7407  sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
7408					    SFUNC_STATIC));
7409  emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
7410  emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
7411
7412  emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
7413  DONE;
7414})
7415
7416(define_insn "initialize_trampoline_compact"
7417  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
7418		     (match_operand:SI 1 "register_operand" "r")
7419		     (reg:SI R2_REG) (reg:SI R3_REG)]
7420		    UNSPEC_INIT_TRAMP)
7421
7422   (clobber (reg:SI PR_REG))]
7423  "TARGET_SHCOMPACT"
7424  "jsr @%1%#"
7425  [(set_attr "type" "sfunc")
7426   (set_attr "needs_delay_slot" "yes")])
7427
7428(define_expand "mov<mode>"
7429  [(set (match_operand:QIHI 0 "general_movdst_operand")
7430	(match_operand:QIHI 1 "general_movsrc_operand"))]
7431  ""
7432{
7433 if (can_create_pseudo_p () && CONST_INT_P (operands[1])
7434    && REG_P (operands[0]) && REGNO (operands[0]) != R0_REG)
7435    {
7436        rtx reg = gen_reg_rtx(SImode);
7437        emit_move_insn (reg, operands[1]);
7438        operands[1] = gen_lowpart (<MODE>mode, reg);
7439    }
7440
7441  prepare_move_operands (operands, <MODE>mode);
7442})
7443
7444;; Specifying the displacement addressing load / store patterns separately
7445;; before the generic movqi / movhi pattern allows controlling the order
7446;; in which load / store insns are selected in a more fine grained way.
7447;; FIXME: The non-SH2A and SH2A variants should be combined by adding
7448;; "enabled" attribute as it is done in other targets.
7449(define_insn "*mov<mode>_store_mem_disp04"
7450  [(set (mem:QIHI
7451	  (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
7452		   (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
7453	(match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
7454  "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
7455  "@
7456	mov.<bw>	%2,@(%O1,%0)
7457	mov.<bw>	%2,@%0"
7458  [(set_attr "type" "store")])
7459
7460(define_insn "*mov<mode>_store_mem_disp12"
7461  [(set (mem:QIHI
7462	  (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
7463		   (match_operand:SI 1 "const_int_operand" "<disp12>")))
7464	(match_operand:QIHI 2 "arith_reg_operand" "r"))]
7465  "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
7466  "mov.<bw>	%2,@(%O1,%0)"
7467  [(set_attr "type" "store")
7468   (set_attr "length" "4")])
7469
7470(define_insn "*mov<mode>_load_mem_disp04"
7471  [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
7472	(mem:QIHI
7473	  (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
7474		   (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
7475  "TARGET_SH1 && ! TARGET_SH2A
7476   && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
7477  "@
7478	mov.<bw>	@(%O2,%1),%0
7479	mov.<bw>	@%1,%0"
7480  [(set_attr "type" "load")])
7481
7482(define_insn "*mov<mode>_load_mem_disp12"
7483  [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
7484	(mem:QIHI
7485	  (plus:SI
7486	    (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
7487	    (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
7488  "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
7489  "@
7490	mov.<bw>	@(%O2,%1),%0
7491	mov.<bw>	@%1,%0
7492	mov.<bw>	@(%O2,%1),%0"
7493  [(set_attr "type" "load")
7494   (set_attr "length" "2,2,4")])
7495
7496;; The order of the constraint alternatives is important here.
7497;; Q/r has to come first, otherwise PC relative loads might wrongly get
7498;; placed into delay slots.  Since there is no QImode PC relative load, the
7499;; Q constraint and general_movsrc_operand will reject it for QImode.
7500;; The Snd alternatives should come before Sdd in order to avoid a preference
7501;; of using r0 als the register operand for addressing modes other than
7502;; displacement addressing.
7503;; The Sdd alternatives allow only r0 as register operand, even though on
7504;; SH2A any register could be allowed by switching to a 32 bit insn.
7505;; Generally sticking to the r0 is preferrable, since it generates smaller
7506;; code.  Obvious r0 reloads can then be eliminated with a peephole on SH2A.
7507(define_insn "*mov<mode>"
7508  [(set (match_operand:QIHI 0 "general_movdst_operand"
7509			      "=r,r,r,Snd,r,  Sdd,z,  r,l")
7510	(match_operand:QIHI 1 "general_movsrc_operand"
7511			       "Q,r,i,r,  Snd,z,  Sdd,l,r"))]
7512  "TARGET_SH1
7513   && (arith_reg_operand (operands[0], <MODE>mode)
7514       || arith_reg_operand (operands[1], <MODE>mode))"
7515  "@
7516	mov.<bw>	%1,%0
7517	mov	%1,%0
7518	mov	%1,%0
7519	mov.<bw>	%1,%0
7520	mov.<bw>	%1,%0
7521	mov.<bw>	%1,%0
7522	mov.<bw>	%1,%0
7523	sts	%1,%0
7524	lds	%1,%0"
7525  [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset")
7526   (set (attr "length")
7527	(cond [(and (match_operand 0 "displacement_mem_operand")
7528		    (not (match_operand 0 "short_displacement_mem_operand")))
7529	       (const_int 4)
7530	       (and (match_operand 1 "displacement_mem_operand")
7531		    (not (match_operand 1 "short_displacement_mem_operand")))
7532	       (const_int 4)]
7533	      (const_int 2)))])
7534
7535(define_insn "*movqi_media"
7536  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
7537	(match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
7538  "TARGET_SHMEDIA
7539   && (arith_reg_operand (operands[0], QImode)
7540       || extend_reg_or_0_operand (operands[1], QImode))"
7541  "@
7542	add.l	%1, r63, %0
7543	movi	%1, %0
7544	ld%M1.ub	%m1, %0
7545	st%M0.b	%m0, %N1"
7546  [(set_attr "type" "arith_media,arith_media,load_media,store_media")
7547   (set (attr "highpart")
7548	(cond [(match_test "sh_contains_memref_p (insn)")
7549	       (const_string "user")]
7550	      (const_string "ignore")))])
7551
7552(define_expand "reload_inqi"
7553  [(set (match_operand:SI 2 "" "=&r")
7554	(match_operand:QI 1 "inqhi_operand" ""))
7555   (set (match_operand:QI 0 "arith_reg_operand" "=r")
7556	(truncate:QI (match_dup 3)))]
7557  "TARGET_SHMEDIA"
7558{
7559  rtx inner = XEXP (operands[1], 0);
7560  int regno = REGNO (inner);
7561
7562  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7563  operands[1] = gen_rtx_REG (SImode, regno);
7564  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7565})
7566
7567(define_insn "*movhi_media"
7568  [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
7569	(match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
7570  "TARGET_SHMEDIA
7571   && (arith_reg_operand (operands[0], HImode)
7572       || arith_reg_or_0_operand (operands[1], HImode))"
7573  "@
7574	add.l	%1, r63, %0
7575	movi	%1, %0
7576	#
7577	ld%M1.w	%m1, %0
7578	st%M0.w	%m0, %N1"
7579  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
7580   (set (attr "highpart")
7581	(cond [(match_test "sh_contains_memref_p (insn)")
7582	       (const_string "user")]
7583	      (const_string "ignore")))])
7584
7585(define_split
7586  [(set (match_operand:HI 0 "register_operand" "")
7587	(match_operand:HI 1 "immediate_operand" ""))]
7588  "TARGET_SHMEDIA && reload_completed
7589   && ! satisfies_constraint_I16 (operands[1])"
7590  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7591
7592(define_expand "reload_inhi"
7593  [(set (match_operand:SI 2 "" "=&r")
7594	(match_operand:HI 1 "inqhi_operand" ""))
7595   (set (match_operand:HI 0 "arith_reg_operand" "=r")
7596	(truncate:HI (match_dup 3)))]
7597  "TARGET_SHMEDIA"
7598{
7599  rtx inner = XEXP (operands[1], 0);
7600  int regno = REGNO (inner);
7601
7602  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7603  operands[1] = gen_rtx_REG (SImode, regno);
7604  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7605})
7606
7607;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
7608;; compiled with -m2 -ml -O3 -funroll-loops
7609(define_insn "*movdi_i"
7610  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
7611	(match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
7612  "TARGET_SH1
7613   && (arith_reg_operand (operands[0], DImode)
7614       || arith_reg_operand (operands[1], DImode))"
7615{
7616  return output_movedouble (insn, operands, DImode);
7617}
7618  [(set_attr "length" "4")
7619   (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
7620
7621;; If the output is a register and the input is memory or a register, we have
7622;; to be careful and see which word needs to be loaded first.
7623(define_split
7624  [(set (match_operand:DI 0 "general_movdst_operand" "")
7625	(match_operand:DI 1 "general_movsrc_operand" ""))]
7626  "TARGET_SH1 && reload_completed"
7627  [(set (match_dup 2) (match_dup 3))
7628   (set (match_dup 4) (match_dup 5))]
7629{
7630  int regno;
7631
7632  if ((MEM_P (operands[0])
7633       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7634      || (MEM_P (operands[1])
7635	  && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7636    FAIL;
7637
7638  switch (GET_CODE (operands[0]))
7639    {
7640    case REG:
7641      regno = REGNO (operands[0]);
7642      break;
7643    case SUBREG:
7644      regno = subreg_regno (operands[0]);
7645      break;
7646    case MEM:
7647      regno = -1;
7648      break;
7649    default:
7650      gcc_unreachable ();
7651    }
7652
7653  if (regno == -1 || ! refers_to_regno_p (regno, operands[1]))
7654    {
7655      operands[2] = operand_subword (operands[0], 0, 0, DImode);
7656      operands[3] = operand_subword (operands[1], 0, 0, DImode);
7657      operands[4] = operand_subword (operands[0], 1, 0, DImode);
7658      operands[5] = operand_subword (operands[1], 1, 0, DImode);
7659    }
7660  else
7661    {
7662      operands[2] = operand_subword (operands[0], 1, 0, DImode);
7663      operands[3] = operand_subword (operands[1], 1, 0, DImode);
7664      operands[4] = operand_subword (operands[0], 0, 0, DImode);
7665      operands[5] = operand_subword (operands[1], 0, 0, DImode);
7666    }
7667
7668  if (operands[2] == 0 || operands[3] == 0
7669      || operands[4] == 0 || operands[5] == 0)
7670    FAIL;
7671})
7672
7673;; The '?'s in the following constraints may not reflect the time taken
7674;; to perform the move. They are there to discourage the use of floating-
7675;; point registers for storing integer values.
7676(define_insn "*movdi_media"
7677  [(set (match_operand:DI 0 "general_movdst_operand"
7678	         "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
7679	(match_operand:DI 1 "general_movsrc_operand"
7680	 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7681  "TARGET_SHMEDIA_FPU
7682   && (register_operand (operands[0], DImode)
7683       || sh_register_operand (operands[1], DImode))"
7684  "@
7685	add	%1, r63, %0
7686	movi	%1, %0
7687	#
7688	ld%M1.q	%m1, %0
7689	st%M0.q	%m0, %N1
7690	fld%M1.d	%m1, %0
7691	fst%M0.d	%m0, %1
7692	fmov.qd	%N1, %0
7693	fmov.dq	%1, %0
7694	fmov.d	%1, %0
7695	ptabs	%1, %0
7696	gettr	%1, %0
7697	pt	%1, %0"
7698  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7699		     fload_media,fstore_media,fload_media,dfpconv_media,
7700		     fmove_media,ptabs_media,gettr_media,pt_media")
7701   (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7702
7703(define_insn "*movdi_media_nofpu"
7704  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
7705	(match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
7706  "TARGET_SHMEDIA
7707   && (register_operand (operands[0], DImode)
7708       || sh_register_operand (operands[1], DImode))"
7709  "@
7710	add	%1, r63, %0
7711	movi	%1, %0
7712	#
7713	ld%M1.q	%m1, %0
7714	st%M0.q	%m0, %N1
7715	ptabs	%1, %0
7716	gettr	%1, %0
7717	pt	%1, %0"
7718  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7719		     ptabs_media,gettr_media,pt_media")
7720   (set_attr "length" "4,4,16,4,4,4,4,*")])
7721
7722(define_insn "*movdi_media_I16"
7723  [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7724	(match_operand:DI 1 "const_int_operand" "I16"))]
7725  "TARGET_SHMEDIA && reload_completed"
7726  "movi	%1, %0"
7727  [(set_attr "type" "arith_media")
7728   (set_attr "length" "4")])
7729
7730(define_split
7731  [(set (match_operand:DI 0 "arith_reg_dest" "")
7732	(match_operand:DI 1 "immediate_operand" ""))]
7733  "TARGET_SHMEDIA && reload_completed
7734   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7735  [(set (match_dup 0) (match_dup 1))]
7736{
7737  rtx insn;
7738
7739  if (TARGET_SHMEDIA64)
7740    insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7741  else
7742    insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7743
7744  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7745
7746  DONE;
7747})
7748
7749(define_expand "movdi_const"
7750  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7751	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7752		  	      (const_int 48)] UNSPEC_EXTRACT_S16)))
7753   (set (match_dup 0)
7754	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7755		(const:DI (unspec:DI [(match_dup 1)
7756				      (const_int 32)] UNSPEC_EXTRACT_U16))))
7757   (set (match_dup 0)
7758	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7759		(const:DI (unspec:DI [(match_dup 1)
7760				      (const_int 16)] UNSPEC_EXTRACT_U16))))
7761   (set (match_dup 0)
7762	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7763		(const:DI (unspec:DI [(match_dup 1)
7764				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
7765  "TARGET_SHMEDIA64 && reload_completed
7766   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7767{
7768  sh_mark_label (operands[1], 4);
7769})
7770
7771(define_expand "movdi_const_32bit"
7772  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7773	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7774			      (const_int 16)] UNSPEC_EXTRACT_S16)))
7775   (set (match_dup 0)
7776	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7777		(const:DI (unspec:DI [(match_dup 1)
7778				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
7779  "TARGET_SHMEDIA32 && reload_completed
7780   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7781{
7782  sh_mark_label (operands[1], 2);
7783})
7784
7785(define_expand "movdi_const_16bit"
7786  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7787	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7788			      (const_int 0)] UNSPEC_EXTRACT_S16)))]
7789  "TARGET_SHMEDIA && flag_pic && reload_completed
7790   && GET_CODE (operands[1]) == SYMBOL_REF"
7791  "")
7792
7793(define_split
7794  [(set (match_operand:DI 0 "ext_dest_operand" "")
7795	(match_operand:DI 1 "immediate_operand" ""))]
7796  "TARGET_SHMEDIA && reload_completed
7797   && CONST_INT_P (operands[1])
7798   && ! satisfies_constraint_I16 (operands[1])"
7799  [(set (match_dup 0) (match_dup 2))
7800   (match_dup 1)]
7801{
7802  unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7803  unsigned HOST_WIDE_INT low = val;
7804  unsigned HOST_WIDE_INT high = val;
7805  unsigned HOST_WIDE_INT sign;
7806  unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7807
7808  /* Zero-extend the 16 least-significant bits.  */
7809  low &= 0xffff;
7810
7811  /* Arithmetic shift right the word by 16 bits.  */
7812  high >>= 16;
7813  if (GET_CODE (operands[0]) == SUBREG
7814      && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7815    {
7816      high &= 0xffff;
7817      high ^= 0x8000;
7818      high -= 0x8000;
7819    }
7820  else
7821    {
7822      sign = 1;
7823      sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7824      high ^= sign;
7825      high -= sign;
7826    }
7827  do
7828    {
7829      /* If we can't generate the constant with a two-insn movi / shori
7830	 sequence, try some other strategies.  */
7831      if (! CONST_OK_FOR_I16 (high))
7832	{
7833	  /* Try constant load / left shift.  We know VAL != 0.  */
7834	  val2 = val ^ (val-1);
7835	  if (val2 > 0x1ffff)
7836	    {
7837	      int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7838
7839	      if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7840		  || (! CONST_OK_FOR_I16 (high >> 16)
7841		      && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7842		{
7843		  val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7844		  operands[1] = gen_ashldi3_media (operands[0], operands[0],
7845						   GEN_INT (trailing_zeroes));
7846		  break;
7847		}
7848	    }
7849	  /* Try constant load / right shift.  */
7850	  val2 = (val >> 15) + 1;
7851	  if (val2 == (val2 & -val2))
7852	    {
7853	      int shift = 49 - exact_log2 (val2);
7854
7855	      val2 = trunc_int_for_mode (val << shift, DImode);
7856	      if (CONST_OK_FOR_I16 (val2))
7857		{
7858		  operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7859						   GEN_INT (shift));
7860		  break;
7861		}
7862	    }
7863	  /* Try mperm.w .  */
7864	  val2 = val & 0xffff;
7865	  if ((val >> 16 & 0xffff) == val2
7866	      && (val >> 32 & 0xffff) == val2
7867	      && (val >> 48 & 0xffff) == val2)
7868	    {
7869	      val2 = (HOST_WIDE_INT) val >> 48;
7870	      operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7871	      operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7872	      break;
7873	    }
7874	  /* Try movi / mshflo.l  */
7875	  val2 = (HOST_WIDE_INT) val >> 32;
7876	  if (val2 == ((unsigned HOST_WIDE_INT)
7877			trunc_int_for_mode (val, SImode)))
7878	    {
7879	      operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7880					     operands[0]);
7881	      break;
7882	    }
7883	  /* Try movi / mshflo.l w/ r63.  */
7884	  val2 = val + ((HOST_WIDE_INT) -1 << 32);
7885	  if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7886	    {
7887	      operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7888					     const0_rtx);
7889	      break;
7890	    }
7891	}
7892      val2 = high;
7893      operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7894    }
7895  while (0);
7896  operands[2] = GEN_INT (val2);
7897})
7898
7899(define_split
7900  [(set (match_operand:DI 0 "ext_dest_operand" "")
7901	(match_operand:DI 1 "immediate_operand" ""))]
7902  "TARGET_SHMEDIA && reload_completed
7903   && GET_CODE (operands[1]) == CONST_DOUBLE"
7904  [(set (match_dup 0) (match_dup 2))
7905  (set (match_dup 0)
7906       (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7907{
7908  unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7909  unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7910  unsigned HOST_WIDE_INT val = low;
7911  unsigned HOST_WIDE_INT sign;
7912
7913  /* Zero-extend the 16 least-significant bits.  */
7914  val &= 0xffff;
7915  operands[1] = GEN_INT (val);
7916
7917  /* Arithmetic shift right the double-word by 16 bits.  */
7918  low >>= 16;
7919  low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7920  high >>= 16;
7921  sign = 1;
7922  sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7923  high ^= sign;
7924  high -= sign;
7925
7926  /* This will only be true if high is a sign-extension of low, i.e.,
7927     it must be either 0 or (unsigned)-1, and be zero iff the
7928     most-significant bit of low is set.  */
7929  if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7930    operands[2] = GEN_INT (low);
7931  else
7932    operands[2] = immed_double_const (low, high, DImode);
7933})
7934
7935(define_insn "shori_media"
7936  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
7937	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7938			   (const_int 16))
7939		(match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
7940  "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
7941  "@
7942	shori	%u2, %0
7943	#"
7944  [(set_attr "type" "arith_media,*")])
7945
7946(define_insn "*shori_media_si"
7947  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7948	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7949			   (const_int 16))
7950		(match_operand:SI 2 "immediate_operand" "K16Csu")))]
7951  "TARGET_SHMEDIA"
7952  "shori	%u2, %0")
7953
7954(define_expand "movdi"
7955  [(set (match_operand:DI 0 "general_movdst_operand" "")
7956	(match_operand:DI 1 "general_movsrc_operand" ""))]
7957  ""
7958{
7959  prepare_move_operands (operands, DImode);
7960  if (TARGET_SH1)
7961    {
7962      /* When the dest operand is (R0, R1) register pair, split it to
7963	 two movsi of which dest is R1 and R0 so as to lower R0-register
7964	 pressure on the first movsi.  Apply only for simple source not
7965	 to make complex rtl here.  */
7966      if (REG_P (operands[0])
7967	  && REGNO (operands[0]) == R0_REG
7968	  && REG_P (operands[1])
7969	  && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
7970	{
7971	  emit_insn (gen_movsi (gen_rtx_REG (SImode, R1_REG),
7972			        gen_rtx_SUBREG (SImode, operands[1], 4)));
7973	  emit_insn (gen_movsi (gen_rtx_REG (SImode, R0_REG),
7974			        gen_rtx_SUBREG (SImode, operands[1], 0)));
7975	  DONE;
7976	}
7977    }
7978})
7979
7980(define_insn "movdf_media"
7981  [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7982	(match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7983  "TARGET_SHMEDIA_FPU
7984   && (register_operand (operands[0], DFmode)
7985       || sh_register_operand (operands[1], DFmode))"
7986  "@
7987	fmov.d	%1, %0
7988	fmov.qd	%N1, %0
7989	fmov.dq	%1, %0
7990	add	%1, r63, %0
7991	#
7992	fld%M1.d	%m1, %0
7993	fst%M0.d	%m0, %1
7994	ld%M1.q	%m1, %0
7995	st%M0.q	%m0, %N1"
7996  [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,
7997		     fload_media,fstore_media,load_media,store_media")])
7998
7999(define_insn "movdf_media_nofpu"
8000  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
8001	(match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8002  "TARGET_SHMEDIA
8003   && (register_operand (operands[0], DFmode)
8004       || sh_register_operand (operands[1], DFmode))"
8005  "@
8006	add	%1, r63, %0
8007	#
8008	ld%M1.q	%m1, %0
8009	st%M0.q	%m0, %N1"
8010  [(set_attr "type" "arith_media,*,load_media,store_media")])
8011
8012(define_split
8013  [(set (match_operand:DF 0 "arith_reg_dest" "")
8014	(match_operand:DF 1 "immediate_operand" ""))]
8015  "TARGET_SHMEDIA && reload_completed"
8016  [(set (match_dup 3) (match_dup 2))]
8017{
8018  int endian = WORDS_BIG_ENDIAN ? 1 : 0;
8019  long values[2];
8020  REAL_VALUE_TYPE value;
8021
8022  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
8023  REAL_VALUE_TO_TARGET_DOUBLE (value, values);
8024
8025  if (HOST_BITS_PER_WIDE_INT >= 64)
8026    operands[2] = immed_double_const ((unsigned long) values[endian]
8027				      | ((HOST_WIDE_INT) values[1 - endian]
8028					 << 32), 0, DImode);
8029  else
8030    {
8031      gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
8032      operands[2] = immed_double_const (values[endian], values[1 - endian],
8033	  			        DImode);
8034    }
8035
8036  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8037})
8038
8039;; FIXME: This should be a define_insn_and_split.
8040(define_insn "movdf_k"
8041  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
8042	(match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
8043  "TARGET_SH1
8044   && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
8045       /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
8046       || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8047       || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8048   && (arith_reg_operand (operands[0], DFmode)
8049       || arith_reg_operand (operands[1], DFmode))"
8050{
8051  return output_movedouble (insn, operands, DFmode);
8052}
8053  [(set_attr "length" "4")
8054   (set_attr "type" "move,pcload,load,store")])
8055
8056;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
8057;; However, the d/F/c/z alternative cannot be split directly; it is converted
8058;; with special code in machine_dependent_reorg into a load of the R0_REG and
8059;; the d/m/c/X alternative, which is split later into single-precision
8060;; instructions.  And when not optimizing, no splits are done before fixing
8061;; up pcloads, so we need usable length information for that.
8062(define_insn "movdf_i4"
8063  [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
8064	(match_operand:DF 1 "general_movsrc_operand"  "d,r,F,m,d,FQ,m,r,d,r"))
8065   (use (reg:SI FPSCR_MODES_REG))
8066   (clobber (match_scratch:SI 2                      "=X,X,&z,X,X,X,X,X,X,X"))]
8067  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
8068   && (arith_reg_operand (operands[0], DFmode)
8069       || arith_reg_operand (operands[1], DFmode))"
8070  {
8071    switch (which_alternative)
8072    {
8073    case 0:
8074      if (TARGET_FMOVD)
8075	return "fmov	%1,%0";
8076      else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
8077	return         "fmov	%R1,%R0"	"\n"
8078	       "	fmov	%S1,%S0";
8079      else
8080	return         "fmov	%S1,%S0"	"\n"
8081	       "	fmov	%R1,%R0";
8082    case 3:
8083    case 4:
8084      return "fmov.d	%1,%0";
8085    default:
8086      return "#";
8087    }
8088  }
8089  [(set_attr_alternative "length"
8090     [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
8091      (const_int 4)
8092      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
8093      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
8094      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
8095      (const_int 4)
8096      (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
8097      ;; We can't use 4-byte push/pop on SHcompact, so we have to
8098      ;; increment or decrement r15 explicitly.
8099      (if_then_else
8100       (match_test "TARGET_SHCOMPACT")
8101       (const_int 10) (const_int 8))
8102      (if_then_else
8103       (match_test "TARGET_SHCOMPACT")
8104       (const_int 10) (const_int 8))])
8105   (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
8106   (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
8107   (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8108					   (const_string "double")
8109					   (const_string "none")))])
8110
8111;; Moving DFmode between fp/general registers through memory
8112;; (the top of the stack) is faster than moving through fpul even for
8113;; little endian.  Because the type of an instruction is important for its
8114;; scheduling,  it is beneficial to split these operations, rather than
8115;; emitting them in one single chunk, even if this will expose a stack
8116;; use that will prevent scheduling of other stack accesses beyond this
8117;; instruction.
8118(define_split
8119  [(set (match_operand:DF 0 "register_operand")
8120	(match_operand:DF 1 "register_operand"))
8121   (use (reg:SI FPSCR_MODES_REG))
8122   (clobber (match_scratch:SI 2))]
8123  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
8124   && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
8125  [(const_int 0)]
8126{
8127  rtx insn, tos;
8128
8129  if (TARGET_SH5 && true_regnum (operands[1]) < 16)
8130    {
8131      emit_move_insn (stack_pointer_rtx,
8132		      plus_constant (Pmode, stack_pointer_rtx, -8));
8133      tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
8134    }
8135  else
8136    tos = gen_tmp_stack_mem (DFmode,
8137			     gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
8138  insn = emit_insn (gen_movdf_i4 (tos, operands[1]));
8139  if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
8140    add_reg_note (insn, REG_INC, stack_pointer_rtx);
8141  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
8142    tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
8143  else
8144    tos = gen_tmp_stack_mem (DFmode,
8145			     gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
8146  insn = emit_insn (gen_movdf_i4 (operands[0], tos));
8147  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
8148    emit_move_insn (stack_pointer_rtx,
8149		    plus_constant (Pmode, stack_pointer_rtx, 8));
8150  else
8151    add_reg_note (insn, REG_INC, stack_pointer_rtx);
8152  DONE;
8153})
8154
8155;; local-alloc sometimes allocates scratch registers even when not required,
8156;; so we must be prepared to handle these.
8157
8158;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
8159(define_split
8160  [(set (match_operand:DF 0 "general_movdst_operand" "")
8161	(match_operand:DF 1 "general_movsrc_operand"  ""))
8162   (use (reg:SI FPSCR_MODES_REG))
8163   (clobber (match_scratch:SI 2))]
8164  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
8165   && reload_completed
8166   && true_regnum (operands[0]) < 16
8167   && true_regnum (operands[1]) < 16"
8168  [(set (match_dup 0) (match_dup 1))]
8169{
8170  /* If this was a reg <-> mem operation with base + index reg addressing,
8171     we have to handle this in a special way.  */
8172  rtx mem = operands[0];
8173  int store_p = 1;
8174  if (! memory_operand (mem, DFmode))
8175    {
8176      mem = operands[1];
8177      store_p = 0;
8178    }
8179  if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
8180    mem = SUBREG_REG (mem);
8181  if (MEM_P (mem))
8182    {
8183      rtx addr = XEXP (mem, 0);
8184      if (GET_CODE (addr) == PLUS
8185	  && REG_P (XEXP (addr, 0))
8186	  && REG_P (XEXP (addr, 1)))
8187	{
8188	  int offset;
8189	  rtx reg0 = gen_rtx_REG (Pmode, 0);
8190	  rtx regop = operands[store_p], word0 ,word1;
8191
8192	  if (GET_CODE (regop) == SUBREG)
8193	    alter_subreg (&regop, true);
8194	  if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
8195	    offset = 2;
8196	  else
8197	    offset = 4;
8198	  mem = copy_rtx (mem);
8199	  PUT_MODE (mem, SImode);
8200	  word0 = gen_rtx_SUBREG (SImode, regop, 0);
8201	  alter_subreg (&word0, true);
8202	  word1 = gen_rtx_SUBREG (SImode, regop, 4);
8203	  alter_subreg (&word1, true);
8204	  if (store_p || ! refers_to_regno_p (REGNO (word0), addr))
8205	    {
8206	      emit_insn (store_p
8207			 ? gen_movsi_ie (mem, word0)
8208			 : gen_movsi_ie (word0, mem));
8209	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
8210	      mem = copy_rtx (mem);
8211	      emit_insn (store_p
8212			 ? gen_movsi_ie (mem, word1)
8213			 : gen_movsi_ie (word1, mem));
8214	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
8215	    }
8216	  else
8217	    {
8218	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
8219	      emit_insn (gen_movsi_ie (word1, mem));
8220	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
8221	      mem = copy_rtx (mem);
8222	      emit_insn (gen_movsi_ie (word0, mem));
8223	    }
8224	  DONE;
8225	}
8226    }
8227})
8228
8229;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
8230(define_split
8231  [(set (match_operand:DF 0 "register_operand" "")
8232	(match_operand:DF 1 "memory_operand"  ""))
8233   (use (reg:SI FPSCR_MODES_REG))
8234   (clobber (reg:SI R0_REG))]
8235  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
8236  [(parallel [(set (match_dup 0) (match_dup 1))
8237	      (use (reg:SI FPSCR_MODES_REG))
8238	      (clobber (scratch:SI))])]
8239  "")
8240
8241(define_expand "reload_indf__frn"
8242  [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
8243		   (match_operand:DF 1 "immediate_operand" "FQ"))
8244	      (use (reg:SI FPSCR_MODES_REG))
8245	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8246  "TARGET_SH1"
8247  "")
8248
8249(define_expand "reload_outdf__RnFRm"
8250  [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
8251		   (match_operand:DF 1 "register_operand" "af,r"))
8252	      (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
8253  "TARGET_SH1"
8254  "")
8255
8256;; Simplify no-op moves.
8257(define_split
8258  [(set (match_operand:SF 0 "register_operand" "")
8259	(match_operand:SF 1 "register_operand" ""))
8260   (use (reg:SI FPSCR_MODES_REG))
8261   (clobber (match_scratch:SI 2))]
8262  "TARGET_SH2E && reload_completed
8263   && true_regnum (operands[0]) == true_regnum (operands[1])"
8264  [(set (match_dup 0) (match_dup 0))]
8265  "")
8266
8267;; fmovd substitute post-reload splits
8268(define_split
8269  [(set (match_operand:DF 0 "register_operand" "")
8270	(match_operand:DF 1 "register_operand" ""))
8271   (use (reg:SI FPSCR_MODES_REG))
8272   (clobber (match_scratch:SI 2))]
8273  "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
8274   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
8275   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
8276  [(const_int 0)]
8277{
8278  int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
8279  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
8280			   gen_rtx_REG (SFmode, src)));
8281  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
8282			   gen_rtx_REG (SFmode, src + 1)));
8283  DONE;
8284})
8285
8286(define_split
8287  [(set (match_operand:DF 0 "register_operand" "")
8288	(mem:DF (match_operand:SI 1 "register_operand" "")))
8289   (use (reg:SI FPSCR_MODES_REG))
8290   (clobber (match_scratch:SI 2))]
8291  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
8292   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
8293   && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
8294  [(const_int 0)]
8295{
8296  int regno = true_regnum (operands[0]);
8297  rtx insn;
8298  rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
8299  rtx mem2
8300    = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
8301  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
8302					       regno + SH_REG_MSW_OFFSET),
8303				  mem2));
8304  add_reg_note (insn, REG_INC, operands[1]);
8305  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
8306					       regno + SH_REG_LSW_OFFSET),
8307				  change_address (mem, SFmode, NULL_RTX)));
8308  DONE;
8309})
8310
8311(define_split
8312  [(set (match_operand:DF 0 "register_operand" "")
8313	(match_operand:DF 1 "memory_operand" ""))
8314   (use (reg:SI FPSCR_MODES_REG))
8315   (clobber (match_scratch:SI 2))]
8316  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
8317   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
8318  [(const_int 0)]
8319{
8320  int regno = true_regnum (operands[0]);
8321  rtx addr, insn;
8322  rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
8323  rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
8324  rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
8325
8326  operands[1] = copy_rtx (mem2);
8327  addr = XEXP (mem2, 0);
8328
8329  switch (GET_CODE (addr))
8330    {
8331    case REG:
8332      /* This is complicated.  If the register is an arithmetic register
8333	 we can just fall through to the REG+DISP case below.  Otherwise
8334	 we have to use a combination of POST_INC and REG addressing...  */
8335      if (! arith_reg_operand (operands[1], SFmode))
8336	{
8337	  XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
8338	  insn = emit_insn (gen_movsf_ie (reg0, mem2));
8339	  add_reg_note (insn, REG_INC, XEXP (addr, 0));
8340	  
8341	  emit_insn (gen_movsf_ie (reg1, operands[1]));
8342
8343	  /* If we have modified the stack pointer, the value that we have
8344	     read with post-increment might be modified by an interrupt,
8345	     so write it back.  */
8346	  if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
8347	    emit_insn (gen_push_e (reg0));
8348	  else
8349	    emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0),
8350				   GEN_INT (-4)));
8351	  break;
8352	}
8353      /* Fall through.  */
8354
8355    case PLUS:
8356      emit_insn (gen_movsf_ie (reg0, operands[1]));
8357      operands[1] = copy_rtx (operands[1]);
8358      XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
8359      emit_insn (gen_movsf_ie (reg1, operands[1]));
8360      break;
8361
8362    case POST_INC:
8363      insn = emit_insn (gen_movsf_ie (reg0, operands[1]));
8364      add_reg_note (insn, REG_INC, XEXP (addr, 0));
8365
8366      insn = emit_insn (gen_movsf_ie (reg1, operands[1]));
8367      add_reg_note (insn, REG_INC, XEXP (addr, 0));
8368      break;
8369
8370    default:
8371      debug_rtx (addr);
8372      gcc_unreachable ();
8373    }
8374
8375  DONE;
8376})
8377
8378(define_split
8379  [(set (match_operand:DF 0 "memory_operand" "")
8380	(match_operand:DF 1 "register_operand" ""))
8381   (use (reg:SI FPSCR_MODES_REG))
8382   (clobber (match_scratch:SI 2))]
8383  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
8384   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
8385  [(const_int 0)]
8386{
8387  int regno = true_regnum (operands[1]);
8388  rtx insn, addr;
8389  rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
8390  rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
8391
8392  operands[0] = copy_rtx (operands[0]);
8393  PUT_MODE (operands[0], SFmode);
8394  addr = XEXP (operands[0], 0);
8395
8396  switch (GET_CODE (addr))
8397    {
8398    case REG:
8399      /* This is complicated.  If the register is an arithmetic register
8400	 we can just fall through to the REG+DISP case below.  Otherwise
8401	 we have to use a combination of REG and PRE_DEC addressing...  */
8402      if (! arith_reg_operand (operands[0], SFmode))
8403	{
8404	  emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
8405	  emit_insn (gen_movsf_ie (operands[0], reg1));
8406
8407	  operands[0] = copy_rtx (operands[0]);
8408	  XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
8409	  
8410	  insn = emit_insn (gen_movsf_ie (operands[0], reg0));
8411	  add_reg_note (insn, REG_INC, XEXP (addr, 0));
8412	  break;
8413	}
8414      /* Fall through.  */
8415
8416    case PLUS:
8417      /* Since REG+DISP addressing has already been decided upon by gcc
8418	 we can rely upon it having chosen an arithmetic register as the
8419	 register component of the address.  Just emit the lower numbered
8420	 register first, to the lower address, then the higher numbered
8421	 register to the higher address.  */
8422      emit_insn (gen_movsf_ie (operands[0], reg0));
8423
8424      operands[0] = copy_rtx (operands[0]);
8425      XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
8426
8427      emit_insn (gen_movsf_ie (operands[0], reg1));
8428      break;
8429
8430    case PRE_DEC:
8431      /* This is easy.  Output the word to go to the higher address
8432         first (ie the word in the higher numbered register) then the
8433	 word to go to the lower address.  */
8434
8435      insn = emit_insn (gen_movsf_ie (operands[0], reg1));
8436      add_reg_note (insn, REG_INC, XEXP (addr, 0));
8437
8438      insn = emit_insn (gen_movsf_ie (operands[0], reg0));
8439      add_reg_note (insn, REG_INC, XEXP (addr, 0));
8440      break;
8441
8442    default:
8443      /* FAIL; */
8444      debug_rtx (addr);
8445      gcc_unreachable ();
8446    }
8447
8448  DONE;
8449})
8450
8451;; If the output is a register and the input is memory or a register, we have
8452;; to be careful and see which word needs to be loaded first.
8453(define_split
8454  [(set (match_operand:DF 0 "general_movdst_operand" "")
8455	(match_operand:DF 1 "general_movsrc_operand" ""))]
8456  "TARGET_SH1 && reload_completed"
8457  [(set (match_dup 2) (match_dup 3))
8458   (set (match_dup 4) (match_dup 5))]
8459{
8460  int regno;
8461
8462  if ((MEM_P (operands[0])
8463       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
8464      || (MEM_P (operands[1])
8465	  && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
8466    FAIL;
8467
8468  switch (GET_CODE (operands[0]))
8469    {
8470    case REG:
8471      regno = REGNO (operands[0]);
8472      break;
8473    case SUBREG:
8474      regno = subreg_regno (operands[0]);
8475      break;
8476    case MEM:
8477      regno = -1;
8478      break;
8479    default:
8480      gcc_unreachable ();
8481    }
8482
8483  if (regno == -1 || ! refers_to_regno_p (regno, operands[1]))
8484    {
8485      operands[2] = operand_subword (operands[0], 0, 0, DFmode);
8486      operands[3] = operand_subword (operands[1], 0, 0, DFmode);
8487      operands[4] = operand_subword (operands[0], 1, 0, DFmode);
8488      operands[5] = operand_subword (operands[1], 1, 0, DFmode);
8489    }
8490  else
8491    {
8492      operands[2] = operand_subword (operands[0], 1, 0, DFmode);
8493      operands[3] = operand_subword (operands[1], 1, 0, DFmode);
8494      operands[4] = operand_subword (operands[0], 0, 0, DFmode);
8495      operands[5] = operand_subword (operands[1], 0, 0, DFmode);
8496    }
8497
8498  if (operands[2] == 0 || operands[3] == 0
8499      || operands[4] == 0 || operands[5] == 0)
8500    FAIL;
8501})
8502
8503(define_expand "movdf"
8504  [(set (match_operand:DF 0 "general_movdst_operand" "")
8505	(match_operand:DF 1 "general_movsrc_operand" ""))]
8506  ""
8507{
8508  prepare_move_operands (operands, DFmode);
8509  if (TARGET_SHMEDIA)
8510    {
8511      if (TARGET_SHMEDIA_FPU)
8512	emit_insn (gen_movdf_media (operands[0], operands[1]));
8513      else
8514	emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
8515      DONE;
8516    }
8517  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8518    {
8519      emit_insn (gen_movdf_i4 (operands[0], operands[1]));
8520      DONE;
8521    }
8522})
8523
8524;;This is incompatible with the way gcc uses subregs.
8525;;(define_insn "movv2sf_i"
8526;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
8527;;	(match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
8528;;  "TARGET_SHMEDIA_FPU
8529;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
8530;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
8531;;  "@
8532;;	#
8533;;	fld%M1.p	%m1, %0
8534;;	fst%M0.p	%m0, %1"
8535;;  [(set_attr "type" "*,fload_media,fstore_media")])
8536(define_insn_and_split "movv2sf_i"
8537  [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8538	(match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8539  "TARGET_SHMEDIA_FPU"
8540  "#"
8541  "TARGET_SHMEDIA_FPU && reload_completed"
8542  [(set (match_dup 0) (match_dup 1))]
8543{
8544  operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
8545  operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
8546})
8547
8548(define_expand "movv2sf"
8549  [(set (match_operand:V2SF 0 "general_movdst_operand" "")
8550	(match_operand:V2SF 1 "nonimmediate_operand" ""))]
8551  "TARGET_SHMEDIA_FPU"
8552{
8553  prepare_move_operands (operands, V2SFmode);
8554})
8555
8556(define_expand "addv2sf3"
8557  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8558   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8559   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8560  "TARGET_SHMEDIA_FPU"
8561{
8562  sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
8563  DONE;
8564})
8565
8566(define_expand "subv2sf3"
8567  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8568   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8569   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8570  "TARGET_SHMEDIA_FPU"
8571{
8572  sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
8573  DONE;
8574})
8575
8576(define_expand "mulv2sf3"
8577  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8578   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8579   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8580  "TARGET_SHMEDIA_FPU"
8581{
8582  sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
8583  DONE;
8584})
8585
8586(define_expand "divv2sf3"
8587  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8588   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8589   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8590  "TARGET_SHMEDIA_FPU"
8591{
8592  sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
8593  DONE;
8594})
8595
8596(define_insn_and_split "*movv4sf_i"
8597  [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8598	(match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8599  "TARGET_SHMEDIA_FPU"
8600  "#"
8601  "&& reload_completed"
8602  [(const_int 0)]
8603{
8604  for (int i = 0; i < 4/2; i++)
8605    {
8606      rtx x, y;
8607
8608      if (MEM_P (operands[0]))
8609	x = adjust_address (operands[0], V2SFmode,
8610			    i * GET_MODE_SIZE (V2SFmode));
8611      else
8612	x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
8613
8614      if (MEM_P (operands[1]))
8615	y = adjust_address (operands[1], V2SFmode,
8616			    i * GET_MODE_SIZE (V2SFmode));
8617      else
8618	y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
8619
8620      emit_insn (gen_movv2sf_i (x, y));
8621    }
8622
8623  DONE;
8624}
8625  [(set_attr "length" "8")])
8626
8627(define_expand "movv4sf"
8628  [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
8629	(match_operand:V4SF 1 "general_operand" ""))]
8630  "TARGET_SHMEDIA_FPU"
8631{
8632  prepare_move_operands (operands, V4SFmode);
8633})
8634
8635(define_insn_and_split "*movv16sf_i"
8636  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8637	(match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8638  "TARGET_SHMEDIA_FPU"
8639  "#"
8640  "&& reload_completed"
8641  [(const_int 0)]
8642{
8643  for (int i = 0; i < 16/2; i++)
8644    {
8645      rtx x, y;
8646
8647      if (MEM_P (operands[0]))
8648	x = adjust_address (operands[0], V2SFmode,
8649			    i * GET_MODE_SIZE (V2SFmode));
8650      else
8651	{
8652	  x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
8653	  alter_subreg (&x, true);
8654	}
8655
8656      if (MEM_P (operands[1]))
8657	y = adjust_address (operands[1], V2SFmode,
8658			    i * GET_MODE_SIZE (V2SFmode));
8659      else
8660	{
8661	  y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
8662	  alter_subreg (&y, true);
8663	}
8664
8665      emit_insn (gen_movv2sf_i (x, y));
8666    }
8667
8668  DONE;
8669}
8670  [(set_attr "length" "32")])
8671
8672(define_expand "movv16sf"
8673  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8674	(match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8675  "TARGET_SHMEDIA_FPU"
8676{
8677  prepare_move_operands (operands, V16SFmode);
8678})
8679
8680(define_insn "movsf_media"
8681  [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8682	(match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8683  "TARGET_SHMEDIA_FPU
8684   && (register_operand (operands[0], SFmode)
8685       || sh_register_operand (operands[1], SFmode))"
8686  "@
8687	fmov.s	%1, %0
8688	fmov.ls	%N1, %0
8689	fmov.sl	%1, %0
8690	add.l	%1, r63, %0
8691	#
8692	fld%M1.s	%m1, %0
8693	fst%M0.s	%m0, %1
8694	ld%M1.l	%m1, %0
8695	st%M0.l	%m0, %N1"
8696  [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8697   (set (attr "highpart")
8698	(cond [(match_test "sh_contains_memref_p (insn)")
8699	       (const_string "user")]
8700	      (const_string "ignore")))])
8701
8702(define_insn "movsf_media_nofpu"
8703  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
8704	(match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8705  "TARGET_SHMEDIA
8706   && (register_operand (operands[0], SFmode)
8707       || sh_register_operand (operands[1], SFmode))"
8708  "@
8709	add.l	%1, r63, %0
8710	#
8711	ld%M1.l	%m1, %0
8712	st%M0.l	%m0, %N1"
8713  [(set_attr "type" "arith_media,*,load_media,store_media")
8714   (set (attr "highpart")
8715	(cond [(match_test "sh_contains_memref_p (insn)")
8716	       (const_string "user")]
8717	      (const_string "ignore")))])
8718
8719(define_split
8720  [(set (match_operand:SF 0 "arith_reg_dest" "")
8721	(match_operand:SF 1 "immediate_operand" ""))]
8722  "TARGET_SHMEDIA && reload_completed
8723   && ! FP_REGISTER_P (true_regnum (operands[0]))"
8724  [(set (match_dup 3) (match_dup 2))]
8725{
8726  long values;
8727  REAL_VALUE_TYPE value;
8728
8729  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
8730  REAL_VALUE_TO_TARGET_SINGLE (value, values);
8731  operands[2] = GEN_INT (values);
8732
8733  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8734})
8735
8736(define_insn "movsf_i"
8737  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
8738	(match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
8739  "TARGET_SH1
8740   && (! TARGET_SH2E
8741       /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
8742       || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8743       || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8744   && (arith_reg_operand (operands[0], SFmode)
8745       || arith_reg_operand (operands[1], SFmode))"
8746  "@
8747	mov	%1,%0
8748	mov	#0,%0
8749	mov.l	%1,%0
8750	mov.l	%1,%0
8751	mov.l	%1,%0
8752	lds	%1,%0
8753	sts	%1,%0"
8754  [(set_attr "type" "move,move,pcload,load,store,move,move")])
8755
8756;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8757;; update_flow_info would not know where to put REG_EQUAL notes
8758;; when the destination changes mode.
8759(define_insn "movsf_ie"
8760  [(set (match_operand:SF 0 "general_movdst_operand"
8761	 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8762	(match_operand:SF 1 "general_movsrc_operand"
8763	  "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8764   (use (reg:SI FPSCR_MODES_REG))
8765   (clobber (match_scratch:SI 2 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
8766  "TARGET_SH2E
8767   && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode)
8768       || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode)
8769       || arith_reg_operand (operands[2], SImode))"
8770  "@
8771	fmov	%1,%0
8772	mov	%1,%0
8773	fldi0	%0
8774	fldi1	%0
8775	#
8776	fmov.s	%1,%0
8777	fmov.s	%1,%0
8778	mov.l	%1,%0
8779	mov.l	%1,%0
8780	mov.l	%1,%0
8781	fsts	fpul,%0
8782	flds	%1,fpul
8783	lds.l	%1,%0
8784	#
8785	sts	%1,%0
8786	lds	%1,%0
8787	sts.l	%1,%0
8788	lds.l	%1,%0
8789	! move optimized away"
8790  [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8791		     store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8792   (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8793   (set_attr_alternative "length"
8794     [(const_int 2)
8795      (const_int 2)
8796      (const_int 2)
8797      (const_int 2)
8798      (const_int 4)
8799      (if_then_else
8800	(match_test "TARGET_SH2A")
8801	(const_int 4) (const_int 2))
8802      (if_then_else
8803	(match_test "TARGET_SH2A")
8804	(const_int 4) (const_int 2))
8805      (const_int 2)
8806      (if_then_else
8807	(match_test "TARGET_SH2A")
8808	(const_int 4) (const_int 2))
8809      (if_then_else
8810	(match_test "TARGET_SH2A")
8811	(const_int 4) (const_int 2))
8812      (const_int 2)
8813      (const_int 2)
8814      (const_int 2)
8815      (const_int 4)
8816      (const_int 2)
8817      (const_int 2)
8818      (const_int 2)
8819      (const_int 2)
8820      (const_int 0)])
8821  (set_attr_alternative "fp_mode"
8822     [(if_then_else (eq_attr "fmovd" "yes")
8823		    (const_string "single") (const_string "none"))
8824      (const_string "none")
8825      (const_string "single")
8826      (const_string "single")
8827      (const_string "none")
8828      (if_then_else (eq_attr "fmovd" "yes")
8829		    (const_string "single") (const_string "none"))
8830      (if_then_else (eq_attr "fmovd" "yes")
8831		    (const_string "single") (const_string "none"))
8832      (const_string "none")
8833      (const_string "none")
8834      (const_string "none")
8835      (const_string "none")
8836      (const_string "none")
8837      (const_string "none")
8838      (const_string "none")
8839      (const_string "none")
8840      (const_string "none")
8841      (const_string "none")
8842      (const_string "none")
8843      (const_string "none")])])
8844
8845(define_insn_and_split "movsf_ie_ra"
8846  [(set (match_operand:SF 0 "general_movdst_operand"
8847	 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8848	(match_operand:SF 1 "general_movsrc_operand"
8849	  "f,r,G,H,FQ,m,f,FQ,m,r,y,f,>,fr,y,r,y,>,y"))
8850   (use (reg:SI FPSCR_MODES_REG))
8851   (clobber (match_scratch:SF 2 "=r,r,X,X,&z,r,r,X,r,r,r,r,r,y,r,r,r,r,r"))
8852   (const_int 0)]
8853  "TARGET_SH2E
8854   && (arith_reg_operand (operands[0], SFmode)
8855       || fpul_operand (operands[0], SFmode)
8856       || arith_reg_operand (operands[1], SFmode)
8857       || fpul_operand (operands[1], SFmode))"
8858  "@
8859	fmov	%1,%0
8860	mov	%1,%0
8861	fldi0	%0
8862	fldi1	%0
8863	#
8864	fmov.s	%1,%0
8865	fmov.s	%1,%0
8866	mov.l	%1,%0
8867	mov.l	%1,%0
8868	mov.l	%1,%0
8869	fsts	fpul,%0
8870	flds	%1,fpul
8871	lds.l	%1,%0
8872	#
8873	sts	%1,%0
8874	lds	%1,%0
8875	sts.l	%1,%0
8876	lds.l	%1,%0
8877	! move optimized away"
8878  "reload_completed
8879   && sh_movsf_ie_ra_split_p (operands[0], operands[1], operands[2])"
8880  [(const_int 0)]
8881{
8882  if (! rtx_equal_p (operands[0], operands[1]))
8883    {
8884      emit_insn (gen_movsf_ie (operands[2], operands[1]));
8885      emit_insn (gen_movsf_ie (operands[0], operands[2]));
8886    }
8887}
8888  [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8889		     store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8890   (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8891   (set_attr_alternative "length"
8892     [(const_int 2)
8893      (const_int 2)
8894      (const_int 2)
8895      (const_int 2)
8896      (const_int 4)
8897      (if_then_else
8898	(match_test "TARGET_SH2A")
8899	(const_int 4) (const_int 2))
8900      (if_then_else
8901	(match_test "TARGET_SH2A")
8902	(const_int 4) (const_int 2))
8903      (const_int 2)
8904      (if_then_else
8905	(match_test "TARGET_SH2A")
8906	(const_int 4) (const_int 2))
8907      (if_then_else
8908	(match_test "TARGET_SH2A")
8909	(const_int 4) (const_int 2))
8910      (const_int 2)
8911      (const_int 2)
8912      (const_int 2)
8913      (const_int 4)
8914      (const_int 2)
8915      (const_int 2)
8916      (const_int 2)
8917      (const_int 2)
8918      (const_int 0)])
8919  (set_attr_alternative "fp_mode"
8920     [(if_then_else (eq_attr "fmovd" "yes")
8921		    (const_string "single") (const_string "none"))
8922      (const_string "none")
8923      (const_string "single")
8924      (const_string "single")
8925      (const_string "none")
8926      (if_then_else (eq_attr "fmovd" "yes")
8927		    (const_string "single") (const_string "none"))
8928      (if_then_else (eq_attr "fmovd" "yes")
8929		    (const_string "single") (const_string "none"))
8930      (const_string "none")
8931      (const_string "none")
8932      (const_string "none")
8933      (const_string "none")
8934      (const_string "none")
8935      (const_string "none")
8936      (const_string "none")
8937      (const_string "none")
8938      (const_string "none")
8939      (const_string "none")
8940      (const_string "none")
8941      (const_string "none")])])
8942
8943(define_split
8944  [(set (match_operand:SF 0 "register_operand" "")
8945	(match_operand:SF 1 "register_operand" ""))
8946   (use (reg:SI FPSCR_MODES_REG))
8947   (clobber (reg:SI FPUL_REG))]
8948  "TARGET_SH1"
8949  [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
8950	      (use (reg:SI FPSCR_MODES_REG))
8951	      (clobber (scratch:SI))])
8952   (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
8953	      (use (reg:SI FPSCR_MODES_REG))
8954	      (clobber (scratch:SI))])]
8955  "")
8956
8957(define_expand "movsf"
8958  [(set (match_operand:SF 0 "general_movdst_operand" "")
8959        (match_operand:SF 1 "general_movsrc_operand" ""))]
8960  ""
8961{
8962  prepare_move_operands (operands, SFmode);
8963  if (TARGET_SHMEDIA)
8964    {
8965      if (TARGET_SHMEDIA_FPU)
8966	emit_insn (gen_movsf_media (operands[0], operands[1]));
8967      else
8968	emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8969      DONE;
8970    }
8971  if (TARGET_SH2E)
8972    {
8973      if (lra_in_progress)
8974	{
8975	  if (GET_CODE (operands[0]) == SCRATCH)
8976	    DONE;
8977	  emit_insn (gen_movsf_ie_ra (operands[0], operands[1]));
8978	  DONE;
8979	}
8980
8981      emit_insn (gen_movsf_ie (operands[0], operands[1]));
8982      DONE;
8983    }
8984})
8985
8986(define_insn "mov_nop"
8987  [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
8988  "TARGET_SH2E"
8989  ""
8990  [(set_attr "length" "0")
8991   (set_attr "type" "nil")])
8992
8993(define_expand "reload_insf__frn"
8994  [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
8995		   (match_operand:SF 1 "immediate_operand" "FQ"))
8996	      (use (reg:SI FPSCR_MODES_REG))
8997	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8998  "TARGET_SH1"
8999  "")
9000
9001(define_expand "reload_insi__i_fpul"
9002  [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
9003		   (match_operand:SI 1 "immediate_operand" "i"))
9004	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
9005  "TARGET_SH1"
9006  "")
9007
9008(define_expand "ptabs"
9009  [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
9010  "TARGET_SHMEDIA"
9011{
9012  if (!TARGET_PT_FIXED)
9013    {
9014      rtx eq = operands[1];
9015
9016      /* ??? For canonical RTL we really should remove any CONST from EQ
9017	 before wrapping it in the AND, and finally wrap the EQ into a
9018	 const if is constant.  However, for reload we must expose the
9019	 input register or symbolic constant, and we can't have
9020	 different insn structures outside of the operands for different
9021	 alternatives of the same pattern.  */
9022      eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
9023		       GEN_INT (3));
9024      operands[1]
9025	= (gen_rtx_IF_THEN_ELSE
9026	    (PDImode,
9027	     eq,
9028	     gen_rtx_MEM (PDImode, operands[1]),
9029	     gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
9030			    PDImode, operands[1])));
9031    }
9032})
9033
9034;; expanded by ptabs expander.
9035(define_insn "*extendsipdi_media"
9036  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
9037	(if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
9038							  "r,Csy")
9039				      (const_int 3))
9040			      (const_int 3))
9041			  (mem:PDI (match_dup 1))
9042			  (sign_extend:PDI (match_dup 1))))]
9043  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
9044  "@
9045	ptabs	%1, %0
9046	pt	%1, %0"
9047  [(set_attr "type"   "ptabs_media,pt_media")
9048   (set_attr "length" "4,*")])
9049
9050(define_insn "*truncdipdi_media"
9051  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
9052	(if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
9053							  "r,Csy")
9054				      (const_int 3))
9055			      (const_int 3))
9056			  (mem:PDI (match_dup 1))
9057			  (truncate:PDI (match_dup 1))))]
9058  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
9059  "@
9060	ptabs	%1, %0
9061	pt	%1, %0"
9062  [(set_attr "type"   "ptabs_media,pt_media")
9063   (set_attr "length" "4,*")])
9064
9065(define_insn "*movsi_y"
9066  [(set (match_operand:SI 0 "register_operand" "=y,y")
9067	(match_operand:SI 1 "immediate_operand" "Qi,I08"))
9068   (clobber (match_scratch:SI 2 "=&z,r"))]
9069  "TARGET_SH2E
9070   && (reload_in_progress || reload_completed)"
9071  "#"
9072  [(set_attr "length" "4")
9073   (set_attr "type" "pcload,move")])
9074
9075(define_split
9076  [(set (match_operand:SI 0 "register_operand" "")
9077	(match_operand:SI 1 "immediate_operand" ""))
9078   (clobber (match_operand:SI 2 "register_operand" ""))]
9079  "TARGET_SH1"
9080  [(set (match_dup 2) (match_dup 1))
9081   (set (match_dup 0) (match_dup 2))]
9082  "")
9083
9084;; ------------------------------------------------------------------------
9085;; Define the real conditional branch instructions.
9086;; ------------------------------------------------------------------------
9087
9088(define_expand "branch_true"
9089  [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
9090			   (label_ref (match_operand 0))
9091			   (pc)))]
9092  "TARGET_SH1")
9093
9094(define_expand "branch_false"
9095  [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
9096			   (label_ref (match_operand 0))
9097			   (pc)))]
9098  "TARGET_SH1")
9099
9100(define_insn_and_split "*cbranch_t"
9101  [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
9102			   (label_ref (match_operand 0))
9103			   (pc)))]
9104  "TARGET_SH1"
9105{
9106  return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
9107}
9108  "&& 1"
9109  [(const_int 0)]
9110{
9111  /* Try to canonicalize the branch condition if it is not one of:
9112	(ne (reg:SI T_REG) (const_int 0))
9113	(eq (reg:SI T_REG) (const_int 0))
9114
9115     Instead of splitting out a new insn, we modify the current insn's
9116     operands as needed.  This preserves things such as REG_DEAD notes.  */
9117
9118  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9119      && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG
9120      && XEXP (operands[1], 1) == const0_rtx)
9121    DONE;
9122
9123  int branch_cond = sh_eval_treg_value (operands[1]);
9124  rtx new_cond_rtx = NULL_RTX;
9125
9126  if (branch_cond == 0)
9127    new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx);
9128  else if (branch_cond == 1)
9129    new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx);
9130
9131  if (new_cond_rtx != NULL_RTX)
9132    validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0),
9133		     new_cond_rtx, false);
9134  DONE;
9135}
9136  [(set_attr "type" "cbranch")])
9137
9138;; Patterns to prevent reorg from re-combining a condbranch with a branch
9139;; which destination is too far away.
9140;; The const_int_operand is distinct for each branch target; it avoids
9141;; unwanted matches with redundant_insn.
9142(define_insn "block_branch_redirect"
9143  [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
9144  "TARGET_SH1"
9145  ""
9146  [(set_attr "length" "0")])
9147
9148;; This one has the additional purpose to record a possible scratch register
9149;; for the following branch.
9150;; ??? Unfortunately, just setting the scratch register is not good enough,
9151;; because the insn then might be deemed dead and deleted.  And we can't
9152;; make the use in the jump insn explicit because that would disable
9153;; delay slot scheduling from the target.
9154(define_insn "indirect_jump_scratch"
9155  [(set (match_operand:SI 0 "register_operand" "=r")
9156	(unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
9157   (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
9158  "TARGET_SH1"
9159  ""
9160  [(set_attr "length" "0")])
9161
9162;; This one is used to preemt an insn from beyond the bra / braf / jmp
9163;; being pulled into the delay slot of a condbranch that has been made to
9164;; jump around the unconditional jump because it was out of range.
9165(define_insn "stuff_delay_slot"
9166  [(set (pc)
9167	(unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
9168		 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
9169  "TARGET_SH1"
9170  ""
9171  [(set_attr "length" "0")
9172   (set_attr "cond_delay_slot" "yes")])
9173
9174;; Conditional branch insns
9175
9176(define_expand "cbranchint4_media"
9177  [(set (pc)
9178	(if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
9179		       [(match_operand 1 "" "")
9180			(match_operand 2 "" "")])
9181		      (match_operand 3 "" "")
9182		      (pc)))]
9183  "TARGET_SHMEDIA"
9184{
9185  machine_mode mode = GET_MODE (operands[1]);
9186  if (mode == VOIDmode)
9187    mode = GET_MODE (operands[2]);
9188  if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
9189    {
9190      operands[1] = force_reg (mode, operands[1]);
9191      if (CONSTANT_P (operands[2])
9192          && (! satisfies_constraint_I06 (operands[2])))
9193        operands[2] = force_reg (mode, operands[2]);
9194    }
9195  else
9196    {
9197      if (operands[1] != const0_rtx)
9198        operands[1] = force_reg (mode, operands[1]);
9199      if (operands[2] != const0_rtx)
9200        operands[2] = force_reg (mode, operands[2]);
9201    }
9202  switch (GET_CODE (operands[0]))
9203    {
9204    case LEU:
9205    case LE:
9206    case LTU:
9207    case LT:
9208      operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
9209				    VOIDmode, operands[2], operands[1]);
9210      operands[1] = XEXP (operands[0], 0);
9211      operands[2] = XEXP (operands[0], 1);
9212      break;
9213    default:
9214      operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
9215				    VOIDmode, operands[1], operands[2]);
9216      break;
9217    }
9218  operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
9219})
9220
9221(define_expand "cbranchfp4_media"
9222  [(set (pc)
9223	(if_then_else (match_operator 0 "sh_float_comparison_operator"
9224		       [(match_operand 1 "" "")
9225			(match_operand 2 "" "")])
9226		      (match_operand 3 "" "")
9227		      (pc)))]
9228  "TARGET_SHMEDIA"
9229{
9230  rtx tmp = gen_reg_rtx (SImode);
9231  rtx cmp;
9232  if (GET_CODE (operands[0]) == NE)
9233    cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
9234  else
9235    cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
9236			  operands[1], operands[2]);
9237
9238  emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
9239
9240  if (GET_CODE (cmp) == GET_CODE (operands[0]))
9241    operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
9242  else
9243    operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
9244  operands[1] = tmp;
9245  operands[2] = const0_rtx;
9246  operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
9247})
9248
9249(define_insn "*beq_media_i"
9250  [(set (pc)
9251	(if_then_else (match_operator 3 "equality_comparison_operator"
9252			[(match_operand:DI 1 "arith_reg_operand" "r,r")
9253			 (match_operand:DI 2 "arith_operand" "r,I06")])
9254		      (match_operand 0 "target_operand" "b,b")
9255		      (pc)))]
9256  "TARGET_SHMEDIA"
9257  "@
9258	b%o3%'	%1, %2, %0%>
9259	b%o3i%'	%1, %2, %0%>"
9260  [(set_attr "type" "cbranch_media")])
9261
9262(define_insn "*beq_media_i32"
9263  [(set (pc)
9264	(if_then_else (match_operator 3 "equality_comparison_operator"
9265			[(match_operand:SI 1 "arith_reg_operand" "r,r")
9266			 (match_operand:SI 2 "arith_operand" "r,I06")])
9267		      (match_operand 0 "target_operand" "b,b")
9268		      (pc)))]
9269  "TARGET_SHMEDIA"
9270  "@
9271	b%o3%'	%1, %2, %0%>
9272	b%o3i%'	%1, %2, %0%>"
9273  [(set_attr "type" "cbranch_media")])
9274
9275(define_insn "*bgt_media_i"
9276  [(set (pc)
9277	(if_then_else (match_operator 3 "greater_comparison_operator"
9278			[(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
9279			 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
9280		      (match_operand 0 "target_operand" "b")
9281		      (pc)))]
9282  "TARGET_SHMEDIA"
9283  "b%o3%'	%N1, %N2, %0%>"
9284  [(set_attr "type" "cbranch_media")])
9285
9286(define_insn "*bgt_media_i32"
9287  [(set (pc)
9288	(if_then_else (match_operator 3 "greater_comparison_operator"
9289			[(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
9290			 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
9291		      (match_operand 0 "target_operand" "b")
9292		      (pc)))]
9293  "TARGET_SHMEDIA"
9294  "b%o3%'	%N1, %N2, %0%>"
9295  [(set_attr "type" "cbranch_media")])
9296
9297;; These are only needed to make invert_jump() happy - otherwise, jump
9298;; optimization will be silently disabled.
9299(define_insn "*blt_media_i"
9300  [(set (pc)
9301	(if_then_else (match_operator 3 "less_comparison_operator"
9302			[(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
9303			 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
9304		      (match_operand 0 "target_operand" "b")
9305		      (pc)))]
9306  "TARGET_SHMEDIA"
9307  "b%o3%'	%N2, %N1, %0%>"
9308  [(set_attr "type" "cbranch_media")])
9309
9310(define_insn "*blt_media_i32"
9311  [(set (pc)
9312	(if_then_else (match_operator 3 "less_comparison_operator"
9313			[(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
9314			 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
9315		      (match_operand 0 "target_operand" "b")
9316		      (pc)))]
9317  "TARGET_SHMEDIA"
9318  "b%o3%'	%N2, %N1, %0%>"
9319  [(set_attr "type" "cbranch_media")])
9320
9321;; combiner splitter for test-and-branch on single bit in register.  This
9322;; is endian dependent because the non-paradoxical subreg looks different
9323;; on big endian.
9324(define_split
9325  [(set (pc)
9326	(if_then_else
9327	  (match_operator 3 "equality_comparison_operator"
9328	    [(subreg:SI
9329	       (zero_extract:DI
9330		 (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0)
9331		 (const_int 1)
9332		 (match_operand 2 "const_int_operand" "")) 0)
9333	     (const_int 0)])
9334	  (match_operand 0 "target_operand" "")
9335	  (pc)))
9336   (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
9337  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
9338  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
9339   (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
9340{
9341  operands[5] = GEN_INT (31 - INTVAL (operands[2]));
9342  operands[6] = (GET_CODE (operands[3]) == EQ
9343		 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
9344		 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
9345})
9346
9347; operand 0 is the loop count pseudo register
9348; operand 1 is the label to jump to at the top of the loop
9349(define_expand "doloop_end"
9350  [(parallel [(set (pc)
9351		   (if_then_else (ne:SI (match_operand:SI 0 "" "")
9352				        (const_int 1))
9353				 (label_ref (match_operand 1 "" ""))
9354				 (pc)))
9355	      (set (match_dup 0)
9356		   (plus:SI (match_dup 0) (const_int -1)))
9357	      (clobber (reg:SI T_REG))])]
9358  "TARGET_SH2"
9359{
9360  if (GET_MODE (operands[0]) != SImode)
9361    FAIL;
9362  emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0]));
9363  DONE;
9364})
9365
9366(define_insn_and_split "doloop_end_split"
9367  [(set (pc)
9368	(if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
9369			     (const_int 1))
9370		      (label_ref (match_operand 1 "" ""))
9371		      (pc)))
9372   (set (match_operand:SI 0 "arith_reg_dest" "=r")
9373	(plus:SI (match_dup 2) (const_int -1)))
9374   (clobber (reg:SI T_REG))]
9375  "TARGET_SH2"
9376  "#"
9377  ""
9378  [(parallel [(set (reg:SI T_REG)
9379		   (eq:SI (match_dup 2) (const_int 1)))
9380	      (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
9381   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
9382			   (label_ref (match_dup 1))
9383			   (pc)))]
9384  ""
9385  [(set_attr "type" "cbranch")])
9386
9387;; ------------------------------------------------------------------------
9388;; Jump and linkage insns
9389;; ------------------------------------------------------------------------
9390
9391(define_insn "jump_compact"
9392  [(set (pc)
9393	(label_ref (match_operand 0 "" "")))]
9394  "TARGET_SH1 && !CROSSING_JUMP_P (insn)"
9395{
9396  /* The length is 16 if the delay slot is unfilled.  */
9397  if (get_attr_length(insn) > 4)
9398    return output_far_jump(insn, operands[0]);
9399  else
9400    return "bra	%l0%#";
9401}
9402  [(set_attr "type" "jump")
9403   (set_attr "needs_delay_slot" "yes")])
9404
9405(define_insn "*jump_compact_crossing"
9406  [(set (pc)
9407	(label_ref (match_operand 0 "" "")))]
9408  "TARGET_SH1
9409   && flag_reorder_blocks_and_partition
9410   && CROSSING_JUMP_P (insn)"
9411{
9412  /* The length is 16 if the delay slot is unfilled.  */
9413  return output_far_jump(insn, operands[0]);
9414}
9415  [(set_attr "type" "jump")
9416   (set_attr "length" "16")])
9417
9418;; ??? It would be much saner to explicitly use the scratch register
9419;; in the jump insn, and have indirect_jump_scratch only set it,
9420;; but fill_simple_delay_slots would refuse to do delay slot filling
9421;; from the target then, as it uses simplejump_p.
9422;;(define_insn "jump_compact_far"
9423;;  [(set (pc)
9424;;	(label_ref (match_operand 0 "" "")))
9425;;   (use (match_operand 1 "register_operand" "r")]
9426;;  "TARGET_SH1"
9427;;  "* return output_far_jump(insn, operands[0], operands[1]);"
9428;;  [(set_attr "type" "jump")
9429;;   (set_attr "needs_delay_slot" "yes")])
9430
9431(define_insn "jump_media"
9432  [(set (pc)
9433	(match_operand 0 "target_operand" "b"))]
9434  "TARGET_SHMEDIA"
9435  "blink	%0, r63%>"
9436  [(set_attr "type" "jump_media")])
9437
9438(define_expand "jump"
9439  [(set (pc)
9440	(label_ref (match_operand 0 "" "")))]
9441  ""
9442{
9443  if (TARGET_SH1)
9444    emit_jump_insn (gen_jump_compact (operands[0]));
9445  else if (TARGET_SHMEDIA)
9446    {
9447      if (reload_in_progress || reload_completed)
9448	FAIL;
9449      emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0])));
9450    }
9451  DONE;
9452})
9453
9454(define_insn "force_mode_for_call"
9455  [(use (reg:SI FPSCR_MODES_REG))]
9456  "TARGET_SHCOMPACT"
9457  ""
9458  [(set_attr "length" "0")
9459   (set (attr "fp_mode")
9460	(if_then_else (eq_attr "fpu_single" "yes")
9461		      (const_string "single") (const_string "double")))])
9462
9463(define_insn "calli"
9464  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9465	 (match_operand 1 "" ""))
9466   (use (reg:SI FPSCR_MODES_REG))
9467   (clobber (reg:SI PR_REG))]
9468  "TARGET_SH1"
9469{
9470  if (TARGET_SH2A && (dbr_sequence_length () == 0))
9471    return "jsr/n	@%0";
9472  else
9473    return "jsr	@%0%#";
9474}
9475  [(set_attr "type" "call")
9476   (set (attr "fp_mode")
9477	(if_then_else (eq_attr "fpu_single" "yes")
9478		      (const_string "single") (const_string "double")))
9479   (set_attr "needs_delay_slot" "yes")
9480   (set_attr "fp_set" "unknown")])
9481
9482;; This is TBR relative jump instruction for SH2A architecture.
9483;; Its use is enabled by assigning an attribute "function_vector"
9484;; and the vector number to a function during its declaration.
9485(define_insn "calli_tbr_rel"
9486  [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
9487	 (match_operand 1 "" ""))
9488   (use (reg:SI FPSCR_MODES_REG))
9489   (clobber (reg:SI PR_REG))]
9490  "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
9491{
9492  unsigned HOST_WIDE_INT vect_num;
9493  vect_num = sh2a_get_function_vector_number (operands[0]);
9494  operands[2] = GEN_INT (vect_num * 4);
9495
9496  return "jsr/n	@@(%O2,tbr)";
9497}
9498  [(set_attr "type" "call")
9499   (set (attr "fp_mode")
9500	(if_then_else (eq_attr "fpu_single" "yes")
9501		      (const_string "single") (const_string "double")))
9502   (set_attr "needs_delay_slot" "no")
9503   (set_attr "fp_set" "unknown")])
9504
9505;; This is a pc-rel call, using bsrf, for use with PIC.
9506(define_insn "calli_pcrel"
9507  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9508	 (match_operand 1 "" ""))
9509   (use (reg:SI FPSCR_MODES_REG))
9510   (use (reg:SI PIC_REG))
9511   (use (match_operand 2 "" ""))
9512   (clobber (reg:SI PR_REG))]
9513  "TARGET_SH2"
9514{
9515  return       "bsrf	%0"	"\n"
9516	 "%O2:%#";
9517}
9518  [(set_attr "type" "call")
9519   (set (attr "fp_mode")
9520	(if_then_else (eq_attr "fpu_single" "yes")
9521		      (const_string "single") (const_string "double")))
9522   (set_attr "needs_delay_slot" "yes")
9523   (set_attr "fp_set" "unknown")])
9524
9525(define_insn_and_split "call_pcrel"
9526  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9527	 (match_operand 1 "" ""))
9528   (use (reg:SI FPSCR_MODES_REG))
9529   (use (reg:SI PIC_REG))
9530   (clobber (reg:SI PR_REG))
9531   (clobber (match_scratch:SI 2 "=&r"))]
9532  "TARGET_SH2"
9533  "#"
9534  "reload_completed"
9535  [(const_int 0)]
9536{
9537  rtx lab = PATTERN (gen_call_site ());
9538
9539  if (SYMBOL_REF_LOCAL_P (operands[0]))
9540    emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9541  else
9542    emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
9543  emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
9544  DONE;
9545}
9546  [(set_attr "type" "call")
9547   (set (attr "fp_mode")
9548	(if_then_else (eq_attr "fpu_single" "yes")
9549		      (const_string "single") (const_string "double")))
9550   (set_attr "needs_delay_slot" "yes")
9551   (set_attr "fp_set" "unknown")])
9552
9553(define_insn "call_compact"
9554  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9555	 (match_operand 1 "" ""))
9556   (match_operand 2 "immediate_operand" "n")
9557   (use (reg:SI R0_REG))
9558   (use (reg:SI R1_REG))
9559   (use (reg:SI FPSCR_MODES_REG))
9560   (clobber (reg:SI PR_REG))]
9561  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9562  "jsr	@%0%#"
9563  [(set_attr "type" "call")
9564   (set (attr "fp_mode")
9565	(if_then_else (eq_attr "fpu_single" "yes")
9566		      (const_string "single") (const_string "double")))
9567   (set_attr "needs_delay_slot" "yes")])
9568
9569(define_insn "call_compact_rettramp"
9570  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9571	 (match_operand 1 "" ""))
9572   (match_operand 2 "immediate_operand" "n")
9573   (use (reg:SI R0_REG))
9574   (use (reg:SI R1_REG))
9575   (use (reg:SI FPSCR_MODES_REG))
9576   (clobber (reg:SI R10_REG))
9577   (clobber (reg:SI PR_REG))]
9578  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9579  "jsr	@%0%#"
9580  [(set_attr "type" "call")
9581   (set (attr "fp_mode")
9582	(if_then_else (eq_attr "fpu_single" "yes")
9583		      (const_string "single") (const_string "double")))
9584   (set_attr "needs_delay_slot" "yes")])
9585
9586(define_insn "call_media"
9587  [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
9588	 (match_operand 1 "" ""))
9589   (clobber (reg:DI PR_MEDIA_REG))]
9590  "TARGET_SHMEDIA"
9591  "blink	%0, r18"
9592  [(set_attr "type" "jump_media")])
9593
9594(define_insn "call_valuei"
9595  [(set (match_operand 0 "" "=rf")
9596	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9597	      (match_operand 2 "" "")))
9598   (use (reg:SI FPSCR_MODES_REG))
9599   (clobber (reg:SI PR_REG))]
9600  "TARGET_SH1"
9601{
9602  if (TARGET_SH2A && (dbr_sequence_length () == 0))
9603    return "jsr/n	@%1";
9604  else
9605    return "jsr	@%1%#";
9606}
9607  [(set_attr "type" "call")
9608   (set (attr "fp_mode")
9609	(if_then_else (eq_attr "fpu_single" "yes")
9610		      (const_string "single") (const_string "double")))
9611   (set_attr "needs_delay_slot" "yes")
9612   (set_attr "fp_set" "unknown")])
9613
9614;; This is TBR relative jump instruction for SH2A architecture.
9615;; Its use is enabled by assigning an attribute "function_vector"
9616;; and the vector number to a function during its declaration.
9617(define_insn "call_valuei_tbr_rel"
9618  [(set (match_operand 0 "" "=rf")
9619	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9620	      (match_operand 2 "" "")))
9621   (use (reg:SI FPSCR_MODES_REG))
9622   (clobber (reg:SI PR_REG))]
9623  "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
9624{
9625  unsigned HOST_WIDE_INT vect_num;
9626  vect_num = sh2a_get_function_vector_number (operands[1]);
9627  operands[3] = GEN_INT (vect_num * 4);
9628
9629  return "jsr/n	@@(%O3,tbr)";
9630}
9631  [(set_attr "type" "call")
9632   (set (attr "fp_mode")
9633	(if_then_else (eq_attr "fpu_single" "yes")
9634		      (const_string "single") (const_string "double")))
9635   (set_attr "needs_delay_slot" "no")
9636   (set_attr "fp_set" "unknown")])
9637
9638(define_insn "call_valuei_pcrel"
9639  [(set (match_operand 0 "" "=rf")
9640	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9641	      (match_operand 2 "" "")))
9642   (use (reg:SI FPSCR_MODES_REG))
9643   (use (reg:SI PIC_REG))
9644   (use (match_operand 3 "" ""))
9645   (clobber (reg:SI PR_REG))]
9646  "TARGET_SH2"
9647{
9648  return       "bsrf	%1"	"\n"
9649	 "%O3:%#";
9650}
9651  [(set_attr "type" "call")
9652   (set (attr "fp_mode")
9653	(if_then_else (eq_attr "fpu_single" "yes")
9654		      (const_string "single") (const_string "double")))
9655   (set_attr "needs_delay_slot" "yes")
9656   (set_attr "fp_set" "unknown")])
9657
9658(define_insn_and_split "call_value_pcrel"
9659  [(set (match_operand 0 "" "=rf")
9660	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9661	      (match_operand 2 "" "")))
9662   (use (reg:SI FPSCR_MODES_REG))
9663   (use (reg:SI PIC_REG))
9664   (clobber (reg:SI PR_REG))
9665   (clobber (match_scratch:SI 3 "=&r"))]
9666  "TARGET_SH2"
9667  "#"
9668  "reload_completed"
9669  [(const_int 0)]
9670{
9671  rtx lab = PATTERN (gen_call_site ());
9672
9673  if (SYMBOL_REF_LOCAL_P (operands[1]))
9674    emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9675  else
9676    emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
9677  emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
9678					 operands[2], copy_rtx (lab)));
9679  DONE;
9680}
9681  [(set_attr "type" "call")
9682   (set (attr "fp_mode")
9683	(if_then_else (eq_attr "fpu_single" "yes")
9684		      (const_string "single") (const_string "double")))
9685   (set_attr "needs_delay_slot" "yes")
9686   (set_attr "fp_set" "unknown")])
9687
9688(define_insn "call_value_compact"
9689  [(set (match_operand 0 "" "=rf")
9690	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9691	      (match_operand 2 "" "")))
9692   (match_operand 3 "immediate_operand" "n")
9693   (use (reg:SI R0_REG))
9694   (use (reg:SI R1_REG))
9695   (use (reg:SI FPSCR_MODES_REG))
9696   (clobber (reg:SI PR_REG))]
9697  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9698  "jsr	@%1%#"
9699  [(set_attr "type" "call")
9700   (set (attr "fp_mode")
9701	(if_then_else (eq_attr "fpu_single" "yes")
9702		      (const_string "single") (const_string "double")))
9703   (set_attr "needs_delay_slot" "yes")])
9704
9705(define_insn "call_value_compact_rettramp"
9706  [(set (match_operand 0 "" "=rf")
9707	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9708	      (match_operand 2 "" "")))
9709   (match_operand 3 "immediate_operand" "n")
9710   (use (reg:SI R0_REG))
9711   (use (reg:SI R1_REG))
9712   (use (reg:SI FPSCR_MODES_REG))
9713   (clobber (reg:SI R10_REG))
9714   (clobber (reg:SI PR_REG))]
9715  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9716  "jsr	@%1%#"
9717  [(set_attr "type" "call")
9718   (set (attr "fp_mode")
9719	(if_then_else (eq_attr "fpu_single" "yes")
9720		      (const_string "single") (const_string "double")))
9721   (set_attr "needs_delay_slot" "yes")])
9722
9723(define_insn "call_value_media"
9724  [(set (match_operand 0 "" "=rf")
9725	(call (mem:DI (match_operand 1 "target_reg_operand" "b"))
9726	      (match_operand 2 "" "")))
9727   (clobber (reg:DI PR_MEDIA_REG))]
9728  "TARGET_SHMEDIA"
9729  "blink	%1, r18"
9730  [(set_attr "type" "jump_media")])
9731
9732(define_expand "call"
9733  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9734			    (match_operand 1 "" ""))
9735	      (match_operand 2 "" "")
9736	      (use (reg:SI FPSCR_MODES_REG))
9737	      (clobber (reg:SI PR_REG))])]
9738  ""
9739{
9740  if (TARGET_SHMEDIA)
9741    {
9742      operands[0] = shmedia_prepare_call_address (operands[0], 0);
9743      emit_call_insn (gen_call_media (operands[0], operands[1]));
9744      DONE;
9745    }
9746  else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9747    {
9748      rtx cookie_rtx = operands[2];
9749      long cookie = INTVAL (cookie_rtx);
9750      rtx func = XEXP (operands[0], 0);
9751      rtx r0, r1;
9752
9753      if (flag_pic)
9754	{
9755	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9756	    {
9757	      rtx reg = gen_reg_rtx (Pmode);
9758
9759	      emit_insn (gen_symGOTPLT2reg (reg, func));
9760	      func = reg;
9761	    }
9762	  else
9763	    func = legitimize_pic_address (func, Pmode, 0);
9764	}
9765
9766      r0 = gen_rtx_REG (SImode, R0_REG);
9767      r1 = gen_rtx_REG (SImode, R1_REG);
9768
9769      /* Since such a call function may use all call-clobbered
9770	 registers, we force a mode switch earlier, so that we don't
9771	 run out of registers when adjusting fpscr for the call.  */
9772      emit_insn (gen_force_mode_for_call ());
9773
9774      operands[0]
9775	= function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9776      operands[0] = force_reg (SImode, operands[0]);
9777
9778      emit_move_insn (r0, func);
9779      emit_move_insn (r1, cookie_rtx);
9780
9781      if (cookie & CALL_COOKIE_RET_TRAMP (1))
9782	emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9783						   operands[2]));
9784      else
9785	emit_call_insn (gen_call_compact (operands[0], operands[1],
9786					  operands[2]));
9787
9788      DONE;
9789    }
9790  else if (TARGET_SHCOMPACT && flag_pic
9791	   && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9792	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9793    {
9794      rtx reg = gen_reg_rtx (Pmode);
9795
9796      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9797      XEXP (operands[0], 0) = reg;
9798    }
9799  if (!flag_pic && TARGET_SH2A
9800      && MEM_P (operands[0])
9801      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9802    {
9803      if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9804	{
9805	  emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9806					     operands[1]));
9807	  DONE;
9808	}
9809    }
9810  if (flag_pic && TARGET_SH2
9811      && MEM_P (operands[0])
9812      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9813    {
9814      emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
9815      DONE;
9816    }
9817  else
9818  {
9819    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9820    operands[1] = operands[2];
9821  }
9822
9823  emit_call_insn (gen_calli (operands[0], operands[1]));
9824  DONE;
9825})
9826
9827(define_insn "call_pop_compact"
9828  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9829	 (match_operand 1 "" ""))
9830   (match_operand 2 "immediate_operand" "n")
9831   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9832				 (match_operand 3 "immediate_operand" "n")))
9833   (use (reg:SI R0_REG))
9834   (use (reg:SI R1_REG))
9835   (use (reg:SI FPSCR_MODES_REG))
9836   (clobber (reg:SI PR_REG))]
9837  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9838  "jsr	@%0%#"
9839  [(set_attr "type" "call")
9840   (set (attr "fp_mode")
9841	(if_then_else (eq_attr "fpu_single" "yes")
9842		      (const_string "single") (const_string "double")))
9843   (set_attr "needs_delay_slot" "yes")])
9844
9845(define_insn "call_pop_compact_rettramp"
9846  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9847	 (match_operand 1 "" ""))
9848   (match_operand 2 "immediate_operand" "n")
9849   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9850				 (match_operand 3 "immediate_operand" "n")))
9851   (use (reg:SI R0_REG))
9852   (use (reg:SI R1_REG))
9853   (use (reg:SI FPSCR_MODES_REG))
9854   (clobber (reg:SI R10_REG))
9855   (clobber (reg:SI PR_REG))]
9856  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9857  "jsr	@%0%#"
9858  [(set_attr "type" "call")
9859   (set (attr "fp_mode")
9860	(if_then_else (eq_attr "fpu_single" "yes")
9861		      (const_string "single") (const_string "double")))
9862   (set_attr "needs_delay_slot" "yes")])
9863
9864(define_expand "call_pop"
9865  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9866		    (match_operand 1 "" ""))
9867	     (match_operand 2 "" "")
9868	     (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9869					   (match_operand 3 "" "")))])]
9870  "TARGET_SHCOMPACT"
9871{
9872  rtx cookie_rtx;
9873  long cookie;
9874  rtx func;
9875  rtx r0, r1;
9876
9877  gcc_assert (operands[2] && INTVAL (operands[2]));
9878  cookie_rtx = operands[2];
9879  cookie = INTVAL (cookie_rtx);
9880  func = XEXP (operands[0], 0);
9881
9882  if (flag_pic)
9883    {
9884      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9885	{
9886	  rtx reg = gen_reg_rtx (Pmode);
9887	  emit_insn (gen_symGOTPLT2reg (reg, func));
9888	  func = reg;
9889	}
9890      else
9891	func = legitimize_pic_address (func, Pmode, 0);
9892    }
9893
9894  r0 = gen_rtx_REG (SImode, R0_REG);
9895  r1 = gen_rtx_REG (SImode, R1_REG);
9896
9897  /* Since such a call function may use all call-clobbered
9898     registers, we force a mode switch earlier, so that we don't
9899     run out of registers when adjusting fpscr for the call.  */
9900  emit_insn (gen_force_mode_for_call ());
9901
9902  operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9903				 SFUNC_GOT);
9904  operands[0] = force_reg (SImode, operands[0]);
9905
9906  emit_move_insn (r0, func);
9907  emit_move_insn (r1, cookie_rtx);
9908
9909  if (cookie & CALL_COOKIE_RET_TRAMP (1))
9910    emit_call_insn (gen_call_pop_compact_rettramp
9911	   	     (operands[0], operands[1], operands[2], operands[3]));
9912  else
9913    emit_call_insn (gen_call_pop_compact
9914	  	     (operands[0], operands[1], operands[2], operands[3]));
9915
9916  DONE;
9917})
9918
9919(define_expand "call_value"
9920  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9921		   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9922				 (match_operand 2 "" "")))
9923	      (match_operand 3 "" "")
9924	      (use (reg:SI FPSCR_MODES_REG))
9925	      (clobber (reg:SI PR_REG))])]
9926  ""
9927{
9928  if (TARGET_SHMEDIA)
9929    {
9930      operands[1] = shmedia_prepare_call_address (operands[1], 0);
9931      emit_call_insn (gen_call_value_media (operands[0], operands[1],
9932					    operands[2]));
9933      DONE;
9934    }
9935  else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9936    {
9937      rtx cookie_rtx = operands[3];
9938      long cookie = INTVAL (cookie_rtx);
9939      rtx func = XEXP (operands[1], 0);
9940      rtx r0, r1;
9941
9942      if (flag_pic)
9943	{
9944	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9945	    {
9946	      rtx reg = gen_reg_rtx (Pmode);
9947
9948	      emit_insn (gen_symGOTPLT2reg (reg, func));
9949	      func = reg;
9950	    }
9951	  else
9952	    func = legitimize_pic_address (func, Pmode, 0);
9953	}
9954
9955      r0 = gen_rtx_REG (SImode, R0_REG);
9956      r1 = gen_rtx_REG (SImode, R1_REG);
9957
9958      /* Since such a call function may use all call-clobbered
9959	 registers, we force a mode switch earlier, so that we don't
9960	 run out of registers when adjusting fpscr for the call.  */
9961      emit_insn (gen_force_mode_for_call ());
9962
9963      operands[1]
9964	= function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9965      operands[1] = force_reg (SImode, operands[1]);
9966
9967      emit_move_insn (r0, func);
9968      emit_move_insn (r1, cookie_rtx);
9969
9970      if (cookie & CALL_COOKIE_RET_TRAMP (1))
9971	emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9972							 operands[1],
9973							 operands[2],
9974							 operands[3]));
9975      else
9976	emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9977						operands[2], operands[3]));
9978
9979      DONE;
9980    }
9981  else if (TARGET_SHCOMPACT && flag_pic
9982	   && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9983	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9984    {
9985      rtx reg = gen_reg_rtx (Pmode);
9986
9987      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9988      XEXP (operands[1], 0) = reg;
9989    }
9990  if (!flag_pic && TARGET_SH2A
9991      && MEM_P (operands[1])
9992      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9993    {
9994      if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9995	{
9996	  emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9997				 XEXP (operands[1], 0), operands[2]));
9998	  DONE;
9999	}
10000    }
10001  if (flag_pic && TARGET_SH2
10002      && MEM_P (operands[1])
10003      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
10004    {
10005      emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
10006					    operands[2]));
10007      DONE;
10008    }
10009  else
10010    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
10011
10012  emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
10013  DONE;
10014})
10015
10016(define_insn "sibcalli"
10017  [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
10018	 (match_operand 1 "" ""))
10019   (use (reg:SI FPSCR_MODES_REG))
10020   (return)]
10021  "TARGET_SH1"
10022  "jmp	@%0%#"
10023  [(set_attr "needs_delay_slot" "yes")
10024   (set (attr "fp_mode")
10025	(if_then_else (eq_attr "fpu_single" "yes")
10026		      (const_string "single") (const_string "double")))
10027   (set_attr "type" "jump_ind")])
10028
10029(define_insn "sibcalli_pcrel"
10030  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
10031	 (match_operand 1 "" ""))
10032   (use (match_operand 2 "" ""))
10033   (use (reg:SI FPSCR_MODES_REG))
10034   (return)]
10035  "TARGET_SH2"
10036{
10037  return       "braf	%0"	"\n"
10038	 "%O2:%#";
10039}
10040  [(set_attr "needs_delay_slot" "yes")
10041   (set (attr "fp_mode")
10042	(if_then_else (eq_attr "fpu_single" "yes")
10043		      (const_string "single") (const_string "double")))
10044   (set_attr "type" "jump_ind")])
10045
10046;; This uses an unspec to describe that the symbol_ref is very close.
10047(define_insn "sibcalli_thunk"
10048  [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
10049			     UNSPEC_THUNK))
10050	 (match_operand 1 "" ""))
10051   (use (reg:SI FPSCR_MODES_REG))
10052   (return)]
10053  "TARGET_SH1"
10054  "bra	%O0"
10055  [(set_attr "needs_delay_slot" "yes")
10056   (set (attr "fp_mode")
10057	(if_then_else (eq_attr "fpu_single" "yes")
10058		      (const_string "single") (const_string "double")))
10059   (set_attr "type" "jump")
10060   (set_attr "length" "2")])
10061
10062(define_insn_and_split "sibcall_pcrel"
10063  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
10064	 (match_operand 1 "" ""))
10065   (use (reg:SI FPSCR_MODES_REG))
10066   (clobber (match_scratch:SI 2 "=&k"))
10067   (return)]
10068  "TARGET_SH2"
10069  "#"
10070  "reload_completed"
10071  [(const_int 0)]
10072{
10073  rtx lab = PATTERN (gen_call_site ());
10074  rtx call_insn;
10075
10076  emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
10077  call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
10078						  copy_rtx (lab)));
10079  SIBLING_CALL_P (call_insn) = 1;
10080  DONE;
10081}
10082  [(set_attr "needs_delay_slot" "yes")
10083   (set (attr "fp_mode")
10084	(if_then_else (eq_attr "fpu_single" "yes")
10085		      (const_string "single") (const_string "double")))
10086   (set_attr "type" "jump_ind")])
10087
10088(define_insn "sibcall_compact"
10089  [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
10090	 (match_operand 1 "" ""))
10091   (return)
10092   (use (match_operand:SI 2 "register_operand" "z,x"))
10093   (use (reg:SI R1_REG))
10094   (use (reg:SI FPSCR_MODES_REG))
10095   ;; We want to make sure the `x' above will only match MACH_REG
10096   ;; because sibcall_epilogue may clobber MACL_REG.
10097   (clobber (reg:SI MACL_REG))]
10098  "TARGET_SHCOMPACT"
10099{
10100  static const char* alt[] =
10101  {
10102       "jmp	@%0%#",
10103
10104       "jmp	@%0"	"\n"
10105    "	sts	%2,r0"
10106  };
10107  return alt[which_alternative];
10108}
10109  [(set_attr "needs_delay_slot" "yes,no")
10110   (set_attr "length" "2,4")
10111   (set (attr "fp_mode") (const_string "single"))
10112   (set_attr "type" "jump_ind")])
10113
10114(define_insn "sibcall_media"
10115  [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
10116	 (match_operand 1 "" ""))
10117   (use (reg:SI PR_MEDIA_REG))
10118   (return)]
10119  "TARGET_SHMEDIA"
10120  "blink	%0, r63"
10121  [(set_attr "type" "jump_media")])
10122
10123(define_expand "sibcall"
10124  [(parallel
10125    [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
10126	   (match_operand 1 "" ""))
10127     (match_operand 2 "" "")
10128   (use (reg:SI FPSCR_MODES_REG))
10129     (return)])]
10130  ""
10131{
10132  if (TARGET_SHMEDIA)
10133    {
10134      operands[0] = shmedia_prepare_call_address (operands[0], 1);
10135      emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
10136      DONE;
10137    }
10138  else if (TARGET_SHCOMPACT && operands[2]
10139	   && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
10140    {
10141      rtx cookie_rtx = operands[2];
10142      long cookie = INTVAL (cookie_rtx);
10143      rtx func = XEXP (operands[0], 0);
10144      rtx mach, r1;
10145
10146      if (flag_pic)
10147	{
10148	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10149	    {
10150	      rtx reg = gen_reg_rtx (Pmode);
10151
10152	      emit_insn (gen_symGOT2reg (reg, func));
10153	      func = reg;
10154	    }
10155	  else
10156	    func = legitimize_pic_address (func, Pmode, 0);
10157	}
10158
10159      /* FIXME: if we could tell whether all argument registers are
10160	 already taken, we could decide whether to force the use of
10161	 MACH_REG or to stick to R0_REG.  Unfortunately, there's no
10162	 simple way to tell.  We could use the CALL_COOKIE, but we
10163	 can't currently tell a register used for regular argument
10164	 passing from one that is unused.  If we leave it up to reload
10165	 to decide which register to use, it seems to always choose
10166	 R0_REG, which leaves no available registers in SIBCALL_REGS
10167	 to hold the address of the trampoline.  */
10168      mach = gen_rtx_REG (SImode, MACH_REG);
10169      r1 = gen_rtx_REG (SImode, R1_REG);
10170
10171      /* Since such a call function may use all call-clobbered
10172	 registers, we force a mode switch earlier, so that we don't
10173	 run out of registers when adjusting fpscr for the call.  */
10174      emit_insn (gen_force_mode_for_call ());
10175
10176      operands[0]
10177	= function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
10178      operands[0] = force_reg (SImode, operands[0]);
10179
10180      /* We don't need a return trampoline, since the callee will
10181	 return directly to the upper caller.  */
10182      if (cookie & CALL_COOKIE_RET_TRAMP (1))
10183	{
10184	  cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
10185	  cookie_rtx = GEN_INT (cookie);
10186	}
10187
10188      emit_move_insn (mach, func);
10189      emit_move_insn (r1, cookie_rtx);
10190
10191      emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
10192      DONE;
10193    }
10194  else if (TARGET_SHCOMPACT && flag_pic
10195	   && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
10196	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
10197    {
10198      rtx reg = gen_reg_rtx (Pmode);
10199
10200      emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
10201      XEXP (operands[0], 0) = reg;
10202    }
10203  if (flag_pic && TARGET_SH2
10204      && MEM_P (operands[0])
10205      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
10206      /* The PLT needs the PIC register, but the epilogue would have
10207	 to restore it, so we can only use PC-relative PIC calls for
10208	 static functions.  */
10209      && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
10210    {
10211      emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
10212      DONE;
10213    }
10214  else
10215    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
10216
10217  emit_call_insn (gen_sibcalli (operands[0], operands[1]));
10218  DONE;
10219})
10220
10221(define_insn "sibcall_valuei"
10222  [(set (match_operand 0 "" "=rf")
10223	(call (mem:SI (match_operand:SI 1 "register_operand" "k"))
10224	      (match_operand 2 "" "")))
10225   (use (reg:SI FPSCR_MODES_REG))
10226   (return)]
10227  "TARGET_SH1"
10228  "jmp	@%1%#"
10229  [(set_attr "needs_delay_slot" "yes")
10230   (set (attr "fp_mode")
10231	(if_then_else (eq_attr "fpu_single" "yes")
10232		      (const_string "single") (const_string "double")))
10233   (set_attr "type" "jump_ind")])
10234
10235(define_insn "sibcall_valuei_pcrel"
10236  [(set (match_operand 0 "" "=rf")
10237	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
10238	      (match_operand 2 "" "")))
10239   (use (match_operand 3 "" ""))
10240   (use (reg:SI FPSCR_MODES_REG))
10241   (return)]
10242  "TARGET_SH2"
10243{
10244  return       "braf	%1"	"\n"
10245	 "%O3:%#";
10246}
10247  [(set_attr "needs_delay_slot" "yes")
10248   (set (attr "fp_mode")
10249	(if_then_else (eq_attr "fpu_single" "yes")
10250		      (const_string "single") (const_string "double")))
10251   (set_attr "type" "jump_ind")])
10252
10253;; sibcall_value_pcrel used to have a =&k clobber for the scratch register
10254;; that it needs for the branch address.  This causes troubles when there
10255;; is a big overlap of argument and return value registers.  Hence, use a
10256;; fixed call clobbered register for the address.  See also PR 67260.
10257(define_insn_and_split "sibcall_value_pcrel"
10258  [(set (match_operand 0 "" "=rf")
10259	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
10260	      (match_operand 2 "" "")))
10261   (use (reg:SI FPSCR_MODES_REG))
10262   (clobber (reg:SI R1_REG))
10263   (return)]
10264  "TARGET_SH2"
10265  "#"
10266  "reload_completed"
10267  [(const_int 0)]
10268{
10269  rtx lab = PATTERN (gen_call_site ());
10270  rtx call_insn;
10271
10272  operands[3] =  gen_rtx_REG (SImode, R1_REG);
10273
10274  emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
10275  call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
10276							operands[3],
10277							operands[2],
10278							copy_rtx (lab)));
10279  SIBLING_CALL_P (call_insn) = 1;
10280  DONE;
10281}
10282  [(set_attr "needs_delay_slot" "yes")
10283   (set (attr "fp_mode")
10284	(if_then_else (eq_attr "fpu_single" "yes")
10285		      (const_string "single") (const_string "double")))
10286   (set_attr "type" "jump_ind")])
10287
10288(define_insn "sibcall_value_compact"
10289  [(set (match_operand 0 "" "=rf,rf")
10290	(call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
10291	      (match_operand 2 "" "")))
10292   (return)
10293   (use (match_operand:SI 3 "register_operand" "z,x"))
10294   (use (reg:SI R1_REG))
10295   (use (reg:SI FPSCR_MODES_REG))
10296   ;; We want to make sure the `x' above will only match MACH_REG
10297   ;; because sibcall_epilogue may clobber MACL_REG.
10298   (clobber (reg:SI MACL_REG))]
10299  "TARGET_SHCOMPACT"
10300{
10301  static const char* alt[] =
10302  {
10303       "jmp	@%1%#",
10304
10305       "jmp	@%1"	"\n"
10306    "	sts	%3,r0"
10307  };
10308  return alt[which_alternative];
10309}
10310  [(set_attr "needs_delay_slot" "yes,no")
10311   (set_attr "length" "2,4")
10312   (set (attr "fp_mode") (const_string "single"))
10313   (set_attr "type" "jump_ind")])
10314
10315(define_insn "sibcall_value_media"
10316  [(set (match_operand 0 "" "=rf")
10317	(call (mem:DI (match_operand 1 "target_reg_operand" "k"))
10318	      (match_operand 2 "" "")))
10319   (use (reg:SI PR_MEDIA_REG))
10320   (return)]
10321  "TARGET_SHMEDIA"
10322  "blink	%1, r63"
10323  [(set_attr "type" "jump_media")])
10324
10325(define_expand "sibcall_value"
10326  [(parallel
10327    [(set (match_operand 0 "arith_reg_operand" "")
10328	  (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
10329	  	(match_operand 2 "" "")))
10330     (match_operand 3 "" "")
10331   (use (reg:SI FPSCR_MODES_REG))
10332     (return)])]
10333  ""
10334{
10335  if (TARGET_SHMEDIA)
10336    {
10337      operands[1] = shmedia_prepare_call_address (operands[1], 1);
10338      emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
10339					       operands[2]));
10340      DONE;
10341    }
10342  else if (TARGET_SHCOMPACT && operands[3]
10343	   && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
10344    {
10345      rtx cookie_rtx = operands[3];
10346      long cookie = INTVAL (cookie_rtx);
10347      rtx func = XEXP (operands[1], 0);
10348      rtx mach, r1;
10349
10350      if (flag_pic)
10351	{
10352	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10353	    {
10354	      rtx reg = gen_reg_rtx (Pmode);
10355
10356	      emit_insn (gen_symGOT2reg (reg, func));
10357	      func = reg;
10358	    }
10359	  else
10360	    func = legitimize_pic_address (func, Pmode, 0);
10361	}
10362
10363      /* FIXME: if we could tell whether all argument registers are
10364	 already taken, we could decide whether to force the use of
10365	 MACH_REG or to stick to R0_REG.  Unfortunately, there's no
10366	 simple way to tell.  We could use the CALL_COOKIE, but we
10367	 can't currently tell a register used for regular argument
10368	 passing from one that is unused.  If we leave it up to reload
10369	 to decide which register to use, it seems to always choose
10370	 R0_REG, which leaves no available registers in SIBCALL_REGS
10371	 to hold the address of the trampoline.  */
10372      mach = gen_rtx_REG (SImode, MACH_REG);
10373      r1 = gen_rtx_REG (SImode, R1_REG);
10374
10375      /* Since such a call function may use all call-clobbered
10376	 registers, we force a mode switch earlier, so that we don't
10377	 run out of registers when adjusting fpscr for the call.  */
10378      emit_insn (gen_force_mode_for_call ());
10379
10380      operands[1]
10381	= function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
10382      operands[1] = force_reg (SImode, operands[1]);
10383
10384      /* We don't need a return trampoline, since the callee will
10385	 return directly to the upper caller.  */
10386      if (cookie & CALL_COOKIE_RET_TRAMP (1))
10387	{
10388	  cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
10389	  cookie_rtx = GEN_INT (cookie);
10390	}
10391
10392      emit_move_insn (mach, func);
10393      emit_move_insn (r1, cookie_rtx);
10394
10395      emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
10396						 operands[2], mach));
10397      DONE;
10398    }
10399  else if (TARGET_SHCOMPACT && flag_pic
10400	   && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
10401	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
10402    {
10403      rtx reg = gen_reg_rtx (Pmode);
10404
10405      emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
10406      XEXP (operands[1], 0) = reg;
10407    }
10408  if (flag_pic && TARGET_SH2
10409      && MEM_P (operands[1])
10410      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
10411      /* The PLT needs the PIC register, but the epilogue would have
10412	 to restore it, so we can only use PC-relative PIC calls for
10413	 static functions.  */
10414      && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
10415    {
10416      emit_call_insn (gen_sibcall_value_pcrel (operands[0],
10417					       XEXP (operands[1], 0),
10418					       operands[2]));
10419      DONE;
10420    }
10421  else
10422    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
10423
10424  emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
10425  DONE;
10426})
10427
10428(define_insn "call_value_pop_compact"
10429  [(set (match_operand 0 "" "=rf")
10430	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
10431	      (match_operand 2 "" "")))
10432   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
10433				 (match_operand 4 "immediate_operand" "n")))
10434   (match_operand 3 "immediate_operand" "n")
10435   (use (reg:SI R0_REG))
10436   (use (reg:SI R1_REG))
10437   (use (reg:SI FPSCR_MODES_REG))
10438   (clobber (reg:SI PR_REG))]
10439  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
10440  "jsr	@%1%#"
10441  [(set_attr "type" "call")
10442   (set (attr "fp_mode")
10443	(if_then_else (eq_attr "fpu_single" "yes")
10444		      (const_string "single") (const_string "double")))
10445   (set_attr "needs_delay_slot" "yes")])
10446
10447(define_insn "call_value_pop_compact_rettramp"
10448  [(set (match_operand 0 "" "=rf")
10449	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
10450	      (match_operand 2 "" "")))
10451   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
10452				 (match_operand 4 "immediate_operand" "n")))
10453   (match_operand 3 "immediate_operand" "n")
10454   (use (reg:SI R0_REG))
10455   (use (reg:SI R1_REG))
10456   (use (reg:SI FPSCR_MODES_REG))
10457   (clobber (reg:SI R10_REG))
10458   (clobber (reg:SI PR_REG))]
10459  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
10460  "jsr	@%1%#"
10461  [(set_attr "type" "call")
10462   (set (attr "fp_mode")
10463	(if_then_else (eq_attr "fpu_single" "yes")
10464		      (const_string "single") (const_string "double")))
10465   (set_attr "needs_delay_slot" "yes")])
10466
10467(define_expand "call_value_pop"
10468  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
10469		   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
10470				 (match_operand 2 "" "")))
10471	      (match_operand 3 "" "")
10472	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
10473					    (match_operand 4 "" "")))])]
10474  "TARGET_SHCOMPACT"
10475{
10476  rtx cookie_rtx;
10477  long cookie;
10478  rtx func;
10479  rtx r0, r1;
10480
10481  gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
10482  cookie_rtx = operands[3];
10483  cookie = INTVAL (cookie_rtx);
10484  func = XEXP (operands[1], 0);
10485
10486  if (flag_pic)
10487    {
10488      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10489	{
10490	  rtx reg = gen_reg_rtx (Pmode);
10491
10492	  emit_insn (gen_symGOTPLT2reg (reg, func));
10493	  func = reg;
10494	}
10495      else
10496	func = legitimize_pic_address (func, Pmode, 0);
10497    }
10498
10499  r0 = gen_rtx_REG (SImode, R0_REG);
10500  r1 = gen_rtx_REG (SImode, R1_REG);
10501
10502  /* Since such a call function may use all call-clobbered
10503     registers, we force a mode switch earlier, so that we don't
10504     run out of registers when adjusting fpscr for the call.  */
10505  emit_insn (gen_force_mode_for_call ());
10506
10507  operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
10508				 SFUNC_GOT);
10509  operands[1] = force_reg (SImode, operands[1]);
10510
10511  emit_move_insn (r0, func);
10512  emit_move_insn (r1, cookie_rtx);
10513
10514  if (cookie & CALL_COOKIE_RET_TRAMP (1))
10515    emit_call_insn (gen_call_value_pop_compact_rettramp
10516			(operands[0], operands[1], operands[2],
10517			 operands[3], operands[4]));
10518  else
10519    emit_call_insn (gen_call_value_pop_compact
10520			(operands[0], operands[1], operands[2],
10521			 operands[3], operands[4]));
10522
10523  DONE;
10524})
10525
10526(define_expand "sibcall_epilogue"
10527  [(return)]
10528  ""
10529{
10530  sh_expand_epilogue (true);
10531  if (TARGET_SHCOMPACT)
10532    {
10533      rtx_insn *insn;
10534      rtx set;
10535
10536      /* If epilogue clobbers r0, preserve it in macl.  */
10537      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
10538	if ((set = single_set (insn))
10539	    && REG_P (SET_DEST (set))
10540	    && REGNO (SET_DEST (set)) == R0_REG)
10541	  {
10542	    rtx r0 = gen_rtx_REG (SImode, R0_REG);
10543	    rtx tmp = gen_rtx_REG (SImode, MACL_REG);
10544
10545	    /* We can't tell at this point whether the sibcall is a
10546	       sibcall_compact and, if it is, whether it uses r0 or
10547	       mach as operand 2, so let the instructions that
10548	       preserve r0 be optimized away if r0 turns out to be
10549	       dead.  */
10550	    emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
10551	    emit_move_insn (r0, tmp);
10552	    break;
10553	  }
10554    }
10555  DONE;
10556})
10557
10558(define_insn "indirect_jump_compact"
10559  [(set (pc)
10560	(match_operand:SI 0 "arith_reg_operand" "r"))]
10561  "TARGET_SH1"
10562  "jmp	@%0%#"
10563  [(set_attr "needs_delay_slot" "yes")
10564   (set_attr "type" "jump_ind")])
10565
10566(define_expand "indirect_jump"
10567  [(set (pc)
10568	(match_operand 0 "register_operand" ""))]
10569  ""
10570{
10571  if (GET_MODE (operands[0]) != Pmode)
10572    operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
10573})
10574
10575;; The use of operand 1 / 2 helps us distinguish case table jumps
10576;; which can be present in structured code from indirect jumps which can not
10577;; be present in structured code.  This allows -fprofile-arcs to work.
10578
10579;; For SH1 processors.
10580(define_insn "casesi_jump_1"
10581  [(set (pc)
10582	(match_operand:SI 0 "register_operand" "r"))
10583   (use (label_ref (match_operand 1 "" "")))]
10584  "TARGET_SH1"
10585  "jmp	@%0%#"
10586  [(set_attr "needs_delay_slot" "yes")
10587   (set_attr "type" "jump_ind")])
10588
10589;; For all later processors.
10590(define_insn "casesi_jump_2"
10591  [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
10592		      (label_ref (match_operand 1 "" ""))))
10593   (use (label_ref (match_operand 2 "" "")))]
10594  "TARGET_SH2
10595   && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
10596  "braf	%0%#"
10597  [(set_attr "needs_delay_slot" "yes")
10598   (set_attr "type" "jump_ind")])
10599
10600(define_insn "casesi_jump_media"
10601  [(set (pc) (match_operand 0 "target_reg_operand" "b"))
10602   (use (label_ref (match_operand 1 "" "")))]
10603  "TARGET_SHMEDIA"
10604  "blink	%0, r63"
10605  [(set_attr "type" "jump_media")])
10606
10607;; Call subroutine returning any type.
10608;; ??? This probably doesn't work.
10609(define_expand "untyped_call"
10610  [(parallel [(call (match_operand 0 "" "")
10611		    (const_int 0))
10612	      (match_operand 1 "" "")
10613	      (match_operand 2 "" "")])]
10614  "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
10615{
10616  if (! TARGET_SHMEDIA)
10617    {
10618      /* RA does not know that the call sets the function value registers.
10619	 We avoid problems by claiming that those registers are clobbered
10620	 at this point.  */
10621      for (int i = 0; i < XVECLEN (operands[2], 0); i++)
10622	{
10623	  rtx set = XVECEXP (operands[2], 0, i);
10624	  emit_clobber (SET_SRC (set));
10625	}
10626    }
10627
10628  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
10629
10630  for (int i = 0; i < XVECLEN (operands[2], 0); i++)
10631    {
10632      rtx set = XVECEXP (operands[2], 0, i);
10633      emit_move_insn (SET_DEST (set), SET_SRC (set));
10634    }
10635
10636  /* The optimizer does not know that the call sets the function value
10637     registers we stored in the result block.  We avoid problems by
10638     claiming that all hard registers are used and clobbered at this
10639     point.  */
10640  emit_insn (gen_blockage ());
10641
10642  DONE;
10643})
10644
10645;; ------------------------------------------------------------------------
10646;; Misc insns
10647;; ------------------------------------------------------------------------
10648
10649(define_insn "dect"
10650  [(set (reg:SI T_REG)
10651	(eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
10652   (set (match_operand:SI 0 "arith_reg_dest" "=r")
10653	(plus:SI (match_dup 1) (const_int -1)))]
10654  "TARGET_SH2"
10655  "dt	%0"
10656  [(set_attr "type" "arith")])
10657
10658(define_insn "nop"
10659  [(const_int 0)]
10660  ""
10661  "nop")
10662
10663;; Load address of a label. This is only generated by the casesi expand,
10664;; and by machine_dependent_reorg (fixing up fp moves).
10665;; This must use unspec, because this only works for labels that are
10666;; within range.
10667(define_insn "mova"
10668  [(set (reg:SI R0_REG)
10669	(unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
10670  "TARGET_SH1"
10671  "mova	%O0,r0"
10672  [(set_attr "in_delay_slot" "no")
10673   (set_attr "type" "arith")])
10674
10675;; machine_dependent_reorg will make this a `mova'.
10676(define_insn "mova_const"
10677  [(set (reg:SI R0_REG)
10678	(unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
10679  "TARGET_SH1"
10680  "#"
10681  [(set_attr "in_delay_slot" "no")
10682   (set_attr "type" "arith")])
10683
10684;; Loads of the GOTPC relocation values must not be optimized away
10685;; by e.g. any kind of CSE and must stay as they are.  Although there
10686;; are other various ways to ensure this, we use an artificial counter
10687;; operand to generate unique symbols.
10688(define_expand "GOTaddr2picreg"
10689  [(set (reg:SI R0_REG)
10690	(unspec:SI [(const:SI (unspec:SI [(match_dup 2)
10691					  (match_operand:SI 0 "" "")]
10692					 UNSPEC_PIC))] UNSPEC_MOVA))
10693   (set (match_dup 1)
10694	(const:SI (unspec:SI [(match_dup 2) (match_dup 0)] UNSPEC_PIC)))
10695   (set (match_dup 1) (plus:SI (match_dup 1) (reg:SI R0_REG)))]
10696  ""
10697{
10698  if (TARGET_VXWORKS_RTP)
10699    {
10700      rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
10701      rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
10702      emit_insn (gen_vxworks_picreg (gott_base, gott_index));
10703      DONE;
10704    }
10705
10706  operands[1] = gen_rtx_REG (Pmode, PIC_REG);
10707  operands[2] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
10708
10709  if (TARGET_SHMEDIA)
10710    {
10711      rtx tr = gen_rtx_REG (Pmode, TR0_REG);
10712      rtx pic = operands[1];
10713      rtx lab = PATTERN (gen_call_site ());
10714      rtx insn, equiv;
10715
10716      equiv = operands[2];
10717      operands[2] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], lab),
10718				    UNSPEC_PCREL_SYMOFF);
10719      operands[2] = gen_rtx_CONST (Pmode, operands[2]);
10720
10721      if (Pmode == SImode)
10722	{
10723	  emit_insn (gen_movsi_const (pic, operands[2]));
10724	  emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
10725	}
10726      else
10727	{
10728	  emit_insn (gen_movdi_const (pic, operands[2]));
10729	  emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
10730	}
10731
10732      insn = emit_move_insn (operands[1], tr);
10733
10734      set_unique_reg_note (insn, REG_EQUAL, equiv);
10735
10736      DONE;
10737    }
10738})
10739
10740;; A helper for GOTaddr2picreg to finish up the initialization of the
10741;; PIC register.
10742(define_expand "vxworks_picreg"
10743  [(set (reg:SI PIC_REG)
10744	(const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
10745   (set (reg:SI R0_REG)
10746	(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
10747   (set (reg:SI PIC_REG)
10748	(mem:SI (reg:SI PIC_REG)))
10749   (set (reg:SI PIC_REG)
10750	(mem:SI (plus:SI (reg:SI PIC_REG)
10751			 (reg:SI R0_REG))))]
10752  "TARGET_VXWORKS_RTP")
10753
10754(define_insn "*ptb"
10755  [(set (match_operand 0 "target_reg_operand" "=b")
10756	(const (unspec [(match_operand 1 "" "Csy")]
10757			     UNSPEC_DATALABEL)))]
10758  "TARGET_SHMEDIA && flag_pic
10759   && satisfies_constraint_Csy (operands[1])"
10760  "ptb/u	datalabel %1, %0"
10761  [(set_attr "type" "ptabs_media")
10762   (set_attr "length" "*")])
10763
10764(define_insn "ptrel_si"
10765  [(set (match_operand:SI 0 "target_reg_operand" "=b")
10766	(plus:SI (match_operand:SI 1 "register_operand" "r")
10767	      (pc)))
10768   (match_operand:SI 2 "" "")]
10769  "TARGET_SHMEDIA"
10770  "%O2: ptrel/u	%1, %0"
10771  [(set_attr "type" "ptabs_media")])
10772
10773(define_insn "ptrel_di"
10774  [(set (match_operand:DI 0 "target_reg_operand" "=b")
10775	(plus:DI (match_operand:DI 1 "register_operand" "r")
10776	      (pc)))
10777   (match_operand:DI 2 "" "")]
10778  "TARGET_SHMEDIA"
10779  "%O2: ptrel/u	%1, %0"
10780  [(set_attr "type" "ptabs_media")])
10781
10782(define_expand "builtin_setjmp_receiver"
10783  [(match_operand 0 "" "")]
10784  "flag_pic"
10785{
10786  emit_insn (gen_GOTaddr2picreg (const0_rtx));
10787  DONE;
10788})
10789
10790(define_expand "call_site"
10791  [(unspec [(match_dup 0)] UNSPEC_CALLER)]
10792  "TARGET_SH1"
10793{
10794  static HOST_WIDE_INT i = 0;
10795  operands[0] = GEN_INT (i);
10796  i++;
10797})
10798
10799;; op0 = op1 + r12 but hide it before reload completed.  See the comment
10800;; in symGOT_load expand.
10801(define_insn_and_split "chk_guard_add"
10802  [(set (match_operand:SI 0 "register_operand" "=&r")
10803	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
10804		    (reg:SI PIC_REG)]
10805		   UNSPEC_CHKADD))]
10806  "TARGET_SH1"
10807  "#"
10808  "TARGET_SH1 && reload_completed"
10809  [(set (match_dup 0) (reg:SI PIC_REG))
10810   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
10811  ""
10812  [(set_attr "type" "arith")])
10813
10814(define_expand "sym_label2reg"
10815  [(set (match_operand:SI 0 "" "")
10816	(const:SI (unspec:SI [(match_operand:SI 1 "" "")
10817			      (const (plus:SI (match_operand:SI 2 "" "")
10818					      (const_int 2)))]
10819			     UNSPEC_SYMOFF)))]
10820  "TARGET_SH1" "")
10821
10822(define_expand "symGOT_load"
10823  [(set (match_dup 2) (match_operand 1 "" ""))
10824   (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
10825   (set (match_operand 0 "" "") (mem (match_dup 3)))]
10826  ""
10827{
10828  rtx mem;
10829  bool stack_chk_guard_p = false;
10830
10831  operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10832  operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10833
10834  if (!TARGET_SHMEDIA
10835      && flag_stack_protect
10836      && GET_CODE (operands[1]) == CONST
10837      && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
10838      && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
10839      && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
10840		 "__stack_chk_guard") == 0)
10841    stack_chk_guard_p = true;
10842
10843  if (TARGET_SHMEDIA)
10844    {
10845      rtx reg = operands[2];
10846
10847      if (Pmode == DImode)
10848	{      
10849	  if (flag_pic > 1)
10850	    emit_insn (gen_movdi_const_32bit (reg, operands[1]));
10851	  else
10852	    emit_insn (gen_movdi_const_16bit (reg, operands[1]));
10853	}
10854      else
10855	{
10856	  if (flag_pic > 1)
10857	    emit_insn (gen_movsi_const (reg, operands[1]));
10858	  else
10859	    emit_insn (gen_movsi_const_16bit (reg, operands[1]));
10860	}
10861    }
10862  else
10863    emit_move_insn (operands[2], operands[1]);
10864
10865  /* When stack protector inserts codes after the result is set to
10866     R0, @(rX, r12) will cause a spill failure for R0.  Use a unspec
10867     insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
10868     when rX is a GOT address for the guard symbol.  Ugly but doesn't
10869     matter because this is a rare situation.  */
10870  if (stack_chk_guard_p)
10871    emit_insn (gen_chk_guard_add (operands[3], operands[2]));
10872  else
10873    emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
10874					       gen_rtx_REG (Pmode, PIC_REG)));
10875
10876  /* N.B. This is not constant for a GOTPLT relocation.  */
10877  mem = gen_rtx_MEM (Pmode, operands[3]);
10878  MEM_NOTRAP_P (mem) = 1;
10879  /* ??? Should we have a special alias set for the GOT?  */
10880  emit_move_insn (operands[0], mem);
10881
10882  DONE;
10883})
10884
10885(define_expand "sym2GOT"
10886  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
10887  ""
10888  "")
10889
10890(define_expand "symGOT2reg"
10891  [(match_operand 0 "" "") (match_operand 1 "" "")]
10892  ""
10893{
10894  rtx gotsym, insn;
10895
10896  gotsym = gen_sym2GOT (operands[1]);
10897  PUT_MODE (gotsym, Pmode);
10898  insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
10899
10900  MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
10901
10902  DONE;
10903})
10904
10905(define_expand "symGOTPLT2reg"
10906  [(match_operand 0 "" "") (match_operand 1 "" "")]
10907  ""
10908{
10909  rtx pltsym = gen_rtx_CONST (Pmode,
10910			      gen_rtx_UNSPEC (Pmode,
10911					      gen_rtvec (1, operands[1]),
10912					      UNSPEC_GOTPLT));
10913  emit_insn (gen_symGOT_load (operands[0], pltsym));
10914  DONE;
10915})
10916
10917(define_expand "sym2GOTOFF"
10918  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10919  ""
10920  "")
10921
10922(define_expand "symGOTOFF2reg"
10923  [(match_operand 0 "" "") (match_operand 1 "" "")]
10924  ""
10925{
10926  rtx gotoffsym, insn;
10927  rtx t = (!can_create_pseudo_p ()
10928	   ? operands[0]
10929	   : gen_reg_rtx (GET_MODE (operands[0])));
10930
10931  gotoffsym = gen_sym2GOTOFF (operands[1]);
10932  PUT_MODE (gotoffsym, Pmode);
10933  emit_move_insn (t, gotoffsym);
10934  insn = emit_move_insn (operands[0],
10935			 gen_rtx_PLUS (Pmode, t,
10936				       gen_rtx_REG (Pmode, PIC_REG)));
10937
10938  set_unique_reg_note (insn, REG_EQUAL, operands[1]);
10939
10940  DONE;
10941})
10942
10943(define_expand "symPLT_label2reg"
10944  [(set (match_operand:SI 0 "" "")
10945	(const:SI
10946	 (unspec:SI
10947	  [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10948	   (const:SI (plus:SI (match_operand:SI 2 "" "")
10949			      (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
10950   ;; Even though the PIC register is not really used by the call
10951   ;; sequence in which this is expanded, the PLT code assumes the PIC
10952   ;; register is set, so we must not skip its initialization.  Since
10953   ;; we only use this expand as part of calling sequences, and never
10954   ;; to take the address of a function, this is the best point to
10955   ;; insert the (use).  Using the PLT to take the address of a
10956   ;; function would be wrong, not only because the PLT entry could
10957   ;; then be called from a function that doesn't initialize the PIC
10958   ;; register to the proper GOT, but also because pointers to the
10959   ;; same function might not compare equal, should they be set by
10960   ;; different shared libraries.
10961   (use (reg:SI PIC_REG))]
10962  "TARGET_SH1"
10963  "")
10964
10965(define_expand "sym2PIC"
10966  [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
10967  ""
10968  "")
10969
10970;; -------------------------------------------------------------------------
10971;; TLS code generation.
10972
10973;; FIXME: The multi-insn asm blocks should be converted to use
10974;; define_insn_and_split.
10975;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10976;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10977;; for details.
10978
10979(define_insn "tls_global_dynamic"
10980  [(set (match_operand:SI 0 "register_operand" "=&z")
10981	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10982				  UNSPEC_TLSGD))
10983	      (const_int 0)))
10984   (use (reg:SI FPSCR_MODES_REG))
10985   (use (reg:SI PIC_REG))
10986   (clobber (reg:SI PR_REG))
10987   (clobber (scratch:SI))]
10988  "TARGET_SH1"
10989{
10990  return       "mov.l	1f,r4"			"\n"
10991	 "	mova	2f,r0"			"\n"
10992	 "	mov.l	2f,r1"			"\n"
10993	 "	add	r0,r1"			"\n"
10994	 "	jsr	@r1"			"\n"
10995	 "	add	r12,r4"			"\n"
10996	 "	bra	3f"			"\n"
10997	 "	nop"				"\n"
10998	 "	.align	2"			"\n"
10999	 "1:	.long	%a1@TLSGD"		"\n"
11000	 "2:	.long	__tls_get_addr@PLT"	"\n"
11001	 "3:";
11002}
11003  [(set_attr "type" "tls_load")
11004   (set_attr "length" "26")])
11005
11006(define_insn "tls_local_dynamic"
11007  [(set (match_operand:SI 0 "register_operand" "=&z")
11008	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
11009				  UNSPEC_TLSLDM))
11010	      (const_int 0)))
11011   (use (reg:SI FPSCR_MODES_REG))
11012   (use (reg:SI PIC_REG))
11013   (clobber (reg:SI PR_REG))
11014   (clobber (scratch:SI))]
11015  "TARGET_SH1"
11016{
11017  return       "mov.l	1f,r4"			"\n"
11018	 "	mova	2f,r0"			"\n"
11019	 "	mov.l	2f,r1"			"\n"
11020	 "	add	r0,r1"			"\n"
11021	 "	jsr	@r1"			"\n"
11022	 "	add	r12,r4"			"\n"
11023	 "	bra	3f"			"\n"
11024	 "	nop"				"\n"
11025	 "	.align	2"			"\n"
11026	 "1:	.long	%a1@TLSLDM"		"\n"
11027	 "2:	.long	__tls_get_addr@PLT"	"\n"
11028	 "3:";
11029}
11030  [(set_attr "type" "tls_load")
11031   (set_attr "length" "26")])
11032
11033(define_expand "sym2DTPOFF"
11034  [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
11035  ""
11036  "")
11037
11038(define_expand "symDTPOFF2reg"
11039  [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
11040  ""
11041{
11042  rtx dtpoffsym;
11043  rtx t = (!can_create_pseudo_p ()
11044	   ? operands[0]
11045	   : gen_reg_rtx (GET_MODE (operands[0])));
11046
11047  dtpoffsym = gen_sym2DTPOFF (operands[1]);
11048  PUT_MODE (dtpoffsym, Pmode);
11049  emit_move_insn (t, dtpoffsym);
11050  emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
11051  DONE;
11052})
11053
11054(define_expand "sym2GOTTPOFF"
11055  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
11056  ""
11057  "")
11058
11059(define_insn "tls_initial_exec"
11060  [(set (match_operand:SI 0 "register_operand" "=&r")
11061	(unspec:SI [(match_operand:SI 1 "" "")]
11062		    UNSPEC_TLSIE))
11063   (use (reg:SI GBR_REG))
11064   (use (reg:SI PIC_REG))
11065   (clobber (reg:SI R0_REG))]
11066  ""
11067{
11068  return       "mov.l	1f,r0"		"\n"
11069	 "	stc	gbr,%0"		"\n"
11070	 "	mov.l	@(r0,r12),r0"	"\n"
11071	 "	bra	2f"		"\n"
11072	 "	add	r0,%0"		"\n"
11073	 "	.align	2"		"\n"
11074	 "1:	.long	%a1"		"\n"
11075	 "2:";
11076}
11077  [(set_attr "type" "tls_load")
11078   (set_attr "length" "16")])
11079
11080(define_expand "sym2TPOFF"
11081  [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
11082  ""
11083  "")
11084
11085(define_expand "symTPOFF2reg"
11086  [(match_operand 0 "" "") (match_operand 1 "" "")]
11087  ""
11088{
11089  rtx tpoffsym;
11090
11091  tpoffsym = gen_sym2TPOFF (operands[1]);
11092  PUT_MODE (tpoffsym, Pmode);
11093  emit_move_insn (operands[0], tpoffsym);
11094  DONE;
11095})
11096
11097;;------------------------------------------------------------------------------
11098;; Thread pointer getter and setter.
11099;;
11100;; On SH the thread pointer is kept in the GBR.
11101;; These patterns are usually expanded from the respective built-in functions.
11102(define_expand "get_thread_pointersi"
11103  [(set (match_operand:SI 0 "arith_reg_dest") (reg:SI GBR_REG))]
11104  "TARGET_SH1")
11105
11106;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
11107(define_insn "store_gbr"
11108  [(set (match_operand:SI 0 "arith_reg_dest" "=r") (reg:SI GBR_REG))]
11109  ""
11110  "stc	gbr,%0"
11111  [(set_attr "type" "tls_load")])
11112
11113(define_expand "set_thread_pointersi"
11114  [(set (reg:SI GBR_REG)
11115	(unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand")]
11116	 UNSPECV_GBR))]
11117  "TARGET_SH1")
11118
11119(define_insn "load_gbr"
11120  [(set (reg:SI GBR_REG)
11121	(unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand" "r")]
11122	 UNSPECV_GBR))]
11123  "TARGET_SH1"
11124  "ldc	%0,gbr"
11125  [(set_attr "type" "move")])
11126
11127;;------------------------------------------------------------------------------
11128;; Thread pointer relative memory loads and stores.
11129;;
11130;; On SH there are GBR displacement address modes which can be utilized to
11131;; access memory behind the thread pointer.
11132;; Since we do not allow using GBR for general purpose memory accesses, these
11133;; GBR addressing modes are formed by the combine pass.
11134;; This could be done with fewer patterns than below by using a mem predicate
11135;; for the GBR mem, but then reload would try to reload addresses with a
11136;; zero displacement for some strange reason.
11137
11138(define_insn "*mov<mode>_gbr_load"
11139  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z")
11140	(mem:QIHISI (plus:SI (reg:SI GBR_REG)
11141			     (match_operand:QIHISI 1 "gbr_displacement"))))]
11142  "TARGET_SH1"
11143  "mov.<bwl>	@(%O1,gbr),%0"
11144  [(set_attr "type" "load")])
11145
11146(define_insn "*mov<mode>_gbr_load"
11147  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z")
11148	(mem:QIHISI (reg:SI GBR_REG)))]
11149  "TARGET_SH1"
11150  "mov.<bwl>	@(0,gbr),%0"
11151  [(set_attr "type" "load")])
11152
11153(define_insn "*mov<mode>_gbr_load"
11154  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11155	(sign_extend:SI
11156	  (mem:QIHI (plus:SI (reg:SI GBR_REG)
11157			     (match_operand:QIHI 1 "gbr_displacement")))))]
11158  "TARGET_SH1"
11159  "mov.<bw>	@(%O1,gbr),%0"
11160  [(set_attr "type" "load")])
11161
11162(define_insn "*mov<mode>_gbr_load"
11163  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11164	(sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
11165  "TARGET_SH1"
11166  "mov.<bw>	@(0,gbr),%0"
11167  [(set_attr "type" "load")])
11168
11169(define_insn "*mov<mode>_gbr_store"
11170  [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
11171			     (match_operand:QIHISI 0 "gbr_displacement")))
11172	(match_operand:QIHISI 1 "register_operand" "z"))]
11173  "TARGET_SH1"
11174  "mov.<bwl>	%1,@(%O0,gbr)"
11175  [(set_attr "type" "store")])
11176
11177(define_insn "*mov<mode>_gbr_store"
11178  [(set (mem:QIHISI (reg:SI GBR_REG))
11179	(match_operand:QIHISI 0 "register_operand" "z"))]
11180  "TARGET_SH1"
11181  "mov.<bwl>	%0,@(0,gbr)"
11182  [(set_attr "type" "store")])
11183
11184;; DImode memory accesses have to be split in two SImode accesses.
11185;; Split them before reload, so that it gets a better chance to figure out
11186;; how to deal with the R0 restriction for the individual SImode accesses.
11187;; Do not match this insn during or after reload because it can't be split
11188;; afterwards.
11189(define_insn_and_split "*movdi_gbr_load"
11190  [(set (match_operand:DI 0 "arith_reg_dest")
11191	(match_operand:DI 1 "gbr_address_mem"))]
11192  "TARGET_SH1 && can_create_pseudo_p ()"
11193  "#"
11194  "&& 1"
11195  [(set (match_dup 3) (match_dup 5))
11196   (set (match_dup 4) (match_dup 6))]
11197{
11198  /* Swap low/high part load order on little endian, so that the result reg
11199     of the second load can be used better.  */
11200  int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
11201  operands[3 + off] = gen_lowpart (SImode, operands[0]);
11202  operands[5 + off] = gen_lowpart (SImode, operands[1]);
11203  operands[4 - off] = gen_highpart (SImode, operands[0]);
11204  operands[6 - off] = gen_highpart (SImode, operands[1]);
11205})
11206
11207(define_insn_and_split "*movdi_gbr_store"
11208  [(set (match_operand:DI 0 "gbr_address_mem")
11209	(match_operand:DI 1 "register_operand"))]
11210  "TARGET_SH1 && can_create_pseudo_p ()"
11211  "#"
11212  "&& 1"
11213  [(set (match_dup 3) (match_dup 5))
11214   (set (match_dup 4) (match_dup 6))]
11215{
11216  /* Swap low/high part store order on big endian, so that stores of function
11217     call results can save a reg copy.  */
11218  int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
11219  operands[3 + off] = gen_lowpart (SImode, operands[0]);
11220  operands[5 + off] = gen_lowpart (SImode, operands[1]);
11221  operands[4 - off] = gen_highpart (SImode, operands[0]);
11222  operands[6 - off] = gen_highpart (SImode, operands[1]);
11223})
11224
11225;; Sometimes memory accesses do not get combined with the store_gbr insn,
11226;; in particular when the displacements are in the range of the regular move
11227;; insns.  Thus, in the first split pass after the combine pass we search
11228;; for missed opportunities and try to fix them up ourselves.
11229;; If an equivalent GBR address can be determined the load / store is split
11230;; into one of the GBR load / store patterns.
11231;; All of that must happen before reload (GBR address modes use R0 as the
11232;; other operand) and there's no point of doing it if the GBR is not
11233;; referenced in a function at all.
11234(define_split
11235  [(set (match_operand:QIHISIDI 0 "register_operand")
11236	(match_operand:QIHISIDI 1 "memory_operand"))]
11237  "TARGET_SH1 && !reload_in_progress && !reload_completed
11238   && df_regs_ever_live_p (GBR_REG)"
11239  [(set (match_dup 0) (match_dup 1))]
11240{
11241  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
11242  if (gbr_mem != NULL_RTX)
11243    operands[1] = replace_equiv_address (operands[1], gbr_mem);
11244  else
11245    FAIL;
11246})
11247
11248(define_split
11249  [(set (match_operand:SI 0 "register_operand")
11250	(sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
11251  "TARGET_SH1 && !reload_in_progress && !reload_completed
11252   && df_regs_ever_live_p (GBR_REG)"
11253  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
11254{
11255  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
11256  if (gbr_mem != NULL_RTX)
11257    operands[1] = replace_equiv_address (operands[1], gbr_mem);
11258  else
11259    FAIL;
11260})
11261
11262;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
11263;; Split those so that a GBR load can be used.
11264(define_split
11265  [(set (match_operand:SI 0 "register_operand")
11266	(zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
11267  "TARGET_SH2A && !reload_in_progress && !reload_completed
11268   && df_regs_ever_live_p (GBR_REG)"
11269  [(set (match_dup 2) (match_dup 1))
11270   (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
11271{
11272  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
11273  if (gbr_mem != NULL_RTX)
11274    {
11275      operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
11276      operands[1] = replace_equiv_address (operands[1], gbr_mem);
11277    }
11278  else
11279    FAIL;
11280})
11281
11282(define_split
11283  [(set (match_operand:QIHISIDI 0 "memory_operand")
11284	(match_operand:QIHISIDI 1 "register_operand"))]
11285  "TARGET_SH1 && !reload_in_progress && !reload_completed
11286   && df_regs_ever_live_p (GBR_REG)"
11287  [(set (match_dup 0) (match_dup 1))]
11288{
11289  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
11290  if (gbr_mem != NULL_RTX)
11291    operands[0] = replace_equiv_address (operands[0], gbr_mem);
11292  else
11293    FAIL;
11294})
11295
11296;;------------------------------------------------------------------------------
11297;; case instruction for switch statements.
11298
11299;; operand 0 is index
11300;; operand 1 is the minimum bound
11301;; operand 2 is the maximum bound - minimum bound + 1
11302;; operand 3 is CODE_LABEL for the table;
11303;; operand 4 is the CODE_LABEL to go to if index out of range.
11304(define_expand "casesi"
11305  [(match_operand:SI 0 "arith_reg_operand" "")
11306   (match_operand:SI 1 "arith_reg_operand" "")
11307   (match_operand:SI 2 "arith_reg_operand" "")
11308   (match_operand 3 "" "") (match_operand 4 "" "")]
11309  ""
11310{
11311  rtx reg = gen_reg_rtx (SImode);
11312  rtx reg2 = gen_reg_rtx (SImode);
11313  if (TARGET_SHMEDIA)
11314    {
11315      rtx reg = gen_reg_rtx (DImode);
11316      rtx reg2 = gen_reg_rtx (DImode);
11317      rtx reg3 = gen_reg_rtx (Pmode);
11318      rtx reg4 = gen_reg_rtx (Pmode);
11319      rtx reg5 = gen_reg_rtx (Pmode);
11320      rtx load, test;
11321
11322      operands[0] = convert_modes (DImode, SImode, operands[0], 0);
11323      operands[1] = convert_modes (DImode, SImode, operands[1], 0);
11324      operands[2] = convert_modes (DImode, SImode, operands[2], 1);
11325
11326      test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
11327      emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0],
11328				      operands[4]));
11329      emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
11330      test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
11331      emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
11332      emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
11333      emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
11334					       (Pmode, operands[3])));
11335      /* Messy: can we subreg to clean this up? */
11336      if (Pmode == DImode)
11337	load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
11338      else
11339	load = gen_casesi_load_media (reg4,
11340				      gen_rtx_SUBREG (DImode, reg3, 0),
11341				      reg2, operands[3]);
11342      PUT_MODE (SET_SRC (load), Pmode);
11343      emit_insn (load);
11344      /* ??? The following add could be eliminated if we used ptrel.  */
11345      emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
11346      emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
11347      emit_barrier ();
11348      DONE;
11349    }
11350  operands[1] = copy_to_mode_reg (SImode, operands[1]);
11351  operands[2] = copy_to_mode_reg (SImode, operands[2]);
11352  /* If optimizing, casesi_worker depends on the mode of the instruction
11353     before label it 'uses' - operands[3].  */
11354  emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
11355			   reg));
11356  emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
11357  if (TARGET_SH2)
11358    emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
11359  else
11360    emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
11361  /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
11362     operands[3], but to lab.  We will fix this up in
11363     machine_dependent_reorg.  */
11364  emit_barrier ();
11365  DONE;
11366})
11367
11368(define_expand "casesi_0"
11369  [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
11370   (set (match_dup 4) (minus:SI (match_dup 4)
11371				(match_operand:SI 1 "arith_operand" "")))
11372   (set (reg:SI T_REG)
11373	(gtu:SI (match_dup 4)
11374		(match_operand:SI 2 "arith_reg_operand" "")))
11375   (set (pc)
11376	(if_then_else (ne (reg:SI T_REG)
11377			  (const_int 0))
11378		      (label_ref (match_operand 3 "" ""))
11379		      (pc)))]
11380  "TARGET_SH1"
11381  "")
11382
11383;; ??? reload might clobber r0 if we use it explicitly in the RTL before
11384;; reload; using a R0_REGS pseudo reg is likely to give poor code.
11385;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
11386;;
11387;; The use on the T_REG in the casesi_worker* patterns links the bounds
11388;; checking insns and the table memory access.  See also PR 69713.
11389(define_insn "casesi_worker_0"
11390  [(set (match_operand:SI 0 "register_operand" "=r,r")
11391	(unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
11392		 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11393   (clobber (match_scratch:SI 3 "=X,1"))
11394   (clobber (match_scratch:SI 4 "=&z,z"))
11395   (use (reg:SI T_REG))]
11396  "TARGET_SH1"
11397  "#")
11398
11399(define_split
11400  [(set (match_operand:SI 0 "register_operand" "")
11401	(unspec:SI [(match_operand:SI 1 "register_operand" "")
11402		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11403   (clobber (match_scratch:SI 3 ""))
11404   (clobber (match_scratch:SI 4))
11405   (use (reg:SI T_REG))]
11406  "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
11407  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
11408   (parallel [(set (match_dup 0)
11409	      (unspec:SI [(reg:SI R0_REG) (match_dup 1)
11410			  (label_ref (match_dup 2))] UNSPEC_CASESI))
11411	      (clobber (match_dup 3))])
11412   (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
11413{
11414  if (GET_CODE (operands[2]) == CODE_LABEL)
11415    LABEL_NUSES (operands[2])++;
11416})
11417
11418(define_split
11419  [(set (match_operand:SI 0 "register_operand" "")
11420	(unspec:SI [(match_operand:SI 1 "register_operand" "")
11421		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11422   (clobber (match_scratch:SI 3 ""))
11423   (clobber (match_scratch:SI 4))
11424   (use (reg:SI T_REG))]
11425  "TARGET_SH2 && reload_completed"
11426  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
11427   (parallel [(set (match_dup 0)
11428	      (unspec:SI [(reg:SI R0_REG) (match_dup 1)
11429			  (label_ref (match_dup 2))] UNSPEC_CASESI))
11430	      (clobber (match_dup 3))])]
11431{
11432  if (GET_CODE (operands[2]) == CODE_LABEL)
11433    LABEL_NUSES (operands[2])++;
11434})
11435
11436;; This may be replaced with casesi_worker_2 in sh_reorg for PIC.
11437;; The insn length is set to 8 for that case.
11438(define_insn "casesi_worker_1"
11439  [(set (match_operand:SI 0 "register_operand" "=r,r")
11440	(unspec:SI [(reg:SI R0_REG)
11441		    (match_operand:SI 1 "register_operand" "0,r")
11442		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11443   (clobber (match_scratch:SI 3 "=X,1"))]
11444  "TARGET_SH1"
11445{
11446  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
11447
11448  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11449
11450  switch (GET_MODE (diff_vec))
11451    {
11452    case SImode:
11453      return   "shll2	%1"	"\n"
11454	     "	mov.l	@(r0,%1),%0";
11455    case HImode:
11456      return   "add	%1,%1"	"\n"
11457	     "	mov.w	@(r0,%1),%0";
11458    case QImode:
11459      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11460	return         "mov.b	@(r0,%1),%0"	"\n"
11461	       "	extu.b	%0,%0";
11462      else
11463	return "mov.b	@(r0,%1),%0";
11464
11465    default:
11466      gcc_unreachable ();
11467    }
11468}
11469  [(set_attr_alternative "length"
11470     [(if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))
11471      (if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))])])
11472
11473(define_insn "casesi_worker_2"
11474  [(set (match_operand:SI 0 "register_operand" "=r,r")
11475	(unspec:SI [(reg:SI R0_REG)
11476		    (match_operand:SI 1 "register_operand" "0,r")
11477		    (label_ref (match_operand 2 "" ""))
11478		    (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
11479   (clobber (match_operand:SI 4 "" "=X,1"))]
11480  "TARGET_SH2 && reload_completed && flag_pic"
11481{
11482  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
11483  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11484
11485  switch (GET_MODE (diff_vec))
11486    {
11487    case SImode:
11488      return   "shll2	%1"		"\n"
11489	     "	add	r0,%1"		"\n"
11490	     "	mova	%O3,r0"		"\n"
11491	     "  mov.l	@(r0,%1),%0";
11492    case HImode:
11493      return   "add	%1,%1"		"\n"
11494	     "	add	r0,%1"		"\n"
11495	     "	mova	%O3,r0"		"\n"
11496	     "	mov.w	@(r0,%1),%0";
11497    case QImode:
11498      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11499	return	       "add	r0,%1"		"\n"
11500		"	mova	%O3,r0"		"\n"
11501		"	mov.b	@(r0,%1),%0"	"\n"
11502		"	extu.b	%0,%0";
11503      else
11504	return	       "add	r0,%1"		"\n"
11505		"	mova	%O3,r0"		"\n"
11506		"	mov.b	@(r0,%1),%0";
11507    default:
11508      gcc_unreachable ();
11509    }
11510}
11511  [(set_attr "length" "8")])
11512
11513(define_insn "casesi_shift_media"
11514  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11515	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
11516		   (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
11517		    UNSPEC_CASESI)))]
11518  "TARGET_SHMEDIA"
11519{
11520  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
11521
11522  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11523
11524  switch (GET_MODE (diff_vec))
11525    {
11526    case SImode:
11527      return "shlli	%1, 2, %0";
11528    case HImode:
11529      return "shlli	%1, 1, %0";
11530    case QImode:
11531      if (rtx_equal_p (operands[0], operands[1]))
11532	return "";
11533      return "add	%1, r63, %0";
11534    default:
11535      gcc_unreachable ();
11536    }
11537}
11538  [(set_attr "type" "arith_media")])
11539
11540(define_insn "casesi_load_media"
11541  [(set (match_operand 0 "any_arith_reg_dest" "=r")
11542	(mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
11543		      (match_operand:DI 2 "arith_reg_operand" "r")
11544		      (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
11545  "TARGET_SHMEDIA"
11546{
11547  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[3])));
11548
11549  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11550
11551  switch (GET_MODE (diff_vec))
11552    {
11553    case SImode:
11554      return "ldx.l	%1, %2, %0";
11555    case HImode:
11556#if 0
11557      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11558	return "ldx.uw	%1, %2, %0";
11559#endif
11560      return "ldx.w	%1, %2, %0";
11561    case QImode:
11562      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11563	return "ldx.ub	%1, %2, %0";
11564      return "ldx.b	%1, %2, %0";
11565    default:
11566      gcc_unreachable ();
11567    }
11568}
11569  [(set_attr "type" "load_media")])
11570
11571(define_expand "simple_return"
11572  [(simple_return)]
11573 "sh_can_use_simple_return_p ()")
11574
11575(define_expand "return"
11576  [(return)]
11577 "reload_completed && epilogue_completed"
11578{
11579  if (TARGET_SHMEDIA)
11580    {
11581      emit_jump_insn (gen_return_media ());
11582      DONE;
11583    }
11584
11585  if (TARGET_SHCOMPACT
11586      && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
11587    {
11588      emit_jump_insn (gen_shcompact_return_tramp ());
11589      DONE;
11590    }
11591})
11592
11593(define_insn "*<code>_i"
11594  [(any_return)]
11595  "TARGET_SH1 && ! (TARGET_SHCOMPACT
11596		    && (crtl->args.info.call_cookie
11597			& CALL_COOKIE_RET_TRAMP (1)))
11598   && reload_completed
11599   && ! sh_cfun_trap_exit_p ()"
11600{
11601  if (TARGET_SH2A && (dbr_sequence_length () == 0)
11602      && !current_function_interrupt)
11603    return "rts/n";
11604  else
11605    return "%@	%#";
11606}
11607  [(set_attr "type" "return")
11608   (set_attr "needs_delay_slot" "yes")])
11609
11610;; trapa has no delay slot.
11611(define_insn "*return_trapa"
11612  [(return)]
11613  "TARGET_SH1 && !TARGET_SHCOMPACT
11614   && reload_completed"
11615  "%@"
11616  [(set_attr "type" "return")])
11617
11618(define_expand "shcompact_return_tramp"
11619  [(return)]
11620  "TARGET_SHCOMPACT
11621   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11622{
11623  rtx reg = gen_rtx_REG (Pmode, R0_REG);
11624
11625  function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
11626  emit_jump_insn (gen_shcompact_return_tramp_i ());
11627  DONE;
11628})
11629
11630(define_insn "shcompact_return_tramp_i"
11631  [(parallel [(return) (use (reg:SI R0_REG))])]
11632  "TARGET_SHCOMPACT
11633   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11634  "jmp	@r0%#"
11635  [(set_attr "type" "jump_ind")
11636   (set_attr "needs_delay_slot" "yes")])
11637
11638(define_insn "return_media_i"
11639  [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
11640  "TARGET_SHMEDIA && reload_completed"
11641  "blink	%0, r63"
11642  [(set_attr "type" "jump_media")])
11643
11644(define_insn "return_media_rte"
11645  [(return)]
11646  "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
11647  "rte"
11648  [(set_attr "type" "jump_media")])
11649
11650(define_expand "return_media"
11651  [(return)]
11652  "TARGET_SHMEDIA && reload_completed"
11653{
11654  int tr_regno = sh_media_register_for_return ();
11655  rtx tr;
11656
11657  if (current_function_interrupt)
11658    {
11659      emit_jump_insn (gen_return_media_rte ());
11660      DONE;
11661    }
11662  if (tr_regno < 0)
11663    {
11664      rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
11665
11666      gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
11667      tr_regno = TR0_REG;
11668      tr = gen_rtx_REG (Pmode, tr_regno);
11669      emit_move_insn (tr, r18);
11670    }
11671  else
11672    tr = gen_rtx_REG (Pmode, tr_regno);
11673
11674  emit_jump_insn (gen_return_media_i (tr));
11675  DONE;
11676})
11677
11678(define_insn "shcompact_preserve_incoming_args"
11679  [(set (match_operand:SI 0 "register_operand" "+r")
11680	(unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
11681  "TARGET_SHCOMPACT"
11682  ""
11683  [(set_attr "length" "0")])
11684
11685(define_insn "shcompact_incoming_args"
11686  [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
11687   (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
11688   (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
11689   (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
11690   (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
11691   (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
11692   (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
11693   (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
11694   (set (mem:BLK (reg:SI MACL_REG))
11695	(unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
11696   (use (reg:SI R0_REG))
11697   (clobber (reg:SI R0_REG))
11698   (clobber (reg:SI MACL_REG))
11699   (clobber (reg:SI MACH_REG))
11700   (clobber (reg:SI PR_REG))]
11701  "TARGET_SHCOMPACT"
11702  "jsr	@r0%#"
11703  [(set_attr "needs_delay_slot" "yes")])
11704
11705(define_insn "shmedia_save_restore_regs_compact"
11706  [(set (reg:SI SP_REG)
11707	(plus:SI (reg:SI SP_REG)
11708		 (match_operand:SI 0 "immediate_operand" "i")))
11709   (use (reg:SI R0_REG))
11710   (clobber (reg:SI PR_REG))]
11711  "TARGET_SHCOMPACT
11712   && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
11713       || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
11714  "jsr @r0%#"
11715  [(set_attr "needs_delay_slot" "yes")])
11716
11717(define_expand "prologue"
11718  [(const_int 0)]
11719  ""
11720{
11721  sh_expand_prologue ();
11722  DONE;
11723})
11724
11725(define_expand "epilogue"
11726  [(return)]
11727  ""
11728{
11729  sh_expand_epilogue (false);
11730  if (TARGET_SHMEDIA
11731      || (TARGET_SHCOMPACT
11732	  && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
11733    {
11734      emit_jump_insn (gen_return ());
11735      DONE;
11736    }
11737})
11738
11739(define_expand "eh_return"
11740  [(use (match_operand 0 "register_operand" ""))]
11741  ""
11742{
11743  rtx ra = operands[0];
11744
11745  if (TARGET_SHMEDIA64)
11746    emit_insn (gen_eh_set_ra_di (ra));
11747  else
11748    emit_insn (gen_eh_set_ra_si (ra));
11749
11750  DONE;
11751})
11752
11753;; Clobber the return address on the stack.  We can't expand this
11754;; until we know where it will be put in the stack frame.
11755
11756(define_insn "eh_set_ra_si"
11757  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
11758      UNSPECV_EH_RETURN)
11759   (clobber (match_scratch:SI 1 "=&r"))]
11760  "! TARGET_SHMEDIA64"
11761  "#")
11762
11763(define_insn "eh_set_ra_di"
11764  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
11765      UNSPECV_EH_RETURN)
11766   (clobber (match_scratch:DI 1 "=&r"))]
11767  "TARGET_SHMEDIA64"
11768  "#")
11769
11770(define_split
11771  [(unspec_volatile [(match_operand 0 "register_operand" "")]
11772      UNSPECV_EH_RETURN)
11773   (clobber (match_scratch 1 ""))]
11774  "reload_completed"
11775  [(const_int 0)]
11776{
11777  sh_set_return_address (operands[0], operands[1]);
11778  DONE;
11779})
11780
11781(define_insn "blockage"
11782  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
11783  ""
11784  ""
11785  [(set_attr "length" "0")])
11786
11787;; Define movml instructions for SH2A target.  Currently they are
11788;; used to push and pop all banked registers only.
11789
11790(define_insn "movml_push_banked"
11791  [(set (match_operand:SI 0 "register_operand" "=r")
11792	  (plus (match_dup 0) (const_int -32)))
11793   (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
11794   (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
11795   (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
11796   (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
11797   (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
11798   (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
11799   (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
11800   (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
11801  "TARGET_SH2A && REGNO (operands[0]) == 15"
11802  "movml.l	r7,@-r15"
11803  [(set_attr "in_delay_slot" "no")])
11804
11805(define_insn "movml_pop_banked"
11806  [(set (match_operand:SI 0 "register_operand" "=r")
11807	  (plus (match_dup 0) (const_int 32)))
11808   (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
11809   (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
11810   (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
11811   (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
11812   (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
11813   (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
11814   (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
11815   (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
11816  "TARGET_SH2A && REGNO (operands[0]) == 15"
11817  "movml.l	@r15+,r7"
11818  [(set_attr "in_delay_slot" "no")])
11819
11820;; ------------------------------------------------------------------------
11821;; Scc instructions
11822;; ------------------------------------------------------------------------
11823
11824(define_insn "movt"
11825  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11826	(match_operand:SI 1 "t_reg_operand"))]
11827  "TARGET_SH1"
11828  "movt	%0"
11829  [(set_attr "type" "arith")])
11830
11831(define_insn "movrt"
11832  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11833	(xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11834  "TARGET_SH2A"
11835  "movrt	%0"
11836  [(set_attr "type" "arith")])
11837
11838(define_expand "cstore4_media"
11839  [(set (match_operand:SI 0 "register_operand" "=r")
11840	(match_operator:SI 1 "sh_float_comparison_operator"
11841	 [(match_operand 2 "logical_operand" "")
11842	  (match_operand 3 "cmp_operand" "")]))]
11843  "TARGET_SHMEDIA"
11844{
11845  machine_mode mode = GET_MODE (operands[2]);
11846  enum rtx_code code = GET_CODE (operands[1]);
11847  bool invert, swap;
11848  if (mode == VOIDmode)
11849    mode = GET_MODE (operands[3]);
11850  if (operands[2] == const0_rtx)
11851    {
11852      if (code == EQ || code == NE)
11853	operands[2] = operands[3], operands[3] = const0_rtx;
11854    }
11855  else
11856    operands[2] = force_reg (mode, operands[2]);
11857  if (operands[3] != const0_rtx)
11858    operands[3] = force_reg (mode, operands[3]);
11859
11860  switch (code)
11861    {
11862    case GEU:
11863    case GE:
11864      swap = invert = !FLOAT_MODE_P (mode);
11865      break;
11866
11867    case LEU:
11868    case LE:
11869      swap = FLOAT_MODE_P (mode), invert = !swap;
11870      break;
11871
11872    case LTU:
11873    case LT:
11874      swap = true, invert = false;
11875      break;
11876
11877    case GTU:
11878    case GT:
11879    case EQ:
11880    case UNORDERED:
11881      swap = invert = false;
11882      break;
11883
11884    case NE:
11885      swap = invert = true;
11886      break;
11887
11888    default:
11889      gcc_unreachable ();
11890  }
11891
11892  if (swap)
11893    {
11894      std::swap (operands[2], operands[3]);
11895      code = swap_condition (code);
11896    }
11897
11898  if (invert)
11899    {
11900      rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
11901      code = reverse_condition (code);
11902      operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11903      emit_insn (gen_cstore4_media (tem, operands[1],
11904				    operands[2], operands[3]));
11905      code = EQ;
11906      operands[2] = tem;
11907      operands[3] = const0_rtx;
11908    }
11909
11910  operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11911})
11912
11913(define_expand "cstoresi4"
11914  [(set (match_operand:SI 0 "register_operand" "=r")
11915	(match_operator:SI 1 "comparison_operator"
11916	 [(match_operand:SI 2 "cmpsi_operand" "")
11917	  (match_operand:SI 3 "arith_operand" "")]))]
11918  "TARGET_SH1 || TARGET_SHMEDIA"
11919{
11920  if (TARGET_SHMEDIA)
11921    {
11922      emit_insn (gen_cstore4_media (operands[0], operands[1],
11923				    operands[2], operands[3]));
11924      DONE;
11925    }
11926
11927   if (sh_expand_t_scc (operands))
11928     DONE;
11929
11930   if (! currently_expanding_to_rtl)
11931     FAIL;
11932   
11933   sh_emit_compare_and_set (operands, SImode);
11934   DONE;
11935})
11936
11937(define_expand "cstoredi4"
11938  [(set (match_operand:SI 0 "register_operand" "=r")
11939	(match_operator:SI 1 "comparison_operator"
11940	 [(match_operand:DI 2 "arith_operand" "")
11941	  (match_operand:DI 3 "arith_operand" "")]))]
11942  "TARGET_SH2 || TARGET_SHMEDIA"
11943{
11944  if (TARGET_SHMEDIA)
11945    {
11946      emit_insn (gen_cstore4_media (operands[0], operands[1],
11947				    operands[2], operands[3]));
11948      DONE;
11949    }
11950
11951   if (sh_expand_t_scc (operands))
11952     DONE;
11953
11954   if (! currently_expanding_to_rtl)
11955     FAIL;
11956   
11957   sh_emit_compare_and_set (operands, DImode);
11958   DONE;
11959})
11960
11961;; Move the complement of the T reg to a reg.
11962;; On SH2A the movrt insn can be used.
11963;; On anything else than SH2A this has to be done with multiple instructions.
11964;; One obvious way would be:
11965;;	cmp/eq	...
11966;;	movt	r0
11967;;	xor	#1,r0
11968;;
11969;; However, this puts pressure on r0 in most cases and thus the following is
11970;; more appealing:
11971;;	cmp/eq	...
11972;;	mov	#-1,temp
11973;;	negc	temp,dest
11974;;
11975;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11976;; becomes a one instruction operation.  Moreover, care must be taken that
11977;; the insn can still be combined with inverted compare and branch code
11978;; around it.  On the other hand, if a function returns the complement of
11979;; a previous comparison result in the T bit, the xor #1,r0 approach might
11980;; lead to better code.
11981(define_expand "movnegt"
11982  [(set (match_operand:SI 0 "arith_reg_dest" "")
11983	(xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11984  "TARGET_SH1"
11985{
11986  if (TARGET_SH2A)
11987    emit_insn (gen_movrt (operands[0], operands[1]));
11988  else
11989    {
11990      rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
11991      emit_insn (gen_movrt_negc (operands[0], operands[1], val));
11992    }
11993  DONE;
11994})
11995
11996(define_insn_and_split "movrt_negc"
11997  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11998	(xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11999   (set (reg:SI T_REG) (const_int 1))
12000   (use (match_operand:SI 2 "arith_reg_operand" "r"))]
12001  "TARGET_SH1"
12002  "negc	%2,%0"
12003  "&& !sh_in_recog_treg_set_expr ()"
12004  [(const_int 0)]
12005{
12006  if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands))
12007    DONE;
12008  else
12009    FAIL;
12010}
12011  [(set_attr "type" "arith")])
12012
12013;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
12014;; pattern can be used by the combine pass.  Using a scratch reg for the
12015;; -1 constant results in slightly better register allocations compared to
12016;; generating a pseudo reg before reload.
12017(define_insn_and_split "*movrt_negc"
12018  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12019	(xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
12020   (clobber (match_scratch:SI 2 "=r"))
12021   (clobber (reg:SI T_REG))]
12022  "TARGET_SH1 && ! TARGET_SH2A"
12023  "#"
12024  "&& !sh_in_recog_treg_set_expr ()"
12025  [(const_int 0)]
12026{
12027  if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands))
12028    DONE;
12029  else if (reload_completed)
12030    {
12031      emit_move_insn (operands[2], gen_int_mode (-1, SImode));
12032      emit_insn (gen_movrt_negc (operands[0], operands[1], operands[2]));
12033      DONE;
12034    }
12035  else
12036    FAIL;
12037})
12038
12039;; Store the negated T bit in a reg using r0 and xor.  This one doesn't
12040;; clobber the T bit, which is useful when storing the T bit and the
12041;; negated T bit in parallel.  On SH2A the movrt insn can be used for that.
12042;; Usually we don't want this insn to be matched, except for cases where the
12043;; T bit clobber is really not appreciated.  Hence the extra use on T_REG.
12044(define_insn_and_split "movrt_xor"
12045  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
12046	(xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
12047   (use (reg:SI T_REG))]
12048  "TARGET_SH1"
12049  "#"
12050  "&& reload_completed"
12051  [(set (match_dup 0) (reg:SI T_REG))
12052   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
12053
12054;; Use negc to store the T bit in a MSB of a reg in the following way:
12055;;	T = 0: 0x80000000 -> reg
12056;;	T = 1: 0x7FFFFFFF -> reg
12057;; This works because 0 - 0x80000000 = 0x80000000.
12058(define_insn_and_split "*mov_t_msb_neg"
12059  [(set (match_operand:SI 0 "arith_reg_dest")
12060	(minus:SI (const_int -2147483648)  ;; 0x80000000
12061		  (match_operand 1 "treg_set_expr")))
12062   (clobber (reg:SI T_REG))]
12063  "TARGET_SH1 && can_create_pseudo_p ()"
12064  "#"
12065  "&& 1"
12066  [(const_int 0)]
12067{
12068  if (negt_reg_operand (operands[1], VOIDmode))
12069    {
12070      emit_insn (gen_addc (operands[0],
12071			   force_reg (SImode, const0_rtx),
12072			   force_reg (SImode, GEN_INT (2147483647))));
12073      DONE;
12074    }
12075
12076  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12077  if (ti.remove_trailing_nott ())
12078    emit_insn (gen_addc (operands[0],
12079			 force_reg (SImode, const0_rtx),
12080			 force_reg (SImode, GEN_INT (2147483647))));
12081  else
12082    emit_insn (gen_negc (operands[0],
12083			 force_reg (SImode, GEN_INT (-2147483648LL))));
12084  DONE;
12085})
12086
12087;; 0x7fffffff + T
12088;; 0x7fffffff + (1-T) = 0 - 0x80000000 - T
12089(define_insn_and_split "*mov_t_msb_neg"
12090  [(set (match_operand:SI 0 "arith_reg_dest")
12091	(plus:SI (match_operand 1 "treg_set_expr")
12092		 (const_int 2147483647)))  ;; 0x7fffffff
12093   (clobber (reg:SI T_REG))]
12094  "TARGET_SH1"
12095   "#"
12096   "&& can_create_pseudo_p ()"
12097  [(const_int 0)]
12098{
12099  if (negt_reg_operand (operands[1], VOIDmode))
12100    {
12101      emit_insn (gen_negc (operands[0],
12102			   force_reg (SImode, GEN_INT (-2147483648LL))));
12103      DONE;
12104    }
12105
12106  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12107  if (ti.remove_trailing_nott ())
12108    emit_insn (gen_negc (operands[0],
12109			 force_reg (SImode, GEN_INT (-2147483648LL))));
12110  else
12111    emit_insn (gen_addc (operands[0],
12112			 force_reg (SImode, const0_rtx),
12113			 force_reg (SImode, GEN_INT (2147483647))));
12114  DONE;
12115})
12116
12117(define_insn_and_split "*mov_t_msb_neg"
12118  [(set (match_operand:SI 0 "arith_reg_dest")
12119	(if_then_else:SI (match_operand 1 "treg_set_expr")
12120			 (match_operand 2 "const_int_operand")
12121			 (match_operand 3 "const_int_operand")))
12122   (clobber (reg:SI T_REG))]
12123  "TARGET_SH1 && can_create_pseudo_p ()
12124   && ((INTVAL (operands[2]) == -2147483648LL
12125	&& INTVAL (operands[3]) == 2147483647LL)
12126       || (INTVAL (operands[2]) == 2147483647LL
12127	   && INTVAL (operands[3]) == -2147483648LL))"
12128  "#"
12129  "&& 1"
12130  [(const_int 0)]
12131{
12132  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12133
12134  if (INTVAL (operands[2]) == -2147483648LL)
12135    {
12136      if (ti.remove_trailing_nott ())
12137	emit_insn (gen_negc (operands[0],
12138			     force_reg (SImode, GEN_INT (-2147483648LL))));
12139      else
12140	emit_insn (gen_addc (operands[0],
12141			     force_reg (SImode, const0_rtx),
12142			     force_reg (SImode, operands[3])));
12143      DONE;
12144    }
12145  else if (INTVAL (operands[2]) == 2147483647LL)
12146    {
12147      if (ti.remove_trailing_nott ())
12148	emit_insn (gen_addc (operands[0],
12149			     force_reg (SImode, const0_rtx),
12150			     force_reg (SImode, GEN_INT (2147483647LL))));
12151      else
12152	emit_insn (gen_negc (operands[0],
12153			     force_reg (SImode, GEN_INT (-2147483648LL))));
12154      DONE;
12155    }
12156  else
12157    gcc_unreachable ();
12158})
12159
12160;; The *negnegt pattern helps the combine pass to figure out how to fold 
12161;; an explicit double T bit negation.
12162(define_insn_and_split "*negnegt"
12163  [(set (reg:SI T_REG)
12164	(eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
12165  "TARGET_SH1"
12166  "#"
12167  ""
12168  [(const_int 0)])
12169
12170;; Store (negated) T bit as all zeros or ones in a reg.
12171;;	subc	Rn,Rn	! Rn = Rn - Rn - T; T = T
12172;;	not	Rn,Rn	! Rn = 0 - Rn
12173(define_insn_and_split "mov_neg_si_t"
12174  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12175	(neg:SI (match_operand 1 "treg_set_expr")))]
12176  "TARGET_SH1"
12177{
12178  gcc_assert (t_reg_operand (operands[1], VOIDmode));
12179  return "subc	%0,%0";
12180}
12181  "&& can_create_pseudo_p () && !t_reg_operand (operands[1], VOIDmode)"
12182  [(const_int 0)]
12183{
12184  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12185  emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
12186
12187  if (ti.remove_trailing_nott ())
12188    emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
12189
12190  DONE;
12191}
12192  [(set_attr "type" "arith")])
12193
12194;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
12195(define_insn_and_split "*movtt"
12196  [(set (reg:SI T_REG)
12197	(eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
12198  "TARGET_SH1"
12199  "#"
12200  ""
12201  [(const_int 0)])
12202
12203;; Invert the T bit.
12204;; On SH2A we can use the nott insn.  On anything else this must be done with
12205;; multiple insns like:
12206;;	movt	Rn
12207;;	tst	Rn,Rn
12208;; This requires an additional pseudo.  The SH specific sh_treg_combine RTL
12209;; pass will look for this insn.  Disallow using it if pseudos can't be
12210;; created.
12211;; Don't split the nott inside the splitting of a treg_set_expr, or else
12212;; surrounding insns might not see and recombine it.  Defer the splitting
12213;; of the nott until after the whole insn containing the treg_set_expr
12214;; has been split.
12215(define_insn_and_split "nott"
12216  [(set (reg:SI T_REG)
12217	(xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))]
12218  "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())"
12219{
12220  gcc_assert (TARGET_SH2A);
12221  return "nott";
12222}
12223  "!TARGET_SH2A && can_create_pseudo_p () && !sh_in_recog_treg_set_expr ()"
12224  [(set (match_dup 0) (reg:SI T_REG))
12225   (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
12226{
12227  operands[0] = gen_reg_rtx (SImode);
12228})
12229
12230;; Store T bit as MSB in a reg.
12231;; T = 0: 0x00000000 -> reg
12232;; T = 1: 0x80000000 -> reg
12233(define_insn_and_split "*movt_msb"
12234  [(set (match_operand:SI 0 "arith_reg_dest")
12235	(mult:SI (match_operand:SI 1 "t_reg_operand")
12236		 (const_int -2147483648)))  ;; 0xffffffff80000000
12237   (clobber (reg:SI T_REG))]
12238  "TARGET_SH1"
12239  "#"
12240  "&& 1"
12241  [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
12242
12243;; Store inverted T bit as MSB in a reg.
12244;; T = 0: 0x80000000 -> reg
12245;; T = 1: 0x00000000 -> reg
12246;; On SH2A we can get away without clobbering the T_REG using the movrt insn.
12247;; On non SH2A we resort to the following sequence:
12248;;	movt	Rn
12249;;	tst	Rn,Rn
12250;;	rotcr	Rn
12251;; The T bit value will be modified during the sequence, but the rotcr insn
12252;; will restore its original value.
12253(define_insn_and_split "*negt_msb"
12254  [(set (match_operand:SI 0 "arith_reg_dest")
12255	(match_operand:SI 1 "negt_reg_shl31_operand"))]
12256  "TARGET_SH1"
12257  "#"
12258  "&& can_create_pseudo_p ()"
12259  [(const_int 0)]
12260{
12261  rtx tmp = gen_reg_rtx (SImode);
12262
12263  if (TARGET_SH2A)
12264    {
12265      emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
12266      emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
12267    }
12268  else
12269    {
12270      emit_move_insn (tmp, get_t_reg_rtx ());
12271      emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
12272      emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
12273    }
12274  DONE;
12275})
12276
12277;; The *cset_zero patterns convert optimizations such as
12278;;	"if (test) x = 0;"
12279;; to
12280;;	"x &= -(test == 0);"
12281;; back to conditional branch sequences if zero-displacement branches
12282;; are enabled.
12283;; FIXME: These patterns can be removed when conditional execution patterns
12284;; are implemented, since ifcvt will not perform these optimizations if
12285;; conditional execution is supported.
12286(define_insn "*cset_zero"
12287  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12288	(and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
12289			 (const_int -1))
12290		(match_operand:SI 2 "arith_reg_operand" "0")))]
12291  "TARGET_SH1 && TARGET_ZDCBRANCH"
12292{
12293  return       "bf	0f"	"\n"
12294	 "	mov	#0,%0"	"\n"
12295	 "0:";
12296}
12297  [(set_attr "type" "arith") ;; poor approximation
12298   (set_attr "length" "4")])
12299
12300(define_insn "*cset_zero"
12301  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12302	(if_then_else:SI (match_operand:SI 1 "cbranch_treg_value")
12303			 (match_operand:SI 2 "arith_reg_operand" "0")
12304			 (const_int 0)))]
12305  "TARGET_SH1 && TARGET_ZDCBRANCH"
12306{
12307  int tval = sh_eval_treg_value (operands[1]);
12308  if (tval == true)
12309    return     "bt	0f"	"\n"
12310	   "	mov	#0,%0"	"\n"
12311	   "0:";
12312  else if (tval == false)
12313    return     "bf	0f"	"\n"
12314	   "	mov	#0,%0"	"\n"
12315	   "0:";
12316  else
12317    gcc_unreachable ();
12318}
12319  [(set_attr "type" "arith") ;; poor approximation
12320   (set_attr "length" "4")])
12321
12322(define_expand "cstoresf4"
12323  [(set (match_operand:SI 0 "register_operand" "=r")
12324	(match_operator:SI 1 "sh_float_comparison_operator"
12325	 [(match_operand:SF 2 "arith_operand" "")
12326	  (match_operand:SF 3 "arith_operand" "")]))]
12327  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12328{
12329  if (TARGET_SHMEDIA)
12330    {
12331      emit_insn (gen_cstore4_media (operands[0], operands[1],
12332				    operands[2], operands[3]));
12333      DONE;
12334    }
12335
12336  if (! currently_expanding_to_rtl)
12337    FAIL;
12338   
12339  sh_emit_compare_and_set (operands, SFmode);
12340  DONE;
12341})
12342
12343(define_expand "cstoredf4"
12344  [(set (match_operand:SI 0 "register_operand" "=r")
12345	(match_operator:SI 1 "sh_float_comparison_operator"
12346	 [(match_operand:DF 2 "arith_operand" "")
12347	  (match_operand:DF 3 "arith_operand" "")]))]
12348  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12349{
12350  if (TARGET_SHMEDIA)
12351    {
12352      emit_insn (gen_cstore4_media (operands[0], operands[1],
12353				    operands[2], operands[3]));
12354      DONE;
12355    }
12356
12357  if (! currently_expanding_to_rtl)
12358    FAIL;
12359   
12360  sh_emit_compare_and_set (operands, DFmode);
12361  DONE;
12362})
12363
12364;; Sometimes the T bit result of insns is needed in normal registers.
12365;; Instead of open coding all the pattern variations, use the treg_set_expr
12366;; predicate to match any T bit output insn and split it out after.
12367;; This pattern should be below all other related patterns so that it is
12368;; considered as a last resort option during matching.   This allows
12369;; overriding it with special case patterns.
12370(define_insn_and_split "any_treg_expr_to_reg"
12371  [(set (match_operand:SI 0 "arith_reg_dest")
12372	(match_operand 1 "treg_set_expr"))
12373   (clobber (reg:SI T_REG))]
12374  "TARGET_SH1 && can_create_pseudo_p ()"
12375  "#"
12376  "&& !sh_in_recog_treg_set_expr ()"
12377  [(const_int 0)]
12378{
12379  if (dump_file)
12380    fprintf (dump_file, "splitting any_treg_expr_to_reg\n");
12381
12382  if (t_reg_operand (operands[1], VOIDmode))
12383    {
12384      if (dump_file)
12385	fprintf (dump_file, "t_reg_operand: emitting movt\n");
12386      emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
12387      DONE;
12388    }
12389  if (negt_reg_operand (operands[1], VOIDmode))
12390    {
12391      if (dump_file)
12392	fprintf (dump_file, "negt_reg_operand: emitting movrt\n");
12393      emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
12394      DONE;
12395    }
12396
12397  /* If the split out insns ended with a nott, emit a movrt sequence,
12398     otherwise a normal movt.  */
12399  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12400  rtx_insn* i = NULL;
12401  if (ti.remove_trailing_nott ())
12402    {
12403      /* Emit this same insn_and_split again.  However, the next time it
12404	 is split, it will emit the actual negc/movrt insn.  This gives
12405	 other surrounding insns the chance to see the trailing movrt.  */
12406      if (dump_file)
12407	fprintf (dump_file,
12408		 "any_treg_expr_to_reg: replacing trailing nott with movrt\n");
12409      i = emit_insn (gen_any_treg_expr_to_reg (
12410			operands[0], gen_rtx_XOR (SImode, get_t_reg_rtx (),
12411			const1_rtx)));
12412    }
12413  else
12414    {
12415      i = emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
12416      if (dump_file)
12417	fprintf (dump_file, "any_treg_expr_to_reg: appending movt\n");
12418    }
12419
12420  add_reg_note (i, REG_UNUSED, get_t_reg_rtx ());
12421  DONE;
12422})
12423
12424;; -------------------------------------------------------------------------
12425;; Instructions to cope with inline literal tables
12426;; -------------------------------------------------------------------------
12427
12428;; 2 byte integer in line
12429(define_insn "consttable_2"
12430 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
12431		    (match_operand 1 "" "")]
12432		   UNSPECV_CONST2)]
12433 ""
12434{
12435  if (operands[1] != const0_rtx)
12436    assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
12437  return "";
12438}
12439 [(set_attr "length" "2")
12440 (set_attr "in_delay_slot" "no")])
12441
12442;; 4 byte integer in line
12443(define_insn "consttable_4"
12444 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
12445		    (match_operand 1 "" "")]
12446		   UNSPECV_CONST4)]
12447 ""
12448{
12449  if (operands[1] != const0_rtx)
12450    {
12451      assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
12452      mark_symbol_refs_as_used (operands[0]);
12453    }
12454  return "";
12455}
12456 [(set_attr "length" "4")
12457  (set_attr "in_delay_slot" "no")])
12458
12459;; 8 byte integer in line
12460(define_insn "consttable_8"
12461 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
12462		    (match_operand 1 "" "")]
12463		   UNSPECV_CONST8)]
12464 ""
12465{
12466  if (operands[1] != const0_rtx)
12467    assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
12468  return "";
12469}
12470 [(set_attr "length" "8")
12471  (set_attr "in_delay_slot" "no")])
12472
12473;; 4 byte floating point
12474(define_insn "consttable_sf"
12475 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
12476		    (match_operand 1 "" "")]
12477		   UNSPECV_CONST4)]
12478 ""
12479{
12480  if (operands[1] != const0_rtx)
12481    {
12482      REAL_VALUE_TYPE d;
12483      REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
12484      assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
12485    }
12486  return "";
12487}
12488 [(set_attr "length" "4")
12489  (set_attr "in_delay_slot" "no")])
12490
12491;; 8 byte floating point
12492(define_insn "consttable_df"
12493 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
12494		    (match_operand 1 "" "")]
12495		   UNSPECV_CONST8)]
12496 ""
12497{
12498  if (operands[1] != const0_rtx)
12499    {
12500      REAL_VALUE_TYPE d;
12501      REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
12502      assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
12503    }
12504  return "";
12505}
12506 [(set_attr "length" "8")
12507  (set_attr "in_delay_slot" "no")])
12508
12509;; Alignment is needed for some constant tables; it may also be added for
12510;; Instructions at the start of loops, or after unconditional branches.
12511;; ??? We would get more accurate lengths if we did instruction
12512;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
12513;; here is too conservative.
12514
12515;; align to a two byte boundary
12516(define_expand "align_2"
12517 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
12518 ""
12519 "")
12520
12521;; Align to a four byte boundary.
12522;; align_4 and align_log are instructions for the starts of loops, or
12523;; after unconditional branches, which may take up extra room.
12524(define_expand "align_4"
12525 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
12526 ""
12527 "")
12528
12529;; Align to a cache line boundary.
12530(define_insn "align_log"
12531 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
12532 ""
12533 ""
12534 [(set_attr "length" "0")
12535  (set_attr "in_delay_slot" "no")])
12536
12537;; Emitted at the end of the literal table, used to emit the
12538;; 32bit branch labels if needed.
12539(define_insn "consttable_end"
12540  [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
12541  ""
12542{
12543  return output_jump_label_table ();
12544}
12545  [(set_attr "in_delay_slot" "no")])
12546
12547;; Emitted at the end of the window in the literal table.
12548(define_insn "consttable_window_end"
12549  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
12550  ""
12551  ""
12552  [(set_attr "length" "0")
12553   (set_attr "in_delay_slot" "no")])
12554
12555;; -------------------------------------------------------------------------
12556;; Minimum / maximum operations.
12557;; -------------------------------------------------------------------------
12558
12559;; The SH2A clips.b and clips.w insns do a signed min-max function.  If smin
12560;; and smax standard name patterns are defined, they will be used during
12561;; initial expansion and combine will then be able to form the actual min-max
12562;; pattern.
12563;; The clips.b and clips.w set the SR.CS bit if the value in the register is
12564;; clipped, but there is currently no way of making use of this information.
12565;; The only way to read or reset the SR.CS bit is by accessing the SR.
12566(define_expand "<code>si3"
12567  [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
12568		   (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
12569				 (match_operand 2 "const_int_operand")))
12570	      (clobber (reg:SI T_REG))])]
12571  "TARGET_SH2A"
12572{
12573  /* Force the comparison value into a register, because greater-than
12574     comparisons can work only on registers.  Combine will be able to pick up
12575     the constant value from the REG_EQUAL note when trying to form a min-max
12576     pattern.  */
12577  operands[2] = force_reg (SImode, operands[2]);
12578})
12579
12580;; Convert
12581;;	smax (smin (...))
12582;; to
12583;;	smin (smax (...))
12584(define_insn_and_split "*clips"
12585  [(set (match_operand:SI 0 "arith_reg_dest")
12586	(smax:SI (smin:SI (match_operand:SI 1 "arith_reg_operand")
12587			  (match_operand 2 "clips_max_const_int"))
12588		 (match_operand 3 "clips_min_const_int")))]
12589  "TARGET_SH2A"
12590  "#"
12591  "&& 1"
12592  [(set (match_dup 0)
12593	(smin:SI (smax:SI (match_dup 1) (match_dup 3)) (match_dup 2)))])
12594
12595(define_insn "*clips"
12596  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12597	(smin:SI (smax:SI (match_operand:SI 1 "arith_reg_operand" "0")
12598			  (match_operand 2 "clips_min_const_int"))
12599		 (match_operand 3 "clips_max_const_int")))]
12600  "TARGET_SH2A"
12601{
12602  if (INTVAL (operands[3]) == 127)
12603    return "clips.b	%0";
12604  else if (INTVAL (operands[3]) == 32767)
12605    return "clips.w	%0";
12606  else
12607    gcc_unreachable ();
12608}
12609  [(set_attr "type" "arith")])
12610
12611;; If the expanded smin or smax patterns were not combined, split them into
12612;; a compare and branch sequence, because there are no real smin or smax
12613;; insns.
12614(define_insn_and_split "*<code>si3"
12615  [(set (match_operand:SI 0 "arith_reg_dest")
12616	(SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
12617		      (match_operand:SI 2 "arith_reg_or_0_or_1_operand")))
12618   (clobber (reg:SI T_REG))]
12619  "TARGET_SH2A && can_create_pseudo_p ()"
12620  "#"
12621  "&& 1"
12622  [(const_int 0)]
12623{
12624  rtx skip_label = gen_label_rtx ();
12625  emit_move_insn (operands[0], operands[1]);
12626
12627  rtx cmp_val = operands[2];
12628  if (satisfies_constraint_M (cmp_val))
12629    cmp_val = const0_rtx;
12630
12631  emit_insn (gen_cmpgtsi_t (operands[0], cmp_val));
12632  emit_jump_insn (<CODE> == SMIN
12633			    ? gen_branch_false (skip_label)
12634			    : gen_branch_true (skip_label));
12635
12636  emit_label_after (skip_label, emit_move_insn (operands[0], operands[2]));
12637  DONE;
12638})
12639
12640;; The SH2A clipu.b and clipu.w insns can be used to implement a min function
12641;; with a register and a constant.
12642;; The clipu.b and clipu.w set the SR.CS bit if the value in the register is
12643;; clipped, but there is currently no way of making use of this information.
12644;; The only way to read or reset the SR.CS bit is by accessing the SR.
12645(define_expand "uminsi3"
12646  [(set (match_operand:SI 0 "arith_reg_dest")
12647	(umin:SI (match_operand:SI 1 "arith_reg_operand")
12648		 (match_operand 2 "const_int_operand")))]
12649  "TARGET_SH2A"
12650{
12651  if (INTVAL (operands[2]) == 1)
12652    {
12653      emit_insn (gen_clipu_one (operands[0], operands[1]));
12654      DONE;
12655    }
12656  else if (! clipu_max_const_int (operands[2], VOIDmode))
12657    FAIL;
12658})
12659
12660(define_insn "*clipu"
12661  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12662	(umin:SI (match_operand:SI 1 "arith_reg_operand" "0")
12663		 (match_operand 2 "clipu_max_const_int")))]
12664  "TARGET_SH2A"
12665{
12666  if (INTVAL (operands[2]) == 255)
12667    return "clipu.b	%0";
12668  else if (INTVAL (operands[2]) == 65535)
12669    return "clipu.w	%0";
12670  else
12671    gcc_unreachable ();
12672}
12673  [(set_attr "type" "arith")])
12674
12675(define_insn_and_split "clipu_one"
12676  [(set (match_operand:SI 0 "arith_reg_dest")
12677	(umin:SI (match_operand:SI 1 "arith_reg_operand") (const_int 1)))
12678   (clobber (reg:SI T_REG))]
12679  "TARGET_SH2A"
12680  "#"
12681  "&& can_create_pseudo_p ()"
12682  [(const_int 0)]
12683{
12684  emit_insn (gen_cmpeqsi_t (operands[1], const0_rtx));
12685  emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
12686  DONE;
12687})
12688
12689;; -------------------------------------------------------------------------
12690;; Misc
12691;; -------------------------------------------------------------------------
12692
12693;; String/block move insn.
12694
12695(define_expand "movmemsi"
12696  [(parallel [(set (mem:BLK (match_operand:BLK 0))
12697		   (mem:BLK (match_operand:BLK 1)))
12698	      (use (match_operand:SI 2 "nonmemory_operand"))
12699	      (use (match_operand:SI 3 "immediate_operand"))
12700	      (clobber (reg:SI PR_REG))
12701	      (clobber (reg:SI R4_REG))
12702	      (clobber (reg:SI R5_REG))
12703	      (clobber (reg:SI R0_REG))])]
12704  "TARGET_SH1 && ! TARGET_SH5"
12705{
12706  if (expand_block_move (operands))
12707    DONE;
12708  else
12709    FAIL;
12710})
12711
12712(define_insn "block_move_real"
12713  [(parallel [(set (mem:BLK (reg:SI R4_REG))
12714		   (mem:BLK (reg:SI R5_REG)))
12715	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
12716	      (clobber (reg:SI PR_REG))
12717	      (clobber (reg:SI R0_REG))])]
12718  "TARGET_SH1 && ! TARGET_HARD_SH4"
12719  "jsr	@%0%#"
12720  [(set_attr "type" "sfunc")
12721   (set_attr "needs_delay_slot" "yes")])
12722
12723(define_insn "block_lump_real"
12724  [(parallel [(set (mem:BLK (reg:SI R4_REG))
12725		   (mem:BLK (reg:SI R5_REG)))
12726	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
12727	      (use (reg:SI R6_REG))
12728	      (clobber (reg:SI PR_REG))
12729	      (clobber (reg:SI T_REG))
12730	      (clobber (reg:SI R4_REG))
12731	      (clobber (reg:SI R5_REG))
12732	      (clobber (reg:SI R6_REG))
12733	      (clobber (reg:SI R0_REG))])]
12734  "TARGET_SH1 && ! TARGET_HARD_SH4"
12735  "jsr	@%0%#"
12736  [(set_attr "type" "sfunc")
12737   (set_attr "needs_delay_slot" "yes")])
12738
12739(define_insn "block_move_real_i4"
12740  [(parallel [(set (mem:BLK (reg:SI R4_REG))
12741		   (mem:BLK (reg:SI R5_REG)))
12742	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
12743	      (clobber (reg:SI PR_REG))
12744	      (clobber (reg:SI R0_REG))
12745	      (clobber (reg:SI R1_REG))
12746	      (clobber (reg:SI R2_REG))])]
12747  "TARGET_HARD_SH4"
12748  "jsr	@%0%#"
12749  [(set_attr "type" "sfunc")
12750   (set_attr "needs_delay_slot" "yes")])
12751
12752(define_insn "block_lump_real_i4"
12753  [(parallel [(set (mem:BLK (reg:SI R4_REG))
12754		   (mem:BLK (reg:SI R5_REG)))
12755	      (use (match_operand:SI 0 "arith_reg_operand" "r"))
12756	      (use (reg:SI R6_REG))
12757	      (clobber (reg:SI PR_REG))
12758	      (clobber (reg:SI T_REG))
12759	      (clobber (reg:SI R4_REG))
12760	      (clobber (reg:SI R5_REG))
12761	      (clobber (reg:SI R6_REG))
12762	      (clobber (reg:SI R0_REG))
12763	      (clobber (reg:SI R1_REG))
12764	      (clobber (reg:SI R2_REG))
12765	      (clobber (reg:SI R3_REG))])]
12766  "TARGET_HARD_SH4"
12767  "jsr	@%0%#"
12768  [(set_attr "type" "sfunc")
12769   (set_attr "needs_delay_slot" "yes")])
12770
12771;; byte compare pattern
12772;; temp = a ^ b;
12773;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F))
12774(define_insn "cmpstr_t"
12775  [(set (reg:SI T_REG)
12776	(eq:SI (and:SI
12777		 (and:SI
12778		   (and:SI
12779		     (zero_extract:SI
12780		       (xor:SI (match_operand:SI 0 "arith_reg_operand" "r")
12781			       (match_operand:SI 1 "arith_reg_operand" "r"))
12782		       (const_int 8) (const_int 0))
12783		     (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12784				      (const_int 8) (const_int 8)))
12785		    (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12786				     (const_int 8) (const_int 16)))
12787		 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12788				  (const_int 8) (const_int 24)))
12789	       (const_int 0)))]
12790  "TARGET_SH1"
12791  "cmp/str	%0,%1"
12792  [(set_attr "type" "mt_group")])
12793
12794(define_expand "cmpstrsi"
12795  [(set (match_operand:SI 0 "register_operand")
12796	(compare:SI (match_operand:BLK 1 "memory_operand")
12797		    (match_operand:BLK 2 "memory_operand")))
12798   (use (match_operand 3 "immediate_operand"))]
12799  "TARGET_SH1 && optimize"
12800{
12801  if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands))
12802    DONE;
12803  else
12804    FAIL;
12805})
12806
12807(define_expand "cmpstrnsi"
12808  [(set (match_operand:SI 0 "register_operand")
12809	(compare:SI (match_operand:BLK 1 "memory_operand")
12810		    (match_operand:BLK 2 "memory_operand")))
12811   (use (match_operand:SI 3 "immediate_operand"))
12812   (use (match_operand:SI 4 "immediate_operand"))]
12813  "TARGET_SH1 && optimize"
12814{
12815  if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands))
12816    DONE;
12817  else
12818    FAIL;
12819})
12820
12821(define_expand "strlensi"
12822  [(set (match_operand:SI 0 "register_operand")
12823	(unspec:SI [(match_operand:BLK 1 "memory_operand")
12824		   (match_operand:SI 2 "immediate_operand")
12825		   (match_operand:SI 3 "immediate_operand")]
12826		  UNSPEC_BUILTIN_STRLEN))]
12827  "TARGET_SH1 && optimize"
12828{
12829 if (! optimize_insn_for_size_p () && sh_expand_strlen (operands))
12830   DONE;
12831 else
12832   FAIL;
12833})
12834
12835(define_expand "setmemqi"
12836  [(parallel [(set (match_operand:BLK 0 "memory_operand")
12837                   (match_operand 2 "const_int_operand"))
12838              (use (match_operand:QI 1 "const_int_operand"))
12839              (use (match_operand:QI 3 "const_int_operand"))])]
12840  "TARGET_SH1 && optimize"
12841  {
12842    if (optimize_insn_for_size_p ())
12843       FAIL;
12844
12845    sh_expand_setmem (operands);
12846    DONE;
12847  })
12848
12849
12850;; -------------------------------------------------------------------------
12851;; Floating point instructions.
12852;; -------------------------------------------------------------------------
12853
12854;; FIXME: For now we disallow any memory operands for fpscr loads/stores,
12855;; except for post-inc loads and pre-dec stores for push/pop purposes.
12856;; This avoids problems with reload.  As a consequence, user initiated fpscr
12857;; stores to memory will always be ferried through a general register.
12858;; User initiated fpscr loads always have to undergo bit masking to preserve
12859;; the current fpu mode settings for the compiler generated code.  Thus such
12860;; fpscr loads will always have to go through general registers anyways.
12861(define_insn "lds_fpscr"
12862  [(set (reg:SI FPSCR_REG)
12863	(match_operand:SI 0 "fpscr_movsrc_operand" "r,>"))
12864   (set (reg:SI FPSCR_STAT_REG)
12865	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_STAT))
12866   (set (reg:SI FPSCR_MODES_REG)
12867	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
12868  "TARGET_FPU_ANY"
12869  "@
12870	lds	%0,fpscr
12871	lds.l	%0,fpscr"
12872  [(set_attr "type" "gp_fpscr,mem_fpscr")])
12873
12874;; A move fpscr -> reg schedules like a move mac -> reg.  Thus we use mac_gp
12875;; type for it.
12876(define_insn "sts_fpscr"
12877  [(set (match_operand:SI 0 "fpscr_movdst_operand" "=r,<")
12878	(reg:SI FPSCR_REG))
12879   (use (reg:SI FPSCR_STAT_REG))
12880   (use (reg:SI FPSCR_MODES_REG))]
12881  "TARGET_FPU_ANY"
12882  "@
12883	sts	fpscr,%0
12884	sts.l	fpscr,%0"
12885  [(set_attr "type" "mac_gp,fstore")])
12886
12887(define_expand "set_fpscr"
12888  [(parallel [(set (reg:SI FPSCR_REG)
12889		   (match_operand:SI 0 "general_operand"))
12890	      (set (reg:SI FPSCR_STAT_REG)
12891		   (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))])]
12892  "TARGET_FPU_ANY"
12893{
12894  /* We have to mask out the FR, SZ and PR bits.  To do that, we need to
12895     get the current FPSCR value first.
12896     (a & ~mask) | (b & mask) = a ^ ((a ^ b) & mask)  */
12897
12898  rtx mask = force_reg (SImode, GEN_INT (FPSCR_FR | FPSCR_SZ | FPSCR_PR));
12899
12900  rtx a = force_reg (SImode, operands[0]);
12901
12902  rtx b = gen_reg_rtx (SImode);
12903  emit_insn (gen_sts_fpscr (b));
12904
12905  rtx a_xor_b = gen_reg_rtx (SImode);
12906  emit_insn (gen_xorsi3 (a_xor_b, a, b));
12907
12908  rtx a_xor_b_and_mask = gen_reg_rtx (SImode);
12909  emit_insn (gen_andsi3 (a_xor_b_and_mask, a_xor_b, mask));
12910
12911  rtx r = gen_reg_rtx (SImode);
12912  emit_insn (gen_xorsi3 (r, a_xor_b_and_mask, a));
12913  emit_insn (gen_lds_fpscr (r));
12914
12915  DONE;
12916})
12917
12918;; ??? This uses the fp unit, but has no type indicating that.
12919;; If we did that, this would either give a bogus latency or introduce
12920;; a bogus FIFO constraint.
12921;; Since this insn is currently only used for prologues/epilogues,
12922;; it is probably best to claim no function unit, which matches the
12923;; current setting.
12924(define_insn "toggle_sz"
12925  [(set (reg:SI FPSCR_REG)
12926	(xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_SZ)))
12927   (set (reg:SI FPSCR_MODES_REG)
12928	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
12929  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12930  "fschg"
12931  [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
12932
12933;; Toggle FPU precision PR mode.
12934
12935(define_insn "toggle_pr"
12936  [(set (reg:SI FPSCR_REG)
12937	(xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_PR)))
12938   (set (reg:SI FPSCR_MODES_REG)
12939	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
12940  "TARGET_SH4A_FP"
12941  "fpchg"
12942  [(set_attr "type" "fpscr_toggle")])
12943
12944(define_expand "addsf3"
12945  [(set (match_operand:SF 0 "fp_arith_reg_operand")
12946	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand")
12947		 (match_operand:SF 2 "fp_arith_reg_operand")))]
12948  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12949{
12950  if (TARGET_SH2E)
12951    {
12952      emit_insn (gen_addsf3_i (operands[0], operands[1], operands[2]));
12953      DONE;
12954    }
12955})
12956
12957(define_insn "*addsf3_media"
12958  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12959	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12960		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12961  "TARGET_SHMEDIA_FPU"
12962  "fadd.s	%1, %2, %0"
12963  [(set_attr "type" "fparith_media")])
12964
12965(define_insn_and_split "unary_sf_op"
12966  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12967	(vec_select:V2SF
12968	 (vec_concat:V2SF
12969	  (vec_select:SF
12970	   (match_dup 0)
12971	   (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
12972	  (match_operator:SF 2 "unary_float_operator"
12973	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12974			    (parallel [(match_operand 4
12975					"const_int_operand" "n")]))]))
12976	 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
12977  "TARGET_SHMEDIA_FPU"
12978  "#"
12979  "TARGET_SHMEDIA_FPU && reload_completed"
12980  [(set (match_dup 5) (match_dup 6))]
12981{
12982  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12983  rtx op1 = gen_rtx_REG (SFmode,
12984			 (true_regnum (operands[1])
12985			  + (INTVAL (operands[4]) ^ endian)));
12986
12987  operands[7] = gen_rtx_REG (SFmode,
12988			     (true_regnum (operands[0])
12989			      + (INTVAL (operands[3]) ^ endian)));
12990  operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
12991}
12992  [(set_attr "type" "fparith_media")])
12993
12994(define_insn_and_split "binary_sf_op0"
12995  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12996	(vec_concat:V2SF
12997	  (match_operator:SF 3 "binary_float_operator"
12998	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12999			    (parallel [(const_int 0)]))
13000	     (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
13001			    (parallel [(const_int 0)]))])
13002	  (vec_select:SF
13003	   (match_dup 0)
13004	   (parallel [(const_int 1)]))))]
13005  "TARGET_SHMEDIA_FPU"
13006  "#"
13007  "&& reload_completed"
13008  [(set (match_dup 4) (match_dup 5))]
13009{
13010  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
13011  rtx op1 = gen_rtx_REG (SFmode,
13012			 true_regnum (operands[1]) + endian);
13013  rtx op2 = gen_rtx_REG (SFmode,
13014			 true_regnum (operands[2]) + endian);
13015
13016  operands[4] = gen_rtx_REG (SFmode,
13017			     true_regnum (operands[0]) + endian);
13018  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
13019}
13020  [(set_attr "type" "fparith_media")])
13021
13022(define_insn_and_split "binary_sf_op1"
13023  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
13024	(vec_concat:V2SF
13025	  (vec_select:SF
13026	   (match_dup 0)
13027	   (parallel [(const_int 0)]))
13028	  (match_operator:SF 3 "binary_float_operator"
13029	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
13030			    (parallel [(const_int 1)]))
13031	     (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
13032			    (parallel [(const_int 1)]))])))]
13033  "TARGET_SHMEDIA_FPU"
13034  "#"
13035  "&& reload_completed"
13036  [(set (match_dup 4) (match_dup 5))]
13037{
13038  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
13039  rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
13040  rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
13041
13042  operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
13043  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
13044}
13045  [(set_attr "type" "fparith_media")])
13046
13047(define_insn "addsf3_i"
13048  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13049	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
13050		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13051   (clobber (reg:SI FPSCR_STAT_REG))
13052   (use (reg:SI FPSCR_MODES_REG))]
13053  "TARGET_SH2E"
13054  "fadd	%2,%0"
13055  [(set_attr "type" "fp")
13056   (set_attr "fp_mode" "single")])
13057
13058(define_expand "subsf3"
13059  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13060	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
13061		  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
13062  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13063{
13064  if (TARGET_SH2E)
13065    {
13066      emit_insn (gen_subsf3_i (operands[0], operands[1], operands[2]));
13067      DONE;
13068    }
13069})
13070
13071(define_insn "*subsf3_media"
13072  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13073	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
13074		  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13075  "TARGET_SHMEDIA_FPU"
13076  "fsub.s	%1, %2, %0"
13077  [(set_attr "type" "fparith_media")])
13078
13079(define_insn "subsf3_i"
13080  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13081	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
13082		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13083   (clobber (reg:SI FPSCR_STAT_REG))
13084   (use (reg:SI FPSCR_MODES_REG))]
13085  "TARGET_SH2E"
13086  "fsub	%2,%0"
13087  [(set_attr "type" "fp")
13088   (set_attr "fp_mode" "single")])
13089
13090(define_expand "mulsf3"
13091  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13092	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
13093		 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
13094  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13095{
13096  if (TARGET_SH2E)
13097    {
13098      emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2]));
13099      DONE;
13100    }
13101})
13102
13103(define_insn "*mulsf3_media"
13104  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13105	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
13106		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13107  "TARGET_SHMEDIA_FPU"
13108  "fmul.s	%1, %2, %0"
13109  [(set_attr "type" "fparith_media")])
13110
13111(define_insn "mulsf3_i"
13112  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13113	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
13114		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13115   (clobber (reg:SI FPSCR_STAT_REG))
13116   (use (reg:SI FPSCR_MODES_REG))]
13117  "TARGET_SH2E"
13118  "fmul	%2,%0"
13119  [(set_attr "type" "fp")
13120   (set_attr "fp_mode" "single")])
13121
13122;; FMA (fused multiply-add) patterns
13123(define_expand "fmasf4"
13124  [(set (match_operand:SF 0 "fp_arith_reg_operand")
13125	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand")
13126		(match_operand:SF 2 "fp_arith_reg_operand")
13127		(match_operand:SF 3 "fp_arith_reg_operand")))]
13128  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13129{
13130  if (TARGET_SH2E)
13131    {
13132      emit_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
13133			       operands[3]));
13134      DONE;
13135    }
13136})
13137
13138(define_insn "fmasf4_i"
13139  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13140	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
13141		(match_operand:SF 2 "fp_arith_reg_operand" "f")
13142		(match_operand:SF 3 "fp_arith_reg_operand" "0")))
13143   (clobber (reg:SI FPSCR_STAT_REG))
13144   (use (reg:SI FPSCR_MODES_REG))]
13145  "TARGET_SH2E"
13146  "fmac	%1,%2,%0"
13147  [(set_attr "type" "fp")
13148   (set_attr "fp_mode" "single")])
13149
13150(define_insn "fmasf4_media"
13151  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13152	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
13153		(match_operand:SF 2 "fp_arith_reg_operand" "f")
13154		(match_operand:SF 3 "fp_arith_reg_operand" "0")))]
13155  "TARGET_SHMEDIA_FPU"
13156  "fmac.s %1, %2, %0"
13157  [(set_attr "type" "fparith_media")])
13158
13159;; For some cases such as 'a * b + a' the FMA pattern is not generated by
13160;; previous transformations.  If FMA is generally allowed, let the combine
13161;; pass utilize it.
13162(define_insn_and_split "*fmasf4"
13163  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13164	(plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
13165			  (match_operand:SF 2 "fp_arith_reg_operand" "f"))
13166		 (match_operand:SF 3 "arith_reg_operand" "0")))
13167   (clobber (reg:SI FPSCR_STAT_REG))
13168   (use (reg:SI FPSCR_MODES_REG))]
13169  "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
13170  "fmac	%1,%2,%0"
13171  "&& can_create_pseudo_p ()"
13172  [(parallel [(set (match_dup 0)
13173		   (fma:SF (match_dup 1) (match_dup 2) (match_dup 3)))
13174	      (clobber (reg:SI FPSCR_STAT_REG))
13175	      (use (reg:SI FPSCR_MODES_REG))])]
13176{
13177  /* Change 'b * a + a' into 'a * b + a'.
13178     This is better for register allocation.  */
13179  if (REGNO (operands[2]) == REGNO (operands[3]))
13180    std::swap (operands[1], operands[2]);
13181}
13182  [(set_attr "type" "fp")
13183   (set_attr "fp_mode" "single")])
13184
13185(define_insn "*fmasf4_media"
13186  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13187	(plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
13188			  (match_operand:SF 2 "fp_arith_reg_operand" "f"))
13189		 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
13190  "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF"
13191  "fmac.s %1, %2, %0"
13192  [(set_attr "type" "fparith_media")])
13193
13194(define_expand "divsf3"
13195  [(set (match_operand:SF 0 "fp_arith_reg_operand")
13196	(div:SF (match_operand:SF 1 "fp_arith_reg_operand")
13197		(match_operand:SF 2 "fp_arith_reg_operand")))]
13198  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13199{
13200  if (TARGET_SH2E)
13201    {
13202      emit_insn (gen_divsf3_i (operands[0], operands[1], operands[2]));
13203      DONE;
13204    }
13205})
13206
13207(define_insn "*divsf3_media"
13208  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13209	(div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
13210		(match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13211  "TARGET_SHMEDIA_FPU"
13212  "fdiv.s	%1, %2, %0"
13213  [(set_attr "type" "fdiv_media")])
13214
13215(define_insn "divsf3_i"
13216  [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f")
13217	(div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
13218		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13219   (clobber (reg:SI FPSCR_STAT_REG))
13220   (use (reg:SI FPSCR_MODES_REG))]
13221  "TARGET_SH2E"
13222  "fdiv	%2,%0"
13223  [(set_attr "type" "fdiv")
13224   (set_attr "fp_mode" "single")])
13225
13226(define_insn "floatdisf2"
13227  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13228	(float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
13229  "TARGET_SHMEDIA_FPU"
13230  "float.qs %1, %0"
13231  [(set_attr "type" "fpconv_media")])
13232
13233(define_expand "floatsisf2"
13234  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13235	(float:SF (match_operand:SI 1 "fpul_operand" "")))]
13236  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13237{
13238  if (!TARGET_SHMEDIA_FPU)
13239    {
13240      emit_insn (gen_floatsisf2_i4 (operands[0], operands[1]));
13241      DONE;
13242    }
13243})
13244
13245(define_insn "*floatsisf2_media"
13246  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13247	(float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
13248  "TARGET_SHMEDIA_FPU"
13249  "float.ls	%1, %0"
13250  [(set_attr "type" "fpconv_media")])
13251
13252(define_insn "floatsisf2_i4"
13253  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13254	(float:SF (match_operand:SI 1 "fpul_operand" "y")))
13255   (clobber (reg:SI FPSCR_STAT_REG))
13256   (use (reg:SI FPSCR_MODES_REG))]
13257  "TARGET_SH2E"
13258  "float	%1,%0"
13259  [(set_attr "type" "fp")
13260   (set_attr "fp_mode" "single")])
13261
13262(define_insn "fix_truncsfdi2"
13263  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
13264	(fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13265  "TARGET_SHMEDIA_FPU"
13266  "ftrc.sq %1, %0"
13267  [(set_attr "type" "fpconv_media")])
13268
13269(define_expand "fix_truncsfsi2"
13270  [(set (match_operand:SI 0 "fpul_operand" "=y")
13271	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13272  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13273{
13274  if (!TARGET_SHMEDIA_FPU)
13275    {
13276      emit_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1]));
13277      DONE;
13278    }
13279})
13280
13281(define_insn "*fix_truncsfsi2_media"
13282  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
13283	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13284  "TARGET_SHMEDIA_FPU"
13285  "ftrc.sl	%1, %0"
13286  [(set_attr "type" "fpconv_media")])
13287
13288(define_insn "fix_truncsfsi2_i4"
13289  [(set (match_operand:SI 0 "fpul_operand" "=y")
13290	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
13291   (clobber (reg:SI FPSCR_STAT_REG))
13292   (use (reg:SI FPSCR_MODES_REG))]
13293  "TARGET_SH2E"
13294  "ftrc	%1,%0"
13295  [(set_attr "type" "ftrc_s")
13296   (set_attr "fp_mode" "single")])
13297
13298(define_insn "cmpgtsf_t"
13299  [(set (reg:SI T_REG)
13300	(gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
13301	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
13302   (clobber (reg:SI FPSCR_STAT_REG))
13303   (use (reg:SI FPSCR_MODES_REG))]
13304  "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
13305  "fcmp/gt	%1,%0"
13306  [(set_attr "type" "fp_cmp")
13307   (set_attr "fp_mode" "single")])
13308
13309(define_insn "cmpeqsf_t"
13310  [(set (reg:SI T_REG)
13311	(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
13312	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
13313   (clobber (reg:SI FPSCR_STAT_REG))
13314   (use (reg:SI FPSCR_MODES_REG))]
13315  "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
13316  "fcmp/eq	%1,%0"
13317  [(set_attr "type" "fp_cmp")
13318   (set_attr "fp_mode" "single")])
13319
13320(define_insn "ieee_ccmpeqsf_t"
13321  [(set (reg:SI T_REG)
13322	(ior:SI (reg:SI T_REG)
13323		(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
13324		       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
13325   (clobber (reg:SI FPSCR_STAT_REG))
13326   (use (reg:SI FPSCR_MODES_REG))]
13327  "TARGET_IEEE && TARGET_SH2E"
13328{
13329  return output_ieee_ccmpeq (insn, operands);
13330}
13331  [(set_attr "length" "4")
13332   (set_attr "fp_mode" "single")])
13333
13334(define_insn "cmpeqsf_media"
13335  [(set (match_operand:SI 0 "register_operand" "=r")
13336	(eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13337	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13338  "TARGET_SHMEDIA_FPU"
13339  "fcmpeq.s	%1, %2, %0"
13340  [(set_attr "type" "fcmp_media")])
13341
13342(define_insn "cmpgtsf_media"
13343  [(set (match_operand:SI 0 "register_operand" "=r")
13344	(gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13345	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13346  "TARGET_SHMEDIA_FPU"
13347  "fcmpgt.s	%1, %2, %0"
13348  [(set_attr "type" "fcmp_media")])
13349
13350(define_insn "cmpgesf_media"
13351  [(set (match_operand:SI 0 "register_operand" "=r")
13352	(ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13353	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13354  "TARGET_SHMEDIA_FPU"
13355  "fcmpge.s	%1, %2, %0"
13356  [(set_attr "type" "fcmp_media")])
13357
13358(define_insn "cmpunsf_media"
13359  [(set (match_operand:SI 0 "register_operand" "=r")
13360	(unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13361		      (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13362  "TARGET_SHMEDIA_FPU"
13363  "fcmpun.s	%1, %2, %0"
13364  [(set_attr "type" "fcmp_media")])
13365
13366(define_expand "cbranchsf4"
13367  [(set (pc)
13368	(if_then_else (match_operator 0 "sh_float_comparison_operator"
13369		       [(match_operand:SF 1 "arith_operand" "")
13370			(match_operand:SF 2 "arith_operand" "")])
13371		      (match_operand 3 "" "")
13372		      (pc)))]
13373  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13374{
13375  if (TARGET_SHMEDIA)
13376    emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
13377					  operands[3]));
13378  else
13379    sh_emit_compare_and_branch (operands, SFmode);
13380  DONE;
13381})
13382
13383(define_expand "negsf2"
13384  [(set (match_operand:SF 0 "fp_arith_reg_operand")
13385	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand")))]
13386  "TARGET_SH2E || TARGET_SHMEDIA_FPU")
13387
13388(define_insn "*negsf2_media"
13389  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13390	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13391  "TARGET_SHMEDIA_FPU"
13392  "fneg.s	%1, %0"
13393  [(set_attr "type" "fmove_media")])
13394
13395(define_insn "*negsf2_i"
13396  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13397	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))]
13398  "TARGET_SH2E"
13399  "fneg	%0"
13400  [(set_attr "type" "fmove")])
13401
13402(define_expand "sqrtsf2"
13403  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13404	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
13405  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
13406{
13407  if (TARGET_SH3E)
13408    {
13409      emit_insn (gen_sqrtsf2_i (operands[0], operands[1]));
13410      DONE;
13411    }
13412})
13413
13414(define_insn "*sqrtsf2_media"
13415  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13416	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13417  "TARGET_SHMEDIA_FPU"
13418  "fsqrt.s	%1, %0"
13419  [(set_attr "type" "fdiv_media")])
13420
13421(define_insn "sqrtsf2_i"
13422  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13423	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
13424   (clobber (reg:SI FPSCR_STAT_REG))
13425   (use (reg:SI FPSCR_MODES_REG))]
13426  "TARGET_SH3E"
13427  "fsqrt	%0"
13428  [(set_attr "type" "fdiv")
13429   (set_attr "fp_mode" "single")])
13430
13431(define_insn "rsqrtsf2"
13432  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13433	(div:SF (match_operand:SF 1 "immediate_operand" "i")
13434		(sqrt:SF (match_operand:SF 2 "fp_arith_reg_operand" "0"))))
13435   (clobber (reg:SI FPSCR_STAT_REG))
13436   (use (reg:SI FPSCR_MODES_REG))]
13437  "TARGET_FPU_ANY && TARGET_FSRRA
13438   && operands[1] == CONST1_RTX (SFmode)"
13439  "fsrra	%0"
13440  [(set_attr "type" "fsrra")
13441   (set_attr "fp_mode" "single")])
13442
13443;; When the sincos pattern is defined, the builtin functions sin and cos
13444;; will be expanded to the sincos pattern and one of the output values will
13445;; remain unused.
13446(define_expand "sincossf3"
13447  [(set (match_operand:SF 0 "nonimmediate_operand")
13448	(unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
13449   (set (match_operand:SF 1 "nonimmediate_operand")
13450	(unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
13451  "TARGET_FPU_ANY && TARGET_FSCA"
13452{
13453  rtx scaled = gen_reg_rtx (SFmode);
13454  rtx truncated = gen_reg_rtx (SImode);
13455  rtx fsca = gen_reg_rtx (V2SFmode);
13456  rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
13457
13458  emit_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
13459  emit_insn (gen_fix_truncsfsi2 (truncated, scaled));
13460  emit_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf ()));
13461
13462  emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
13463  emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
13464  DONE;
13465})
13466
13467(define_insn_and_split "fsca"
13468  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
13469	(vec_concat:V2SF
13470	 (unspec:SF [(mult:SF
13471		      (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
13472		      (match_operand:SF 2 "fsca_scale_factor" "i"))
13473		    ] UNSPEC_FSINA)
13474	 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
13475		    ] UNSPEC_FCOSA)))
13476   (clobber (reg:SI FPSCR_STAT_REG))
13477   (use (reg:SI FPSCR_MODES_REG))]
13478  "TARGET_FPU_ANY && TARGET_FSCA"
13479  "fsca	fpul,%d0"
13480  "&& !fpul_operand (operands[1], SImode)"
13481  [(const_int 0)]
13482{
13483  /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
13484     to a simple reg, otherwise reload will have trouble reloading the
13485     pseudo into fpul.  */
13486  rtx x = XEXP (operands[1], 0);
13487  while (x != NULL_RTX && !fpul_operand (x, SImode))
13488    {
13489      gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
13490      x = XEXP (x, 0);
13491    }
13492  gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
13493  emit_insn (gen_fsca (operands[0], x, operands[2]));
13494  DONE;
13495}
13496  [(set_attr "type" "fsca")
13497   (set_attr "fp_mode" "single")])
13498
13499(define_expand "abssf2"
13500  [(set (match_operand:SF 0 "fp_arith_reg_operand")
13501	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand")))]
13502  "TARGET_SH2E || TARGET_SHMEDIA_FPU")
13503
13504(define_insn "*abssf2_media"
13505  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13506	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13507  "TARGET_SHMEDIA_FPU"
13508  "fabs.s	%1, %0"
13509  [(set_attr "type" "fmove_media")])
13510
13511(define_insn "*abssf2_i"
13512  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13513	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))]
13514  "TARGET_SH2E"
13515  "fabs	%0"
13516  [(set_attr "type" "fmove")])
13517
13518(define_expand "adddf3"
13519  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13520	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13521		 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13522  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13523{
13524  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13525    {
13526      emit_insn (gen_adddf3_i (operands[0], operands[1], operands[2]));
13527      DONE;
13528    }
13529})
13530
13531(define_insn "*adddf3_media"
13532  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13533	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
13534		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13535  "TARGET_SHMEDIA_FPU"
13536  "fadd.d	%1, %2, %0"
13537  [(set_attr "type" "dfparith_media")])
13538
13539(define_insn "adddf3_i"
13540  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13541	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
13542		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13543   (clobber (reg:SI FPSCR_STAT_REG))
13544   (use (reg:SI FPSCR_MODES_REG))]
13545  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13546  "fadd	%2,%0"
13547  [(set_attr "type" "dfp_arith")
13548   (set_attr "fp_mode" "double")])
13549
13550(define_expand "subdf3"
13551  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13552	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13553		  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13554  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13555{
13556  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13557    {
13558      emit_insn (gen_subdf3_i (operands[0], operands[1], operands[2]));
13559      DONE;
13560    }
13561})
13562
13563(define_insn "*subdf3_media"
13564  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13565	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
13566		  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13567  "TARGET_SHMEDIA_FPU"
13568  "fsub.d	%1, %2, %0"
13569  [(set_attr "type" "dfparith_media")])
13570
13571(define_insn "subdf3_i"
13572  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13573	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
13574		  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13575   (clobber (reg:SI FPSCR_STAT_REG))
13576   (use (reg:SI FPSCR_MODES_REG))]
13577  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13578  "fsub	%2,%0"
13579  [(set_attr "type" "dfp_arith")
13580   (set_attr "fp_mode" "double")])
13581
13582(define_expand "muldf3"
13583  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13584	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13585		 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13586  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13587{
13588  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13589    {
13590      emit_insn (gen_muldf3_i (operands[0], operands[1], operands[2]));
13591      DONE;
13592    }
13593})
13594
13595(define_insn "*muldf3_media"
13596  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13597	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
13598		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13599  "TARGET_SHMEDIA_FPU"
13600  "fmul.d	%1, %2, %0"
13601  [(set_attr "type" "dfmul_media")])
13602
13603(define_insn "muldf3_i"
13604  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13605	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
13606		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13607   (clobber (reg:SI FPSCR_STAT_REG))
13608   (use (reg:SI FPSCR_MODES_REG))]
13609  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13610  "fmul	%2,%0"
13611  [(set_attr "type" "dfp_mul")
13612   (set_attr "fp_mode" "double")])
13613
13614(define_expand "divdf3"
13615  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13616	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13617		(match_operand:DF 2 "fp_arith_reg_operand" "")))]
13618  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13619{
13620  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13621    {
13622      emit_insn (gen_divdf3_i (operands[0], operands[1], operands[2]));
13623      DONE;
13624    }
13625})
13626
13627(define_insn "*divdf3_media"
13628  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13629	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
13630		(match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13631  "TARGET_SHMEDIA_FPU"
13632  "fdiv.d	%1, %2, %0"
13633  [(set_attr "type" "dfdiv_media")])
13634
13635(define_insn "divdf3_i"
13636  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13637	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
13638		(match_operand:DF 2 "fp_arith_reg_operand" "f")))
13639   (clobber (reg:SI FPSCR_STAT_REG))
13640   (use (reg:SI FPSCR_MODES_REG))]
13641  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13642  "fdiv	%2,%0"
13643  [(set_attr "type" "dfdiv")
13644   (set_attr "fp_mode" "double")])
13645
13646(define_insn "floatdidf2"
13647  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13648	(float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
13649  "TARGET_SHMEDIA_FPU"
13650  "float.qd	%1, %0"
13651  [(set_attr "type" "dfpconv_media")])
13652
13653(define_expand "floatsidf2"
13654  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13655	(float:DF (match_operand:SI 1 "fpul_operand" "")))]
13656  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13657{
13658  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13659    {
13660      emit_insn (gen_floatsidf2_i (operands[0], operands[1]));
13661      DONE;
13662    }
13663})
13664
13665(define_insn "*floatsidf2_media"
13666  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13667	(float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
13668  "TARGET_SHMEDIA_FPU"
13669  "float.ld	%1, %0"
13670  [(set_attr "type" "dfpconv_media")])
13671
13672(define_insn "floatsidf2_i"
13673  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13674	(float:DF (match_operand:SI 1 "fpul_operand" "y")))
13675   (clobber (reg:SI FPSCR_STAT_REG))
13676   (use (reg:SI FPSCR_MODES_REG))]
13677  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13678  "float	%1,%0"
13679  [(set_attr "type" "dfp_conv")
13680   (set_attr "fp_mode" "double")])
13681
13682(define_insn "fix_truncdfdi2"
13683  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
13684	(fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13685  "TARGET_SHMEDIA_FPU"
13686  "ftrc.dq	%1, %0"
13687  [(set_attr "type" "dfpconv_media")])
13688
13689(define_expand "fix_truncdfsi2"
13690  [(set (match_operand:SI 0 "fpul_operand" "")
13691	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13692  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13693{
13694  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13695    {
13696      emit_insn (gen_fix_truncdfsi2_i (operands[0], operands[1]));
13697      DONE;
13698    }
13699})
13700
13701(define_insn "*fix_truncdfsi2_media"
13702  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
13703	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13704  "TARGET_SHMEDIA_FPU"
13705  "ftrc.dl	%1, %0"
13706  [(set_attr "type" "dfpconv_media")])
13707
13708(define_insn "fix_truncdfsi2_i"
13709  [(set (match_operand:SI 0 "fpul_operand" "=y")
13710	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13711   (clobber (reg:SI FPSCR_STAT_REG))
13712   (use (reg:SI FPSCR_MODES_REG))]
13713  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13714  "ftrc	%1,%0"
13715  [(set_attr "type" "dfp_conv")
13716   (set_attr "dfp_comp" "no")
13717   (set_attr "fp_mode" "double")])
13718
13719(define_insn "cmpgtdf_t"
13720  [(set (reg:SI T_REG)
13721	(gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13722	       (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13723   (clobber (reg:SI FPSCR_STAT_REG))
13724   (use (reg:SI FPSCR_MODES_REG))]
13725  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13726  "fcmp/gt	%1,%0"
13727  [(set_attr "type" "dfp_cmp")
13728   (set_attr "fp_mode" "double")])
13729
13730(define_insn "cmpeqdf_t"
13731  [(set (reg:SI T_REG)
13732	(eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13733	       (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13734   (clobber (reg:SI FPSCR_STAT_REG))
13735   (use (reg:SI FPSCR_MODES_REG))]
13736  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13737  "fcmp/eq	%1,%0"
13738  [(set_attr "type" "dfp_cmp")
13739   (set_attr "fp_mode" "double")])
13740
13741(define_insn "*ieee_ccmpeqdf_t"
13742  [(set (reg:SI T_REG)
13743	(ior:SI (reg:SI T_REG)
13744		(eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13745		       (match_operand:DF 1 "fp_arith_reg_operand" "f"))))
13746   (clobber (reg:SI FPSCR_STAT_REG))
13747   (use (reg:SI FPSCR_MODES_REG))]
13748  "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13749{
13750  return output_ieee_ccmpeq (insn, operands);
13751}
13752  [(set_attr "length" "4")
13753   (set_attr "fp_mode" "double")])
13754
13755(define_insn "cmpeqdf_media"
13756  [(set (match_operand:SI 0 "register_operand" "=r")
13757	(eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13758	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13759  "TARGET_SHMEDIA_FPU"
13760  "fcmpeq.d	%1,%2,%0"
13761  [(set_attr "type" "fcmp_media")])
13762
13763(define_insn "cmpgtdf_media"
13764  [(set (match_operand:SI 0 "register_operand" "=r")
13765	(gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13766	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13767  "TARGET_SHMEDIA_FPU"
13768  "fcmpgt.d	%1,%2,%0"
13769  [(set_attr "type" "fcmp_media")])
13770
13771(define_insn "cmpgedf_media"
13772  [(set (match_operand:SI 0 "register_operand" "=r")
13773	(ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13774	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13775  "TARGET_SHMEDIA_FPU"
13776  "fcmpge.d	%1,%2,%0"
13777  [(set_attr "type" "fcmp_media")])
13778
13779(define_insn "cmpundf_media"
13780  [(set (match_operand:SI 0 "register_operand" "=r")
13781	(unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13782		      (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13783  "TARGET_SHMEDIA_FPU"
13784  "fcmpun.d	%1,%2,%0"
13785  [(set_attr "type" "fcmp_media")])
13786
13787(define_expand "cbranchdf4"
13788  [(set (pc)
13789	(if_then_else (match_operator 0 "sh_float_comparison_operator"
13790		       [(match_operand:DF 1 "arith_operand" "")
13791			(match_operand:DF 2 "arith_operand" "")])
13792		      (match_operand 3 "" "")
13793		      (pc)))]
13794  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13795{
13796  if (TARGET_SHMEDIA)
13797    emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
13798					  operands[3]));
13799  else
13800    sh_emit_compare_and_branch (operands, DFmode);
13801  DONE;
13802})
13803
13804(define_expand "negdf2"
13805  [(set (match_operand:DF 0 "fp_arith_reg_operand")
13806	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13807  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU")
13808
13809(define_insn "*negdf2_media"
13810  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13811	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13812  "TARGET_SHMEDIA_FPU"
13813  "fneg.d	%1, %0"
13814  [(set_attr "type" "fmove_media")])
13815
13816(define_insn "*negdf2_i"
13817  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13818	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))]
13819  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13820  "fneg	%0"
13821  [(set_attr "type" "fmove")])
13822
13823(define_expand "sqrtdf2"
13824  [(set (match_operand:DF 0 "fp_arith_reg_operand")
13825	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13826  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13827{
13828  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13829    {
13830      emit_insn (gen_sqrtdf2_i (operands[0], operands[1]));
13831      DONE;
13832    }
13833})
13834
13835(define_insn "*sqrtdf2_media"
13836  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13837	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13838  "TARGET_SHMEDIA_FPU"
13839  "fsqrt.d	%1, %0"
13840  [(set_attr "type" "dfdiv_media")])
13841
13842(define_insn "sqrtdf2_i"
13843  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13844	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13845   (clobber (reg:SI FPSCR_STAT_REG))
13846   (use (reg:SI FPSCR_MODES_REG))]
13847  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13848  "fsqrt	%0"
13849  [(set_attr "type" "dfdiv")
13850   (set_attr "fp_mode" "double")])
13851
13852(define_expand "absdf2"
13853  [(set (match_operand:DF 0 "fp_arith_reg_operand")
13854	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13855  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU")
13856
13857(define_insn "*absdf2_media"
13858  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13859	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13860  "TARGET_SHMEDIA_FPU"
13861  "fabs.d	%1, %0"
13862  [(set_attr "type" "fmove_media")])
13863
13864(define_insn "*absdf2_i"
13865  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13866	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))]
13867  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13868  "fabs	%0"
13869  [(set_attr "type" "fmove")])
13870
13871(define_expand "extendsfdf2"
13872  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13873	(float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
13874  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13875{
13876  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13877    {
13878      emit_insn (gen_extendsfdf2_i4 (operands[0], operands[1]));
13879      DONE;
13880    }
13881})
13882
13883(define_insn "*extendsfdf2_media"
13884  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13885	(float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13886  "TARGET_SHMEDIA_FPU"
13887  "fcnv.sd	%1, %0"
13888  [(set_attr "type" "dfpconv_media")])
13889
13890(define_insn "extendsfdf2_i4"
13891  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13892	(float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
13893   (clobber (reg:SI FPSCR_STAT_REG))
13894   (use (reg:SI FPSCR_MODES_REG))]
13895  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13896  "fcnvsd  %1,%0"
13897  [(set_attr "type" "fp")
13898   (set_attr "fp_mode" "double")])
13899
13900(define_expand "truncdfsf2"
13901  [(set (match_operand:SF 0 "fpul_operand" "")
13902	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13903  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13904{
13905  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13906    {
13907      emit_insn (gen_truncdfsf2_i4 (operands[0], operands[1]));
13908      DONE;
13909    }
13910})
13911
13912(define_insn "*truncdfsf2_media"
13913  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13914	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13915  "TARGET_SHMEDIA_FPU"
13916  "fcnv.ds	%1, %0"
13917  [(set_attr "type" "dfpconv_media")])
13918
13919(define_insn "truncdfsf2_i4"
13920  [(set (match_operand:SF 0 "fpul_operand" "=y")
13921	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13922   (clobber (reg:SI FPSCR_STAT_REG))
13923   (use (reg:SI FPSCR_MODES_REG))]
13924  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13925  "fcnvds  %1,%0"
13926  [(set_attr "type" "fp")
13927   (set_attr "fp_mode" "double")])
13928
13929;; -------------------------------------------------------------------------
13930;; Bit field extract patterns.
13931;; -------------------------------------------------------------------------
13932
13933;; These give better code for packed bitfields,  because they allow
13934;; auto-increment addresses to be generated.
13935
13936(define_expand "insv"
13937  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
13938			 (match_operand:SI 1 "immediate_operand" "")
13939			 (match_operand:SI 2 "immediate_operand" ""))
13940	(match_operand:SI 3 "general_operand" ""))]
13941  "TARGET_SH1 && TARGET_BIG_ENDIAN"
13942{
13943  rtx addr_target, orig_address, shift_reg, qi_val;
13944  HOST_WIDE_INT bitsize, size, v = 0;
13945  rtx x = operands[3];
13946
13947  if (TARGET_SH2A && TARGET_BITOPS
13948      && (satisfies_constraint_Sbw (operands[0])
13949	  || satisfies_constraint_Sbv (operands[0]))
13950      && satisfies_constraint_M (operands[1])
13951      && satisfies_constraint_K03 (operands[2]))
13952    {
13953      if (satisfies_constraint_N (operands[3]))
13954	{
13955	  emit_insn (gen_bclr_m2a (operands[0], operands[2]));
13956	  DONE;
13957	}
13958      else if (satisfies_constraint_M (operands[3]))
13959	{
13960	  emit_insn (gen_bset_m2a (operands[0], operands[2]));
13961	  DONE;
13962	}
13963      else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
13964		&& satisfies_constraint_M (operands[1]))
13965	{
13966	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
13967	  DONE;
13968	}
13969      else if (REG_P (operands[3])
13970	       && satisfies_constraint_M (operands[1]))
13971	{
13972	  emit_insn (gen_bldsi_reg (operands[3], const0_rtx));
13973	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
13974	  DONE;
13975	}
13976    }
13977  /* ??? expmed doesn't care for non-register predicates.  */
13978  if (! memory_operand (operands[0], VOIDmode)
13979      || ! immediate_operand (operands[1], VOIDmode)
13980      || ! immediate_operand (operands[2], VOIDmode)
13981      || ! general_operand (x, VOIDmode))
13982    FAIL;
13983  /* If this isn't a 16 / 24 / 32 bit field, or if
13984     it doesn't start on a byte boundary, then fail.  */
13985  bitsize = INTVAL (operands[1]);
13986  if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
13987      || (INTVAL (operands[2]) % 8) != 0)
13988    FAIL;
13989
13990  size = bitsize / 8;
13991  orig_address = XEXP (operands[0], 0);
13992  shift_reg = gen_reg_rtx (SImode);
13993  if (CONST_INT_P (x))
13994    {
13995      v = INTVAL (x);
13996      qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
13997    }
13998  else
13999    {
14000      emit_insn (gen_movsi (shift_reg, operands[3]));
14001      qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
14002    }
14003  addr_target = copy_addr_to_reg (plus_constant (Pmode,
14004						 orig_address, size - 1));
14005
14006  operands[0] = replace_equiv_address (operands[0], addr_target);
14007  emit_insn (gen_movqi (operands[0], qi_val));
14008
14009  while (size -= 1)
14010    {
14011      if (CONST_INT_P (x))
14012	qi_val
14013	  = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
14014      else
14015	{
14016	  emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
14017	  qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
14018	}
14019      emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
14020      emit_insn (gen_movqi (operands[0], qi_val));
14021    }
14022
14023  DONE;
14024})
14025
14026(define_insn "movua"
14027  [(set (match_operand:SI 0 "register_operand" "=z")
14028	(unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
14029		   UNSPEC_MOVUA))]
14030  "TARGET_SH4A"
14031  "movua.l	%1,%0"
14032  [(set_attr "type" "movua")])
14033
14034;; We shouldn't need this, but cse replaces increments with references
14035;; to other regs before flow has a chance to create post_inc
14036;; addressing modes, and only postreload's cse_move2add brings the
14037;; increments back to a usable form.
14038(define_peephole2
14039  [(set (match_operand:SI 0 "register_operand" "")
14040	(sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
14041			 (const_int 32) (const_int 0)))
14042   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
14043  "TARGET_SH4A && REGNO (operands[0]) != REGNO (operands[1])"
14044  [(set (match_operand:SI 0 "register_operand" "")
14045	(sign_extract:SI (mem:SI (post_inc:SI
14046				  (match_operand:SI 1 "register_operand" "")))
14047			 (const_int 32) (const_int 0)))]
14048  "")
14049
14050(define_expand "extv"
14051  [(set (match_operand:SI 0 "register_operand" "")
14052	(sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
14053			 (match_operand 2 "const_int_operand" "")
14054			 (match_operand 3 "const_int_operand" "")))]
14055  "TARGET_SH4A || TARGET_SH2A"
14056{
14057  if (TARGET_SH2A && TARGET_BITOPS
14058      && (satisfies_constraint_Sbw (operands[1])
14059	  || satisfies_constraint_Sbv (operands[1]))
14060      && satisfies_constraint_M (operands[2])
14061      && satisfies_constraint_K03 (operands[3]))
14062   {
14063      emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
14064      if (REGNO (operands[0]) != T_REG)
14065	emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
14066      DONE;
14067   }
14068  if (TARGET_SH4A
14069      && INTVAL (operands[2]) == 32
14070      && INTVAL (operands[3]) == 0
14071      && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
14072    {
14073      rtx src = adjust_address (operands[1], BLKmode, 0);
14074      set_mem_size (src, 4);
14075      emit_insn (gen_movua (operands[0], src));
14076      DONE;
14077    }
14078
14079  FAIL;
14080})
14081
14082(define_expand "extzv"
14083  [(set (match_operand:SI 0 "register_operand" "")
14084	(zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
14085			 (match_operand 2 "const_int_operand" "")
14086			 (match_operand 3 "const_int_operand" "")))]
14087  "TARGET_SH4A || TARGET_SH2A"
14088{
14089  if (TARGET_SH2A && TARGET_BITOPS
14090      && (satisfies_constraint_Sbw (operands[1])
14091	  || satisfies_constraint_Sbv (operands[1]))
14092      && satisfies_constraint_M (operands[2])
14093      && satisfies_constraint_K03 (operands[3]))
14094    {
14095      emit_insn (gen_bld_m2a (operands[1], operands[3]));
14096      if (REGNO (operands[0]) != T_REG)
14097	emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
14098      DONE;
14099    }
14100  if (TARGET_SH4A
14101      && INTVAL (operands[2]) == 32
14102      && INTVAL (operands[3]) == 0
14103      && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
14104    {
14105      rtx src = adjust_address (operands[1], BLKmode, 0);
14106      set_mem_size (src, 4);
14107      emit_insn (gen_movua (operands[0], src));
14108      DONE;
14109    }
14110
14111  FAIL;
14112})
14113
14114;; -------------------------------------------------------------------------
14115;; Extract negated single bit and zero extend it.
14116;; Generally we don't care about the exact xor const_int value, as long
14117;; as it contains the extracted bit.  For simplicity, the pattern variations
14118;; that convert everything into the primary '*neg_zero_extract_0' pattern use
14119;; a xor const_int -1 value.
14120
14121(define_insn_and_split "*neg_zero_extract_0"
14122  [(set (reg:SI T_REG)
14123	(zero_extract:SI (xor:QIHISI (match_operand:QIHISI 0 "arith_reg_operand")
14124				     (match_operand 1 "const_int_operand"))
14125			 (const_int 1)
14126			 (match_operand 2 "const_int_operand")))]
14127  "TARGET_SH1 && can_create_pseudo_p ()
14128   && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))"
14129  "#"
14130  "&& 1"
14131  [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 2))
14132		       (const_int 0)))]
14133{
14134  if (INTVAL (operands[2]) == 31 && <MODE>mode == SImode)
14135    {
14136      /* Use cmp/pz to extract bit 31 into the T bit.  */
14137      emit_insn (gen_cmpgesi_t (operands[0], const0_rtx));
14138      DONE;
14139    }
14140
14141  operands[2] = GEN_INT ((1 << INTVAL (operands[2])));
14142  if (GET_MODE (operands[0]) != SImode)
14143    operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
14144})
14145
14146(define_insn_and_split "*neg_zero_extract_1"
14147  [(set (reg:SI T_REG)
14148	(and:SI (not:SI (match_operand:SI 0 "arith_reg_operand"))
14149		(const_int 1)))]
14150  "TARGET_SH1"
14151  "#"
14152  "&& 1"
14153  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14154					(const_int 1) (const_int 0)))])
14155
14156;; x & (1 << n) == 0: 0x00000000 + 1 = 1
14157;; x & (1 << n) != 0: 0xFFFFFFFF + 1 = 0
14158(define_insn_and_split "*neg_zero_extract_2"
14159  [(set (reg:SI T_REG)
14160	(plus:SI (sign_extract:SI (match_operand:QIHISI 0 "arith_reg_operand")
14161				  (const_int 1)
14162				  (match_operand 1 "const_int_operand"))
14163		 (const_int 1)))]
14164  "TARGET_SH1 && can_create_pseudo_p ()"
14165  "#"
14166  "&& 1"
14167  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14168					(const_int 1) (match_dup 1)))])
14169
14170;; (signed)x >> 31 + 1 = (x >= 0) ^ 1
14171(define_insn_and_split "*neg_zero_extract_3"
14172  [(set (reg:SI T_REG)
14173	(plus:SI (ashiftrt:SI (match_operand:SI 0 "arith_reg_operand")
14174			      (const_int 31))
14175		 (const_int 1)))]
14176  "TARGET_SH1 && can_create_pseudo_p ()"
14177  "#"
14178  "&& 1"
14179  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14180					(const_int 1) (const_int 31)))])
14181
14182;; This is required for some bit patterns of DImode subregs.
14183;; It looks like combine gets confused by the DImode right shift and fails
14184;; to simplify things.
14185(define_insn_and_split "*neg_zero_extract_4"
14186  [(set (reg:SI T_REG)
14187	(and:SI (and:SI
14188		  (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand")
14189				       (match_operand 1 "const_int_operand"))
14190			       (match_operand 2 "const_int_operand"))
14191		  (not:SI (ashift:SI (match_operand:SI 3 "arith_reg_operand")
14192				     (match_operand 4 "const_int_operand"))))
14193		(const_int 1)))]
14194  "TARGET_SH1 && can_create_pseudo_p ()
14195   && INTVAL (operands[4]) > 0
14196   && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))"
14197  "#"
14198  "&& 1"
14199  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
14200				    	(const_int 1) (match_dup 2)))])
14201
14202(define_insn_and_split "*neg_zero_extract_5"
14203  [(set (reg:SI T_REG)
14204	(and:SI (not:SI (subreg:SI
14205			  (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand")
14206				       (match_operand 1 "const_int_operand"))
14207			 0))
14208		(const_int 1)))]
14209  "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()
14210   && INTVAL (operands[1]) < 32"
14211  "#"
14212  "&& 1"
14213  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14214					(const_int 1) (match_dup 1)))]
14215{
14216  operands[0] = gen_lowpart (SImode, operands[0]);
14217})
14218
14219(define_insn_and_split "*neg_zero_extract_6"
14220  [(set (reg:SI T_REG)
14221	(and:SI (not:SI (subreg:SI
14222			  (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand")
14223				       (match_operand 1 "const_int_operand"))
14224			 4))
14225		(const_int 1)))]
14226  "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()
14227   && INTVAL (operands[1]) < 32"
14228  "#"
14229  "&& 1"
14230  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14231					(const_int 1) (match_dup 1)))]
14232{
14233  operands[0] = gen_lowpart (SImode, operands[0]);
14234})
14235
14236;; -------------------------------------------------------------------------
14237;; Extract single bit and zero extend it.
14238;; All patterns store the result bit in the T bit, although that is not
14239;; always possible to do with a single insn and a nott must be appended.
14240;; The trailing nott will be optimized away in most cases.  E.g. if the
14241;; extracted bit is fed into a branch condition, the condition can be
14242;; inverted and the nott will be eliminated.
14243;; FIXME: In cases where the trailing nott can't be eliminated, try to
14244;; convert it into a (not, tst) sequence, which could be better on non-SH2A.
14245
14246;; On SH2A the 'bld<mode>_reg' insn will be used if the bit position fits.
14247(define_insn_and_split "*zero_extract_0"
14248  [(set (reg:SI T_REG)
14249	(zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand")
14250			 (const_int 1)
14251			 (match_operand 1 "const_int_operand")))]
14252  "TARGET_SH1 && can_create_pseudo_p ()
14253   && !(TARGET_SH2A && satisfies_constraint_K03 (operands[1]))"
14254  "#"
14255  "&& 1"
14256  [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 1))
14257			      (const_int 0)))
14258   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]
14259{
14260  if (INTVAL (operands[1]) == 31 && <MODE>mode == SImode)
14261    {
14262      emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
14263      DONE;
14264    }
14265
14266  operands[1] = GEN_INT (1 << INTVAL (operands[1]));
14267  if (GET_MODE (operands[0]) != SImode)
14268    operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
14269})
14270
14271;; This is required for some bit patterns of DImode subregs.
14272;; It looks like combine gets confused by the DImode right shift and fails
14273;; to simplify things.
14274(define_insn_and_split "*zero_extract_1"
14275  [(set (reg:SI T_REG)
14276	(subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand")
14277				    (const_int 1)
14278				    (match_operand 1 "const_int_operand"))
14279	 0))]
14280  "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()
14281   && INTVAL (operands[1]) < 32"
14282  "#"
14283  "&& 1"
14284  [(set (reg:SI T_REG)
14285	(zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))])
14286
14287(define_insn_and_split "*zero_extract_2"
14288  [(set (reg:SI T_REG)
14289	(subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand")
14290				    (const_int 1)
14291				    (match_operand 1 "const_int_operand"))
14292	 4))]
14293  "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()
14294   && INTVAL (operands[1]) < 32"
14295  "#"
14296  "&& 1"
14297  [(set (reg:SI T_REG)
14298	(zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))])
14299
14300;; -------------------------------------------------------------------------
14301;; SH2A instructions for bitwise operations.
14302;; FIXME: Convert multiple instruction insns to insn_and_split.
14303;; FIXME: Use iterators to fold at least and,xor,or insn variations.
14304
14305;; Clear a bit in a memory location.
14306(define_insn "bclr_m2a"
14307  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14308	(and:QI
14309	    (not:QI (ashift:QI (const_int 1)
14310			(match_operand:QI 1 "const_int_operand" "K03,K03")))
14311	    (match_dup 0)))]
14312  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14313  "@
14314	bclr.b	%1,%0
14315	bclr.b	%1,@(0,%t0)"
14316[(set_attr "length" "4,4")])
14317
14318(define_insn "bclrmem_m2a"
14319  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14320        (and:QI (match_dup 0)
14321                (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
14322  "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
14323  "@
14324        bclr.b	%W1,%0
14325        bclr.b	%W1,@(0,%t0)"
14326  [(set_attr "length" "4,4")])
14327
14328;; Set a bit in a memory location.
14329(define_insn "bset_m2a"
14330  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14331	(ior:QI
14332	    (ashift:QI (const_int 1)
14333		       (match_operand:QI 1 "const_int_operand" "K03,K03"))
14334	    (match_dup 0)))]
14335  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14336  "@
14337	bset.b	%1,%0
14338	bset.b	%1,@(0,%t0)"
14339  [(set_attr "length" "4,4")])
14340
14341(define_insn "bsetmem_m2a"
14342  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14343	(ior:QI (match_dup 0)
14344		(match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
14345  "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
14346  "@
14347        bset.b	%V1,%0
14348        bset.b	%V1,@(0,%t0)"
14349  [(set_attr "length" "4,4")])
14350
14351;;; Transfer the contents of the T bit to a specified bit of memory.
14352(define_insn "bst_m2a"
14353  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
14354	(if_then_else (eq (reg:SI T_REG) (const_int 0))
14355	    (and:QI
14356		(not:QI (ashift:QI (const_int 1)
14357			(match_operand:QI 1 "const_int_operand" "K03,K03")))
14358		(match_dup 0))
14359	    (ior:QI
14360		(ashift:QI (const_int 1) (match_dup 1))
14361		(match_dup 0))))]
14362  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14363  "@
14364	bst.b	%1,%0
14365	bst.b	%1,@(0,%t0)"
14366  [(set_attr "length" "4")])
14367
14368;; Store a specified bit of memory in the T bit.
14369(define_insn "bld_m2a"
14370  [(set (reg:SI T_REG)
14371	(zero_extract:SI
14372	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
14373	    (const_int 1)
14374	    (match_operand 1 "const_int_operand" "K03,K03")))]
14375  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14376  "@
14377	bld.b	%1,%0
14378	bld.b	%1,@(0,%t0)"
14379  [(set_attr "length" "4,4")])
14380
14381;; Store a specified bit of memory in the T bit.
14382(define_insn "bldsign_m2a"
14383  [(set (reg:SI T_REG)
14384	(sign_extract:SI
14385	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14386	    (const_int 1)
14387	    (match_operand 1 "const_int_operand" "K03,K03")))]
14388  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14389  "@
14390	bld.b	%1,%0
14391	bld.b	%1,@(0,%t0)"
14392  [(set_attr "length" "4,4")])
14393
14394;; Store a specified bit of the LSB 8 bits of a register in the T bit.
14395(define_insn "bld<mode>_reg"
14396  [(set (reg:SI T_REG)
14397	(zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand" "r")
14398			 (const_int 1)
14399			 (match_operand 1 "const_int_operand" "K03")))]
14400  "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
14401  "bld	%1,%0")
14402
14403;; Take logical and of a specified bit of memory with the T bit and
14404;; store its result in the T bit.
14405(define_insn "band_m2a"
14406  [(set (reg:SI T_REG)
14407	(and:SI (reg:SI T_REG)
14408		(zero_extract:SI
14409		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14410		    (const_int 1)
14411		    (match_operand 1 "const_int_operand" "K03,K03"))))]
14412  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14413  "@
14414	band.b	%1,%0
14415	band.b	%1,@(0,%t0)"
14416  [(set_attr "length" "4,4")])
14417
14418(define_insn "bandreg_m2a"
14419  [(set (match_operand:SI 0 "register_operand" "=r,r")
14420	(and:SI (zero_extract:SI
14421		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
14422		    (const_int 1)
14423		    (match_operand 2 "const_int_operand" "K03,K03"))
14424        	(match_operand:SI 3 "register_operand" "r,r")))]
14425  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
14426{
14427  static const char* alt[] =
14428  {
14429       "band.b	%2,%1"		"\n"
14430    "	movt	%0",
14431
14432       "band.b	%2,@(0,%t1)"	"\n"
14433    "	movt	%0"
14434  };
14435  return alt[which_alternative];
14436}
14437  [(set_attr "length" "6,6")])
14438
14439;; Take logical or of a specified bit of memory with the T bit and
14440;; store its result in the T bit.
14441(define_insn "bor_m2a"
14442  [(set (reg:SI T_REG)
14443	(ior:SI (reg:SI T_REG)
14444		(zero_extract:SI
14445		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14446		    (const_int 1)
14447		    (match_operand 1 "const_int_operand" "K03,K03"))))]
14448  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14449  "@
14450	bor.b	%1,%0
14451	bor.b	%1,@(0,%t0)"
14452  [(set_attr "length" "4,4")])
14453
14454(define_insn "borreg_m2a"
14455  [(set (match_operand:SI 0 "register_operand" "=r,r")
14456	(ior:SI (zero_extract:SI
14457		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
14458		    (const_int 1)
14459		    (match_operand 2 "const_int_operand" "K03,K03"))
14460		(match_operand:SI 3 "register_operand" "=r,r")))]
14461  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
14462{
14463  static const char* alt[] =
14464  {
14465       "bor.b	%2,%1"		"\n"
14466    "	movt	%0",
14467
14468       "bor.b	%2,@(0,%t1)"	"\n"
14469    "	movt	%0"
14470  };
14471  return alt[which_alternative];
14472}
14473  [(set_attr "length" "6,6")])
14474
14475;; Take exclusive or of a specified bit of memory with the T bit and
14476;; store its result in the T bit.
14477(define_insn "bxor_m2a"
14478  [(set (reg:SI T_REG)
14479	(xor:SI (reg:SI T_REG)
14480		(zero_extract:SI
14481		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14482		    (const_int 1)
14483		    (match_operand 1 "const_int_operand" "K03,K03"))))]
14484  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14485  "@
14486	bxor.b	%1,%0
14487	bxor.b	%1,@(0,%t0)"
14488  [(set_attr "length" "4,4")])
14489
14490(define_insn "bxorreg_m2a"
14491  [(set (match_operand:SI 0 "register_operand" "=r,r")
14492	(xor:SI (zero_extract:SI
14493		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
14494		    (const_int 1)
14495		    (match_operand 2 "const_int_operand" "K03,K03"))
14496		(match_operand:SI 3 "register_operand" "=r,r")))]
14497  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
14498{
14499  static const char* alt[] =
14500  {
14501       "bxor.b	%2,%1"		"\n"
14502    "	movt	%0",
14503
14504       "bxor.b	%2,@(0,%t1)"	"\n"
14505    "	movt	%0"
14506  };
14507  return alt[which_alternative];
14508}
14509  [(set_attr "length" "6,6")])
14510
14511;; -------------------------------------------------------------------------
14512;; Peepholes
14513;; -------------------------------------------------------------------------
14514;; This matches cases where the bit in a memory location is set.
14515(define_peephole2
14516  [(set (match_operand:SI 0 "register_operand")
14517	(sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
14518   (set (match_dup 0)
14519	(ior:SI (match_dup 0)
14520	(match_operand:SI 2 "const_int_operand")))
14521   (set (match_dup 1)
14522	(match_operand 3 "arith_reg_operand"))]
14523  "TARGET_SH2A && TARGET_BITOPS
14524   && satisfies_constraint_Pso (operands[2])
14525   && REGNO (operands[0]) == REGNO (operands[3])"
14526  [(set (match_dup 1)
14527        (ior:QI (match_dup 1) (match_dup 2)))]
14528  "")
14529
14530;; This matches cases where the bit in a memory location is cleared.
14531(define_peephole2
14532  [(set (match_operand:SI 0 "register_operand")
14533	(sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
14534   (set (match_dup 0)
14535	(and:SI (match_dup 0)
14536	(match_operand:SI 2 "const_int_operand")))
14537   (set (match_dup 1)
14538	(match_operand 3 "arith_reg_operand"))]
14539  "TARGET_SH2A && TARGET_BITOPS
14540   && satisfies_constraint_Psz (operands[2])
14541   && REGNO (operands[0]) == REGNO (operands[3])"
14542  [(set (match_dup 1)
14543        (and:QI (match_dup 1) (match_dup 2)))]
14544  "")
14545
14546;; This matches cases where a stack pointer increment at the start of the
14547;; epilogue combines with a stack slot read loading the return value.
14548(define_peephole
14549  [(set (match_operand:SI 0 "arith_reg_operand" "")
14550	(mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
14551   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
14552  "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
14553  "mov.l	@%1+,%0")
14554
14555;; See the comment on the dt combiner pattern above.
14556(define_peephole
14557  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
14558	(plus:SI (match_dup 0)
14559		 (const_int -1)))
14560   (set (reg:SI T_REG)
14561	(eq:SI (match_dup 0) (const_int 0)))]
14562  "TARGET_SH2"
14563  "dt	%0")
14564
14565;; The following peepholes fold load sequences for which reload was not
14566;; able to generate a displacement addressing move insn.
14567;; This can happen when reload has to transform a move insn 
14568;; without displacement into one with displacement.  Or when reload can't
14569;; fit a displacement into the insn's constraints.  In the latter case, the
14570;; load destination reg remains at r0, which reload compensates by inserting
14571;; another mov insn.
14572
14573;; Fold sequence:
14574;;	mov #54,r0
14575;;	mov.{b,w} @(r0,r15),r0
14576;;	mov r0,r3
14577;; into:
14578;;	mov.{b,w} @(54,r15),r3
14579;;
14580(define_peephole2
14581  [(set (match_operand:SI 0 "arith_reg_dest" "")
14582	(match_operand:SI 1 "const_int_operand" ""))
14583   (set (match_operand:SI 2 "arith_reg_dest" "")
14584	(sign_extend:SI
14585	 (mem:QI (plus:SI (match_dup 0)
14586			  (match_operand:SI 3 "arith_reg_operand" "")))))
14587   (set (match_operand:QI 4 "arith_reg_dest" "")
14588	(match_operand:QI 5 "arith_reg_operand" ""))]
14589  "TARGET_SH2A
14590   && sh_legitimate_index_p (QImode, operands[1], true, true)
14591   && REGNO (operands[2]) == REGNO (operands[5])
14592   && peep2_reg_dead_p (3, operands[5])"
14593  [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
14594  "")
14595
14596(define_peephole2
14597  [(set (match_operand:SI 0 "arith_reg_dest" "")
14598	(match_operand:SI 1 "const_int_operand" ""))
14599   (set (match_operand:SI 2 "arith_reg_dest" "")
14600	(sign_extend:SI
14601	 (mem:HI (plus:SI (match_dup 0)
14602			  (match_operand:SI 3 "arith_reg_operand" "")))))
14603   (set (match_operand:HI 4 "arith_reg_dest" "")
14604	(match_operand:HI 5 "arith_reg_operand" ""))]
14605  "TARGET_SH2A
14606   && sh_legitimate_index_p (HImode, operands[1], true, true)
14607   && REGNO (operands[2]) == REGNO (operands[5])
14608   && peep2_reg_dead_p (3, operands[5])"
14609  [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
14610  "")
14611
14612;; Fold sequence:
14613;;	mov #54,r0
14614;;	mov.{b,w} @(r0,r15),r1
14615;; into:
14616;;	mov.{b,w} @(54,r15),r1
14617;;
14618(define_peephole2
14619  [(set (match_operand:SI 0 "arith_reg_dest" "")
14620	(match_operand:SI 1 "const_int_operand" ""))
14621   (set (match_operand:SI 2 "arith_reg_dest" "")
14622	 (sign_extend:SI
14623	 (mem:QI (plus:SI (match_dup 0)
14624			  (match_operand:SI 3 "arith_reg_operand" "")))))]
14625  "TARGET_SH2A
14626   && sh_legitimate_index_p (QImode, operands[1], true, true)
14627   && (peep2_reg_dead_p (2, operands[0])
14628       || REGNO (operands[0]) == REGNO (operands[2]))"
14629  [(set (match_dup 2)
14630	(sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
14631  "")
14632
14633(define_peephole2
14634  [(set (match_operand:SI 0 "arith_reg_dest" "")
14635	(match_operand:SI 1 "const_int_operand" ""))
14636   (set (match_operand:SI 2 "arith_reg_dest" "")
14637	 (sign_extend:SI
14638	 (mem:HI (plus:SI (match_dup 0)
14639			  (match_operand:SI 3 "arith_reg_operand" "")))))]
14640  "TARGET_SH2A
14641   && sh_legitimate_index_p (HImode, operands[1], true, true)
14642   && (peep2_reg_dead_p (2, operands[0])
14643       || REGNO (operands[0]) == REGNO (operands[2]))"
14644  [(set (match_dup 2)
14645	(sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
14646  "")
14647
14648;; Fold sequence:
14649;;	mov.{b,w} @(r0,r15),r0
14650;;	mov r0,r3
14651;; into:
14652;;	mov.{b,w} @(r0,r15),r3
14653;;
14654;; This can happen when initially a displacement address is picked, where
14655;; the destination reg is fixed to r0, and then the address is transformed
14656;; into 'r0 + reg'.
14657(define_peephole2
14658  [(set (match_operand:SI 0 "arith_reg_dest" "")
14659	(sign_extend:SI
14660	 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
14661			  (match_operand:SI 2 "arith_reg_operand" "")))))
14662   (set (match_operand:QI 3 "arith_reg_dest" "")
14663	(match_operand:QI 4 "arith_reg_operand" ""))]
14664  "TARGET_SH1
14665   && REGNO (operands[0]) == REGNO (operands[4])
14666   && peep2_reg_dead_p (2, operands[0])"
14667  [(set (match_dup 3)
14668	(mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
14669  "")
14670
14671(define_peephole2
14672  [(set (match_operand:SI 0 "arith_reg_dest" "")
14673	(sign_extend:SI
14674	 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
14675			  (match_operand:SI 2 "arith_reg_operand" "")))))
14676   (set (match_operand:HI 3 "arith_reg_dest" "")
14677	(match_operand:HI 4 "arith_reg_operand" ""))]
14678  "TARGET_SH1
14679   && REGNO (operands[0]) == REGNO (operands[4])
14680   && peep2_reg_dead_p (2, operands[0])"
14681  [(set (match_dup 3)
14682	(mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
14683  "")
14684
14685;;	extu.bw	a,b
14686;;	mov	b,c	->	extu.bw	a,c
14687(define_peephole2
14688  [(set (match_operand:SI 0 "arith_reg_dest")
14689	(zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand")))
14690   (set (match_operand:SI 2 "arith_reg_dest")
14691	(match_dup 0))]
14692  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14693  [(set (match_dup 2) (zero_extend:SI (match_dup 1)))])
14694
14695;;	mov	r0,r1
14696;;	extu.bw	r1,r1   ->	extu.bw	r0,r1
14697(define_peephole2
14698  [(set (match_operand 0 "arith_reg_dest")
14699	(match_operand 1 "arith_reg_operand"))
14700   (set (match_operand:SI 2 "arith_reg_dest")
14701	(zero_extend:SI (match_operand:QIHI 3 "arith_reg_operand")))]
14702  "TARGET_SH1
14703   && REGNO (operands[0]) == REGNO (operands[3])
14704   && (REGNO (operands[0]) == REGNO (operands[2])
14705       || peep2_reg_dead_p (2, operands[0]))"
14706  [(set (match_dup 2) (zero_extend:SI (match_dup 1)))]
14707{
14708  operands[1] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
14709})
14710
14711;;	mov	a,b
14712;;	mov	b,a	->	< nop >
14713(define_peephole2
14714  [(set (match_operand 0 "register_operand")
14715	(match_operand 1 "register_operand"))
14716   (set (match_operand 2 "register_operand")
14717	(match_operand 3 "register_operand"))]
14718  "TARGET_SH1
14719   && REGNO (operands[0]) == REGNO (operands[3])
14720   && REGNO (operands[1]) == REGNO (operands[2])
14721   && peep2_reg_dead_p (2, operands[3])"
14722  [(const_int 0)])
14723
14724;;	mov	#3,r4
14725;;	and	r4,r1	->	mov	r1,r0
14726;;	mov	r1,r0		and	#3,r0
14727(define_code_iterator ANDIORXOR [and ior xor])
14728(define_peephole2
14729  [(set (match_operand:SI 0 "register_operand")
14730	(match_operand:SI 1 "const_logical_operand"))
14731   (set (match_operand:SI 2) (ANDIORXOR:SI (match_dup 2) (match_dup 0)))
14732   (set (reg:SI R0_REG) (match_dup 2))]
14733  "TARGET_SH1
14734   && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])"
14735  [(set (reg:SI R0_REG) (match_dup 2))
14736   (set (reg:SI R0_REG) (ANDIORXOR:SI (reg:SI R0_REG) (match_dup 1)))])
14737
14738;;	...	r2,r0		...	r2,r0
14739;;	or	r1,r0	->	or	r0,r1
14740;;	mov	r0,r1
14741;;	(r0 dead)
14742(define_code_iterator ANDIORXORPLUS [and ior xor plus])
14743(define_peephole2
14744  [(set (match_operand:SI 0 "arith_reg_dest")
14745	(ANDIORXORPLUS:SI (match_dup 0) (match_operand:SI 1 "arith_reg_dest")))
14746   (set (match_dup 1) (match_dup 0))]
14747  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14748  [(set (match_dup 1) (ANDIORXORPLUS:SI (match_dup 1) (match_dup 0)))])
14749
14750;;	mov	r12,r0
14751;;	add	#-48,r0     ->	add	#-48,r12
14752;;	mov.l	r0,@(4,r10)	mov.l	r12,@(4,r10)
14753;;	(r12 dead)
14754(define_peephole2
14755  [(set (match_operand:SI 0 "arith_reg_dest")
14756	(match_operand:SI 1 "arith_reg_dest"))
14757   (set (match_dup 0) (plus:SI (match_dup 0)
14758			       (match_operand:SI 2 "const_int_operand")))
14759   (set (match_operand:SI 3 "general_movdst_operand") (match_dup 0))]
14760  "TARGET_SH1
14761   && peep2_reg_dead_p (2, operands[1]) && peep2_reg_dead_p (3, operands[0])"
14762  [(const_int 0)]
14763{
14764  emit_insn (gen_addsi3 (operands[1], operands[1], operands[2]));
14765  sh_peephole_emit_move_insn (operands[3], operands[1]);
14766})
14767
14768;;	mov.l	@(r0,r9),r1
14769;;	mov	r1,r0	    ->	mov	@(r0,r9),r0
14770(define_peephole2
14771  [(set (match_operand:SI 0 "arith_reg_dest")
14772	(match_operand:SI 1 "general_movsrc_operand"))
14773   (set (match_operand:SI 2 "arith_reg_dest")
14774	(match_dup 0))]
14775  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14776  [(const_int 0)]
14777{
14778  sh_peephole_emit_move_insn (operands[2], operands[1]);
14779})
14780
14781(define_peephole2
14782  [(set (match_operand:QIHI 0 "register_operand")
14783	(match_operand:QIHI 1 "movsrc_no_disp_mem_operand"))
14784   (set (match_operand:QIHI 2 "register_operand")
14785	(match_dup 0))]
14786  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14787  [(const_int 0)]
14788{
14789  sh_peephole_emit_move_insn (operands[2], operands[1]);
14790})
14791
14792(define_peephole2
14793  [(set (match_operand:SI 0 "arith_reg_dest")
14794	(sign_extend:SI (match_operand:QIHI 1 "movsrc_no_disp_mem_operand")))
14795   (set (match_operand:SI 2 "arith_reg_dest")
14796	(match_dup 0))]
14797  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14798  [(const_int 0)]
14799{
14800  sh_check_add_incdec_notes (emit_insn (gen_extend<mode>si2 (operands[2],
14801		   sh_remove_overlapping_post_inc (operands[2], operands[1]))));
14802})
14803
14804;;	mov.w	@(18,r1),r0 (r0 = HImode)
14805;;	mov	r0,r1       (r0 = r1 = HImode)		mov.w	@(18,r1),r0
14806;;	...	..,r13      (r13 = SImode)	-> 	...	..,r13
14807;;	tst	r1,r13					tst	r0,r13
14808(define_peephole2
14809  [(set (match_operand 0 "arith_reg_dest")
14810	(match_operand 1 "arith_reg_dest"))
14811   (set (match_operand:SI 2 "arith_reg_dest")
14812	(match_operand:SI 3))
14813   (set (reg:SI T_REG)
14814	(eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand")
14815		       (match_operand:SI 5 "arith_reg_operand"))
14816	       (const_int 0)))]
14817  "TARGET_SH1
14818   && peep2_reg_dead_p (3, operands[0])
14819   && !reg_overlap_mentioned_p (operands[0], operands[3])
14820   && (REGNO (operands[0]) == REGNO (operands[4])
14821       || REGNO (operands[0]) == REGNO (operands[5]))
14822   && (REGNO (operands[2]) == REGNO (operands[4])
14823       || REGNO (operands[2]) == REGNO (operands[5]))"
14824  [(const_int 0)]
14825{
14826  if (REGNO (operands[1]) == REGNO (operands[2]))
14827      operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));
14828
14829  // We don't know what the new set insn will be in detail.  Just make sure
14830  // that it still can be recognized and the constraints are satisfied.
14831  rtx_insn* i = emit_insn (gen_rtx_SET (VOIDmode, operands[2],
14832		    sh_remove_overlapping_post_inc (operands[2], operands[3])));
14833
14834  recog_data_d prev_recog_data = recog_data;
14835  bool i_invalid = insn_invalid_p (i, false); 
14836  recog_data = prev_recog_data;
14837  
14838  if (i_invalid)
14839    FAIL;
14840    
14841  sh_check_add_incdec_notes (i);
14842
14843  emit_insn (gen_tstsi_t (operands[2],
14844			  gen_rtx_REG (SImode, (REGNO (operands[1])))));
14845})
14846
14847;;	mov.w	@(18,r1),r0 (r0 = HImode)
14848;;	...	..,r13	    (r13 = SImode)		mov.w	@(18,r1),r0
14849;;	mov	r0,r1       (r0 = r1 = HImode)	->	...	..,r13
14850;;	tst	r1,r13					tst	r0,r13
14851(define_peephole2
14852  [(set (match_operand:SI 2 "arith_reg_dest")
14853	(match_operand:SI 3))
14854   (set (match_operand 0 "arith_reg_dest")
14855	(match_operand 1 "arith_reg_operand"))
14856   (set (reg:SI T_REG)
14857	(eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand")
14858		       (match_operand:SI 5 "arith_reg_operand"))
14859	       (const_int 0)))]
14860  "TARGET_SH1
14861   && peep2_reg_dead_p (3, operands[0])
14862   && !reg_overlap_mentioned_p (operands[0], operands[3])
14863   && (REGNO (operands[0]) == REGNO (operands[4])
14864       || REGNO (operands[0]) == REGNO (operands[5]))
14865   && (REGNO (operands[2]) == REGNO (operands[4])
14866       || REGNO (operands[2]) == REGNO (operands[5]))"
14867  [(const_int 0)]
14868{
14869  // We don't know what the new set insn will be in detail.  Just make sure
14870  // that it still can be recognized and the constraints are satisfied.
14871  rtx_insn* i = emit_insn (gen_rtx_SET (VOIDmode, operands[2],
14872		    sh_remove_overlapping_post_inc (operands[2], operands[3])));
14873
14874  recog_data_d prev_recog_data = recog_data;
14875  bool i_invalid = insn_invalid_p (i, false); 
14876  recog_data = prev_recog_data;
14877  
14878  if (i_invalid)
14879    FAIL;
14880    
14881  sh_check_add_incdec_notes (i);
14882  
14883  emit_insn (gen_tstsi_t (operands[2],
14884			  gen_rtx_REG (SImode, (REGNO (operands[1])))));
14885})
14886
14887(define_peephole
14888  [(set (match_operand:SI 0 "register_operand" "=r")
14889	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
14890   (set (mem:SF (match_dup 0))
14891	(match_operand:SF 2 "general_movsrc_operand" ""))]
14892  "TARGET_SH1 && REGNO (operands[0]) == 0
14893   && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
14894       || (GET_CODE (operands[2]) == SUBREG
14895	   && REGNO (SUBREG_REG (operands[2])) < 16))
14896   && reg_unused_after (operands[0], insn)"
14897  "mov.l	%2,@(%0,%1)")
14898
14899(define_peephole
14900  [(set (match_operand:SI 0 "register_operand" "=r")
14901	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
14902   (set (match_operand:SF 2 "general_movdst_operand" "")
14903
14904	(mem:SF (match_dup 0)))]
14905  "TARGET_SH1 && REGNO (operands[0]) == 0
14906   && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
14907       || (GET_CODE (operands[2]) == SUBREG
14908	   && REGNO (SUBREG_REG (operands[2])) < 16))
14909   && reg_unused_after (operands[0], insn)"
14910  "mov.l	@(%0,%1),%2")
14911
14912(define_peephole
14913  [(set (match_operand:SI 0 "register_operand" "=r")
14914	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
14915   (set (mem:SF (match_dup 0))
14916	(match_operand:SF 2 "general_movsrc_operand" ""))]
14917  "TARGET_SH2E && REGNO (operands[0]) == 0
14918   && ((REG_P (operands[2])
14919        && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
14920       || (GET_CODE (operands[2]) == SUBREG
14921	   && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
14922   && reg_unused_after (operands[0], insn)"
14923  "fmov{.s|}	%2,@(%0,%1)")
14924
14925(define_peephole
14926  [(set (match_operand:SI 0 "register_operand" "=r")
14927	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
14928   (set (match_operand:SF 2 "general_movdst_operand" "")
14929
14930	(mem:SF (match_dup 0)))]
14931  "TARGET_SH2E && REGNO (operands[0]) == 0
14932   && ((REG_P (operands[2])
14933	&& FP_OR_XD_REGISTER_P (REGNO (operands[2])))
14934       || (GET_CODE (operands[2]) == SUBREG
14935	   && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
14936   && reg_unused_after (operands[0], insn)"
14937  "fmov{.s|}	@(%0,%1),%2")
14938
14939;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
14940(define_insn "sp_switch_1"
14941  [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")]
14942    UNSPECV_SP_SWITCH_B))]
14943  "TARGET_SH1"
14944{
14945  return       "mov.l	r0,@-r15"	"\n"
14946	 "	mov.l	%0,r0"		"\n"
14947	 "	mov.l	@r0,r0"		"\n"
14948	 "	mov.l	r15,@-r0"	"\n"
14949	 "	mov	r0,r15";
14950}
14951  [(set_attr "length" "10")])
14952
14953;; Switch back to the original stack for interrupt functions with the
14954;; sp_switch attribute.
14955(define_insn "sp_switch_2"
14956  [(unspec_volatile [(const_int 0)]
14957    UNSPECV_SP_SWITCH_E)]
14958  "TARGET_SH1"
14959{
14960  return       "mov.l	@r15,r15"	"\n"
14961	 "	mov.l	@r15+,r0";
14962}
14963  [(set_attr "length" "4")])
14964
14965;; -------------------------------------------------------------------------
14966;; Integer vector moves
14967;; -------------------------------------------------------------------------
14968
14969(define_expand "movv8qi"
14970  [(set (match_operand:V8QI 0 "general_movdst_operand" "")
14971	(match_operand:V8QI 1 "general_movsrc_operand" ""))]
14972  "TARGET_SHMEDIA"
14973{
14974  prepare_move_operands (operands, V8QImode);
14975})
14976
14977(define_insn "movv8qi_i"
14978  [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
14979	(match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14980  "TARGET_SHMEDIA
14981   && (register_operand (operands[0], V8QImode)
14982       || sh_register_operand (operands[1], V8QImode))"
14983  "@
14984	add	%1, r63, %0
14985	movi	%1, %0
14986	#
14987	ld%M1.q	%m1, %0
14988	st%M0.q	%m0, %N1"
14989  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
14990   (set_attr "length" "4,4,16,4,4")])
14991
14992(define_split
14993  [(set (match_operand:V8QI 0 "arith_reg_dest" "")
14994	(subreg:V8QI (const_int 0) 0))]
14995  "TARGET_SHMEDIA"
14996  [(set (match_dup 0)
14997	(const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
14998			    (const_int 0) (const_int 0) (const_int 0)
14999			    (const_int 0) (const_int 0)]))])
15000
15001(define_split
15002  [(set (match_operand 0 "arith_reg_dest" "")
15003	(match_operand 1 "sh_rep_vec" ""))]
15004  "TARGET_SHMEDIA && reload_completed
15005   && GET_MODE (operands[0]) == GET_MODE (operands[1])
15006   && sh_vector_mode_supported_p (GET_MODE (operands[0]))
15007   && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
15008   && (XVECEXP (operands[1], 0, 0) != const0_rtx
15009       || XVECEXP (operands[1], 0, 1) != const0_rtx)
15010   && (XVECEXP (operands[1], 0, 0) != constm1_rtx
15011       || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
15012  [(set (match_dup 0) (match_dup 1))
15013   (match_dup 2)]
15014{
15015  int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
15016  rtx elt1 = XVECEXP (operands[1], 0, 1);
15017
15018  if (unit_size > 2)
15019    operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
15020  else
15021    {
15022      if (unit_size < 2)
15023	operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
15024      operands[2] = gen_mperm_w0 (operands[0], operands[0]);
15025    }
15026  operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
15027  operands[1] = XVECEXP (operands[1], 0, 0);
15028  if (unit_size < 2)
15029    {
15030      if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
15031	operands[1]
15032	  = GEN_INT (TARGET_LITTLE_ENDIAN
15033		     ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
15034		     : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
15035      else
15036	{
15037	  operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
15038	  operands[1]
15039	    = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
15040	}
15041    }
15042})
15043
15044(define_split
15045  [(set (match_operand 0 "arith_reg_dest" "")
15046	(match_operand 1 "sh_const_vec" ""))]
15047  "TARGET_SHMEDIA && reload_completed
15048   && GET_MODE (operands[0]) == GET_MODE (operands[1])
15049   && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
15050  [(set (match_dup 0) (match_dup 1))]
15051{
15052  rtx v = operands[1];
15053  machine_mode new_mode
15054    = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
15055
15056  operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
15057  operands[1]
15058    = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
15059})
15060
15061(define_expand "movv2hi"
15062  [(set (match_operand:V2HI 0 "general_movdst_operand" "")
15063	(match_operand:V2HI 1 "general_movsrc_operand" ""))]
15064  "TARGET_SHMEDIA"
15065{
15066  prepare_move_operands (operands, V2HImode);
15067})
15068
15069(define_insn "movv2hi_i"
15070  [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
15071	(match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15072  "TARGET_SHMEDIA
15073   && (register_operand (operands[0], V2HImode)
15074       || sh_register_operand (operands[1], V2HImode))"
15075  "@
15076	add.l	%1, r63, %0
15077	movi	%1, %0
15078	#
15079	ld%M1.l	%m1, %0
15080	st%M0.l	%m0, %N1"
15081  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
15082   (set_attr "length" "4,4,16,4,4")
15083   (set (attr "highpart")
15084	(cond [(match_test "sh_contains_memref_p (insn)")
15085	       (const_string "user")]
15086	      (const_string "ignore")))])
15087
15088(define_expand "movv4hi"
15089  [(set (match_operand:V4HI 0 "general_movdst_operand" "")
15090	(match_operand:V4HI 1 "general_movsrc_operand" ""))]
15091  "TARGET_SHMEDIA"
15092{
15093  prepare_move_operands (operands, V4HImode);
15094})
15095
15096(define_insn "movv4hi_i"
15097  [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
15098	(match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15099  "TARGET_SHMEDIA
15100   && (register_operand (operands[0], V4HImode)
15101       || sh_register_operand (operands[1], V4HImode))"
15102  "@
15103	add	%1, r63, %0
15104	movi	%1, %0
15105	#
15106	ld%M1.q	%m1, %0
15107	st%M0.q	%m0, %N1"
15108  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
15109   (set_attr "length" "4,4,16,4,4")
15110   (set_attr "highpart" "depend")])
15111
15112(define_expand "movv2si"
15113  [(set (match_operand:V2SI 0 "general_movdst_operand" "")
15114	(match_operand:V2SI 1 "general_movsrc_operand" ""))]
15115  "TARGET_SHMEDIA"
15116{
15117  prepare_move_operands (operands, V2SImode);
15118})
15119
15120(define_insn "movv2si_i"
15121  [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
15122	(match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15123  "TARGET_SHMEDIA
15124   && (register_operand (operands[0], V2SImode)
15125       || sh_register_operand (operands[1], V2SImode))"
15126  "@
15127	add	%1, r63, %0
15128	#
15129	#
15130	ld%M1.q	%m1, %0
15131	st%M0.q	%m0, %N1"
15132  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
15133   (set_attr "length" "4,4,16,4,4")
15134   (set_attr "highpart" "depend")])
15135
15136;; -------------------------------------------------------------------------
15137;; Multimedia Intrinsics
15138;; -------------------------------------------------------------------------
15139
15140(define_insn "absv2si2"
15141  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15142	(abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
15143  "TARGET_SHMEDIA"
15144  "mabs.l	%1, %0"
15145  [(set_attr "type" "mcmp_media")
15146   (set_attr "highpart" "depend")])
15147
15148(define_insn "absv4hi2"
15149  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15150	(abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
15151  "TARGET_SHMEDIA"
15152  "mabs.w	%1, %0"
15153  [(set_attr "type" "mcmp_media")
15154   (set_attr "highpart" "depend")])
15155
15156(define_insn "addv2si3"
15157  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15158	(plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
15159		   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15160  "TARGET_SHMEDIA"
15161  "madd.l	%1, %2, %0"
15162  [(set_attr "type" "arith_media")
15163   (set_attr "highpart" "depend")])
15164
15165(define_insn "addv4hi3"
15166  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15167	(plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
15168		   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15169  "TARGET_SHMEDIA"
15170  "madd.w	%1, %2, %0"
15171  [(set_attr "type" "arith_media")
15172   (set_attr "highpart" "depend")])
15173
15174(define_insn_and_split "addv2hi3"
15175  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
15176	(plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
15177		   (match_operand:V2HI 2 "extend_reg_operand" "r")))]
15178  "TARGET_SHMEDIA"
15179  "#"
15180  "TARGET_SHMEDIA"
15181  [(const_int 0)]
15182{
15183  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
15184  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
15185  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
15186  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
15187  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
15188
15189  emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
15190  emit_insn (gen_truncdisi2 (si_dst, di_dst));
15191  DONE;
15192}
15193  [(set_attr "highpart" "must_split")])
15194
15195(define_insn "ssaddv2si3"
15196  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15197	(ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
15198		      (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15199  "TARGET_SHMEDIA"
15200  "madds.l	%1, %2, %0"
15201  [(set_attr "type" "mcmp_media")
15202   (set_attr "highpart" "depend")])
15203
15204(define_insn "usaddv8qi3"
15205  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15206	(us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
15207		      (match_operand:V8QI 2 "arith_reg_operand" "r")))]
15208  "TARGET_SHMEDIA"
15209  "madds.ub	%1, %2, %0"
15210  [(set_attr "type" "mcmp_media")
15211   (set_attr "highpart" "depend")])
15212
15213(define_insn "ssaddv4hi3"
15214  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15215	(ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
15216		      (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15217  "TARGET_SHMEDIA"
15218  "madds.w	%1, %2, %0"
15219  [(set_attr "type" "mcmp_media")
15220   (set_attr "highpart" "depend")])
15221
15222(define_insn "negcmpeqv8qi"
15223  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15224	(neg:V8QI (eq:V8QI
15225		    (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
15226		    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
15227  "TARGET_SHMEDIA"
15228  "mcmpeq.b	%N1, %N2, %0"
15229  [(set_attr "type" "mcmp_media")
15230   (set_attr "highpart" "depend")])
15231
15232(define_insn "negcmpeqv2si"
15233  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15234	(neg:V2SI (eq:V2SI
15235		    (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
15236		    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
15237  "TARGET_SHMEDIA"
15238  "mcmpeq.l	%N1, %N2, %0"
15239  [(set_attr "type" "mcmp_media")
15240   (set_attr "highpart" "depend")])
15241
15242(define_insn "negcmpeqv4hi"
15243  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15244	(neg:V4HI (eq:V4HI
15245		    (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
15246		    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15247  "TARGET_SHMEDIA"
15248  "mcmpeq.w	%N1, %N2, %0"
15249  [(set_attr "type" "mcmp_media")
15250   (set_attr "highpart" "depend")])
15251
15252(define_insn "negcmpgtuv8qi"
15253  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15254	(neg:V8QI (gtu:V8QI
15255		    (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
15256		    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
15257  "TARGET_SHMEDIA"
15258  "mcmpgt.ub	%N1, %N2, %0"
15259  [(set_attr "type" "mcmp_media")
15260   (set_attr "highpart" "depend")])
15261
15262(define_insn "negcmpgtv2si"
15263  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15264	(neg:V2SI (gt:V2SI
15265		    (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
15266		    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
15267  "TARGET_SHMEDIA"
15268  "mcmpgt.l	%N1, %N2, %0"
15269  [(set_attr "type" "mcmp_media")
15270   (set_attr "highpart" "depend")])
15271
15272(define_insn "negcmpgtv4hi"
15273  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15274	(neg:V4HI (gt:V4HI
15275		    (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
15276		    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15277  "TARGET_SHMEDIA"
15278  "mcmpgt.w	%N1, %N2, %0"
15279  [(set_attr "type" "mcmp_media")
15280   (set_attr "highpart" "depend")])
15281
15282(define_insn "mcmv"
15283  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15284	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15285			(match_operand:DI 2 "arith_reg_operand" "r"))
15286		(and:DI (match_operand:DI 3 "arith_reg_operand" "0")
15287			(not:DI (match_dup 2)))))]
15288  "TARGET_SHMEDIA"
15289  "mcmv	%N1, %2, %0"
15290  [(set_attr "type" "arith_media")
15291   (set_attr "highpart" "depend")])
15292
15293(define_insn "mcnvs_lw"
15294  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15295	(vec_concat:V4HI
15296	 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
15297	 (ss_truncate:V2HI
15298	   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
15299  "TARGET_SHMEDIA"
15300  "mcnvs.lw	%N1, %N2, %0"
15301  [(set_attr "type" "mcmp_media")])
15302
15303(define_insn "mcnvs_wb"
15304  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15305	(vec_concat:V8QI
15306	 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
15307	 (ss_truncate:V4QI
15308	   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15309  "TARGET_SHMEDIA"
15310  "mcnvs.wb	%N1, %N2, %0"
15311  [(set_attr "type" "mcmp_media")])
15312
15313(define_insn "mcnvs_wub"
15314  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15315	(vec_concat:V8QI
15316	 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
15317	 (us_truncate:V4QI
15318	   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15319  "TARGET_SHMEDIA"
15320  "mcnvs.wub	%N1, %N2, %0"
15321  [(set_attr "type" "mcmp_media")])
15322
15323(define_insn "mextr_rl"
15324  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15325	(ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15326			     (match_operand:HI 3 "mextr_bit_offset" "i"))
15327		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15328			   (match_operand:HI 4 "mextr_bit_offset" "i"))))]
15329  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
15330{
15331  static char templ[21];
15332  sprintf (templ, "mextr%d	%%N1, %%N2, %%0",
15333	   (int) INTVAL (operands[3]) >> 3);
15334  return templ;
15335}
15336  [(set_attr "type" "arith_media")])
15337
15338(define_insn "*mextr_lr"
15339  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15340	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15341			   (match_operand:HI 3 "mextr_bit_offset" "i"))
15342		(lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15343			     (match_operand:HI 4 "mextr_bit_offset" "i"))))]
15344  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
15345{
15346  static char templ[21];
15347  sprintf (templ, "mextr%d	%%N2, %%N1, %%0",
15348	   (int) INTVAL (operands[4]) >> 3);
15349  return templ;
15350}
15351  [(set_attr "type" "arith_media")])
15352
15353; mextrN can be modelled with vec_select / vec_concat, but the selection
15354; vector then varies depending on endianness.
15355(define_expand "mextr1"
15356  [(match_operand:DI 0 "arith_reg_dest" "")
15357   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15358   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15359  "TARGET_SHMEDIA"
15360{
15361  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15362			   GEN_INT (1 * 8), GEN_INT (7 * 8)));
15363  DONE;
15364})
15365
15366(define_expand "mextr2"
15367  [(match_operand:DI 0 "arith_reg_dest" "")
15368   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15369   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15370  "TARGET_SHMEDIA"
15371{
15372  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15373			   GEN_INT (2 * 8), GEN_INT (6 * 8)));
15374  DONE;
15375})
15376
15377(define_expand "mextr3"
15378  [(match_operand:DI 0 "arith_reg_dest" "")
15379   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15380   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15381  "TARGET_SHMEDIA"
15382{
15383  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15384			   GEN_INT (3 * 8), GEN_INT (5 * 8)));
15385  DONE;
15386})
15387
15388(define_expand "mextr4"
15389  [(match_operand:DI 0 "arith_reg_dest" "")
15390   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15391   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15392  "TARGET_SHMEDIA"
15393{
15394  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15395			   GEN_INT (4 * 8), GEN_INT (4 * 8)));
15396  DONE;
15397})
15398
15399(define_expand "mextr5"
15400  [(match_operand:DI 0 "arith_reg_dest" "")
15401   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15402   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15403  "TARGET_SHMEDIA"
15404{
15405  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15406			   GEN_INT (5 * 8), GEN_INT (3 * 8)));
15407  DONE;
15408})
15409
15410(define_expand "mextr6"
15411  [(match_operand:DI 0 "arith_reg_dest" "")
15412   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15413   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15414  "TARGET_SHMEDIA"
15415{
15416  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15417			   GEN_INT (6 * 8), GEN_INT (2 * 8)));
15418  DONE;
15419})
15420
15421(define_expand "mextr7"
15422  [(match_operand:DI 0 "arith_reg_dest" "")
15423   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15424   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15425  "TARGET_SHMEDIA"
15426{
15427  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15428			   GEN_INT (7 * 8), GEN_INT (1 * 8)));
15429  DONE;
15430})
15431
15432(define_expand "mmacfx_wl"
15433  [(match_operand:V2SI 0 "arith_reg_dest" "")
15434   (match_operand:V2HI 1 "extend_reg_operand" "")
15435   (match_operand:V2HI 2 "extend_reg_operand" "")
15436   (match_operand:V2SI 3 "arith_reg_operand" "")]
15437  "TARGET_SHMEDIA"
15438{
15439  emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
15440			      operands[1], operands[2]));
15441  DONE;
15442})
15443
15444;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
15445;; is depend
15446(define_insn "mmacfx_wl_i"
15447  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15448	(ss_plus:V2SI
15449	 (match_operand:V2SI 1 "arith_reg_operand" "0")
15450	 (ss_truncate:V2SI
15451	  (ashift:V2DI
15452	   (sign_extend:V2DI
15453	    (mult:V2SI
15454	     (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
15455	     (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
15456	   (const_int 1)))))]
15457  "TARGET_SHMEDIA"
15458  "mmacfx.wl	%2, %3, %0"
15459  [(set_attr "type" "mac_media")
15460   (set_attr "highpart" "depend")])
15461
15462(define_expand "mmacnfx_wl"
15463  [(match_operand:V2SI 0 "arith_reg_dest" "")
15464   (match_operand:V2HI 1 "extend_reg_operand" "")
15465   (match_operand:V2HI 2 "extend_reg_operand" "")
15466   (match_operand:V2SI 3 "arith_reg_operand" "")]
15467  "TARGET_SHMEDIA"
15468{
15469  emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
15470			       operands[1], operands[2]));
15471  DONE;
15472})
15473
15474(define_insn "mmacnfx_wl_i"
15475  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15476	(ss_minus:V2SI
15477	 (match_operand:V2SI 1 "arith_reg_operand" "0")
15478	 (ss_truncate:V2SI
15479	  (ashift:V2DI
15480	   (sign_extend:V2DI
15481	    (mult:V2SI
15482	     (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
15483	     (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
15484	   (const_int 1)))))]
15485  "TARGET_SHMEDIA"
15486  "mmacnfx.wl	%2, %3, %0"
15487  [(set_attr "type" "mac_media")
15488   (set_attr "highpart" "depend")])
15489
15490(define_insn "mulv2si3"
15491  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15492	(mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15493		   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15494  "TARGET_SHMEDIA"
15495  "mmul.l	%1, %2, %0"
15496  [(set_attr "type" "d2mpy_media")
15497   (set_attr "highpart" "depend")])
15498
15499(define_insn "mulv4hi3"
15500  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15501	(mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15502		   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15503  "TARGET_SHMEDIA"
15504  "mmul.w	%1, %2, %0"
15505  [(set_attr "type" "dmpy_media")
15506   (set_attr "highpart" "depend")])
15507
15508(define_insn "mmulfx_l"
15509  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15510	(ss_truncate:V2SI
15511	 (ashiftrt:V2DI
15512	  (mult:V2DI
15513	   (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
15514	   (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
15515	  (const_int 31))))]
15516  "TARGET_SHMEDIA"
15517  "mmulfx.l	%1, %2, %0"
15518  [(set_attr "type" "d2mpy_media")
15519   (set_attr "highpart" "depend")])
15520
15521(define_insn "mmulfx_w"
15522  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15523	(ss_truncate:V4HI
15524	 (ashiftrt:V4SI
15525	  (mult:V4SI
15526	   (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15527	   (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15528	  (const_int 15))))]
15529  "TARGET_SHMEDIA"
15530  "mmulfx.w	%1, %2, %0"
15531  [(set_attr "type" "dmpy_media")
15532   (set_attr "highpart" "depend")])
15533
15534(define_insn "mmulfxrp_w"
15535  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15536	(ss_truncate:V4HI
15537	 (ashiftrt:V4SI
15538	  (plus:V4SI
15539	   (mult:V4SI
15540	    (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15541	    (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15542	   (const_int 16384))
15543	  (const_int 15))))]
15544  "TARGET_SHMEDIA"
15545  "mmulfxrp.w	%1, %2, %0"
15546  [(set_attr "type" "dmpy_media")
15547   (set_attr "highpart" "depend")])
15548
15549
15550(define_expand "mmulhi_wl"
15551  [(match_operand:V2SI 0 "arith_reg_dest" "")
15552   (match_operand:V4HI 1 "arith_reg_operand" "")
15553   (match_operand:V4HI 2 "arith_reg_operand" "")]
15554  "TARGET_SHMEDIA"
15555{
15556  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
15557	     (operands[0], operands[1], operands[2]));
15558  DONE;
15559})
15560
15561(define_expand "mmullo_wl"
15562  [(match_operand:V2SI 0 "arith_reg_dest" "")
15563   (match_operand:V4HI 1 "arith_reg_operand" "")
15564   (match_operand:V4HI 2 "arith_reg_operand" "")]
15565  "TARGET_SHMEDIA"
15566{
15567  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
15568	     (operands[0], operands[1], operands[2]));
15569  DONE;
15570})
15571
15572(define_insn "mmul23_wl"
15573  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15574	(vec_select:V2SI
15575	 (mult:V4SI
15576	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15577	  (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15578	 (parallel [(const_int 2) (const_int 3)])))]
15579  "TARGET_SHMEDIA"
15580{
15581  return (TARGET_LITTLE_ENDIAN
15582	  ? "mmulhi.wl	%1, %2, %0"
15583	  : "mmullo.wl	%1, %2, %0");
15584}
15585  [(set_attr "type" "dmpy_media")
15586   (set (attr "highpart")
15587	(cond [(eq_attr "endian" "big") (const_string "ignore")]
15588	 (const_string "user")))])
15589
15590(define_insn "mmul01_wl"
15591  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15592	(vec_select:V2SI
15593	 (mult:V4SI
15594	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15595	  (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15596	 (parallel [(const_int 0) (const_int 1)])))]
15597  "TARGET_SHMEDIA"
15598{
15599  return (TARGET_LITTLE_ENDIAN
15600	  ? "mmullo.wl	%1, %2, %0"
15601	  : "mmulhi.wl	%1, %2, %0");
15602}
15603  [(set_attr "type" "dmpy_media")
15604   (set (attr "highpart")
15605	(cond [(eq_attr "endian" "little") (const_string "ignore")]
15606	 (const_string "user")))])
15607
15608
15609(define_expand "mmulsum_wq"
15610  [(match_operand:DI 0 "arith_reg_dest" "")
15611   (match_operand:V4HI 1 "arith_reg_operand" "")
15612   (match_operand:V4HI 2 "arith_reg_operand" "")
15613   (match_operand:DI 3 "arith_reg_operand" "")]
15614  "TARGET_SHMEDIA"
15615{
15616  emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
15617			       operands[1], operands[2]));
15618  DONE;
15619})
15620
15621(define_insn "mmulsum_wq_i"
15622  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15623	(plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
15624	 (plus:DI
15625	  (plus:DI
15626	   (vec_select:DI
15627	    (mult:V4DI
15628	     (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
15629	     (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
15630	    (parallel [(const_int 0)]))
15631	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
15632				     (sign_extend:V4DI (match_dup 3)))
15633			  (parallel [(const_int 1)])))
15634	  (plus:DI
15635	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
15636				     (sign_extend:V4DI (match_dup 3)))
15637			  (parallel [(const_int 2)]))
15638	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
15639				     (sign_extend:V4DI (match_dup 3)))
15640			  (parallel [(const_int 3)]))))))]
15641  "TARGET_SHMEDIA"
15642  "mmulsum.wq	%2, %3, %0"
15643  [(set_attr "type" "mac_media")])
15644
15645(define_expand "mperm_w"
15646  [(match_operand:V4HI 0 "arith_reg_dest" "=r")
15647   (match_operand:V4HI 1 "arith_reg_operand" "r")
15648   (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
15649  "TARGET_SHMEDIA"
15650{
15651  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
15652	     (operands[0], operands[1], operands[2]));
15653  DONE;
15654})
15655
15656; This use of vec_select isn't exactly correct according to rtl.texi
15657; (because not constant), but it seems a straightforward extension.
15658(define_insn "mperm_w_little"
15659  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15660	(vec_select:V4HI
15661	 (match_operand:V4HI 1 "arith_reg_operand" "r")
15662	 (parallel
15663	  [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
15664			    (const_int 2) (const_int 0))
15665	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
15666	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
15667	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
15668  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
15669  "mperm.w	%1, %N2, %0"
15670  [(set_attr "type" "arith_media")])
15671
15672(define_insn "mperm_w_big"
15673  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15674	(vec_select:V4HI
15675	 (match_operand:V4HI 1 "arith_reg_operand" "r")
15676	 (parallel
15677	  [(zero_extract:QI (not:QI (match_operand:QI 2
15678				     "extend_reg_or_0_operand" "rZ"))
15679			    (const_int 2) (const_int 0))
15680	   (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
15681	   (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
15682	   (zero_extract:QI (not:QI (match_dup 2))
15683			    (const_int 2) (const_int 6))])))]
15684  "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
15685  "mperm.w	%1, %N2, %0"
15686  [(set_attr "type" "arith_media")])
15687
15688(define_insn "mperm_w0"
15689  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15690	(vec_duplicate:V4HI (truncate:HI (match_operand 1
15691					  "trunc_hi_operand" "r"))))]
15692  "TARGET_SHMEDIA"
15693  "mperm.w	%1, r63, %0"
15694  [(set_attr "type" "arith_media")
15695   (set_attr "highpart" "ignore")])
15696
15697(define_expand "msad_ubq"
15698  [(match_operand:DI 0 "arith_reg_dest" "")
15699   (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
15700   (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
15701   (match_operand:DI 3 "arith_reg_operand" "")]
15702  "TARGET_SHMEDIA"
15703{
15704  emit_insn (gen_msad_ubq_i (operands[0], operands[3],
15705			     operands[1], operands[2]));
15706  DONE;
15707})
15708
15709(define_insn "msad_ubq_i"
15710  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15711	(plus:DI
15712	 (plus:DI
15713	  (plus:DI
15714	   (plus:DI
15715	    (match_operand:DI 1 "arith_reg_operand" "0")
15716	    (abs:DI (vec_select:DI
15717		     (minus:V8DI
15718		      (zero_extend:V8DI
15719		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
15720		      (zero_extend:V8DI
15721		       (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
15722		     (parallel [(const_int 0)]))))
15723	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15724					      (zero_extend:V8DI (match_dup 3)))
15725				  (parallel [(const_int 1)]))))
15726	  (plus:DI
15727	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15728					      (zero_extend:V8DI (match_dup 3)))
15729				  (parallel [(const_int 2)])))
15730	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15731					      (zero_extend:V8DI (match_dup 3)))
15732				  (parallel [(const_int 3)])))))
15733	 (plus:DI
15734	  (plus:DI
15735	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15736					      (zero_extend:V8DI (match_dup 3)))
15737				  (parallel [(const_int 4)])))
15738	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15739					      (zero_extend:V8DI (match_dup 3)))
15740				  (parallel [(const_int 5)]))))
15741	  (plus:DI
15742	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15743					      (zero_extend:V8DI (match_dup 3)))
15744				  (parallel [(const_int 6)])))
15745	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15746					      (zero_extend:V8DI (match_dup 3)))
15747				  (parallel [(const_int 7)])))))))]
15748  "TARGET_SHMEDIA"
15749  "msad.ubq	%N2, %N3, %0"
15750  [(set_attr "type" "mac_media")])
15751
15752(define_insn "mshalds_l"
15753  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15754	(ss_truncate:V2SI
15755	 (ashift:V2DI
15756	  (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
15757	  (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
15758		  (const_int 31)))))]
15759  "TARGET_SHMEDIA"
15760  "mshalds.l	%1, %2, %0"
15761  [(set_attr "type" "mcmp_media")
15762   (set_attr "highpart" "depend")])
15763
15764(define_insn "mshalds_w"
15765  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15766	(ss_truncate:V4HI
15767	 (ashift:V4SI
15768	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15769	  (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
15770		  (const_int 15)))))]
15771  "TARGET_SHMEDIA"
15772  "mshalds.w	%1, %2, %0"
15773  [(set_attr "type" "mcmp_media")
15774   (set_attr "highpart" "depend")])
15775
15776(define_insn "ashrv2si3"
15777  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15778	(ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15779		       (match_operand:DI 2 "arith_reg_operand" "r")))]
15780  "TARGET_SHMEDIA"
15781  "mshard.l	%1, %2, %0"
15782  [(set_attr "type" "arith_media")
15783   (set_attr "highpart" "depend")])
15784
15785(define_insn "ashrv4hi3"
15786  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15787	(ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15788		       (match_operand:DI 2 "arith_reg_operand" "r")))]
15789  "TARGET_SHMEDIA"
15790  "mshard.w	%1, %2, %0"
15791  [(set_attr "type" "arith_media")
15792   (set_attr "highpart" "depend")])
15793
15794(define_insn "mshards_q"
15795  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
15796	(ss_truncate:HI
15797	 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
15798		      (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
15799  "TARGET_SHMEDIA"
15800  "mshards.q	%1, %N2, %0"
15801  [(set_attr "type" "mcmp_media")])
15802
15803(define_expand "mshfhi_b"
15804  [(match_operand:V8QI 0 "arith_reg_dest" "")
15805   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15806   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
15807  "TARGET_SHMEDIA"
15808{
15809  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
15810	     (operands[0], operands[1], operands[2]));
15811  DONE;
15812})
15813
15814(define_expand "mshflo_b"
15815  [(match_operand:V8QI 0 "arith_reg_dest" "")
15816   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15817   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
15818  "TARGET_SHMEDIA"
15819{
15820  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
15821	     (operands[0], operands[1], operands[2]));
15822  DONE;
15823})
15824
15825(define_insn "mshf4_b"
15826  [(set
15827    (match_operand:V8QI 0 "arith_reg_dest" "=r")
15828    (vec_select:V8QI
15829     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15830		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
15831     (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
15832		(const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
15833  "TARGET_SHMEDIA"
15834{
15835  return (TARGET_LITTLE_ENDIAN
15836	  ? "mshfhi.b	%N1, %N2, %0"
15837	  : "mshflo.b	%N1, %N2, %0");
15838}
15839  [(set_attr "type" "arith_media")
15840   (set (attr "highpart")
15841	(cond [(eq_attr "endian" "big") (const_string "ignore")]
15842	 (const_string "user")))])
15843
15844(define_insn "mshf0_b"
15845  [(set
15846    (match_operand:V8QI 0 "arith_reg_dest" "=r")
15847    (vec_select:V8QI
15848     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15849		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
15850     (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
15851		(const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
15852  "TARGET_SHMEDIA"
15853{
15854  return (TARGET_LITTLE_ENDIAN
15855	  ? "mshflo.b	%N1, %N2, %0"
15856	  : "mshfhi.b	%N1, %N2, %0");
15857}
15858  [(set_attr "type" "arith_media")
15859   (set (attr "highpart")
15860	(cond [(eq_attr "endian" "little") (const_string "ignore")]
15861	 (const_string "user")))])
15862
15863(define_expand "mshfhi_l"
15864  [(match_operand:V2SI 0 "arith_reg_dest" "")
15865   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15866   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
15867  "TARGET_SHMEDIA"
15868{
15869  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
15870	     (operands[0], operands[1], operands[2]));
15871  DONE;
15872})
15873
15874(define_expand "mshflo_l"
15875  [(match_operand:V2SI 0 "arith_reg_dest" "")
15876   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15877   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
15878  "TARGET_SHMEDIA"
15879{
15880  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
15881	     (operands[0], operands[1], operands[2]));
15882  DONE;
15883})
15884
15885(define_insn "mshf4_l"
15886  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15887	(vec_select:V2SI
15888	 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15889			  (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
15890	 (parallel [(const_int 1) (const_int 3)])))]
15891  "TARGET_SHMEDIA"
15892{
15893  return (TARGET_LITTLE_ENDIAN
15894	  ? "mshfhi.l	%N1, %N2, %0"
15895	  : "mshflo.l	%N1, %N2, %0");
15896}
15897  [(set_attr "type" "arith_media")
15898   (set (attr "highpart")
15899	(cond [(eq_attr "endian" "big") (const_string "ignore")]
15900	 (const_string "user")))])
15901
15902(define_insn "mshf0_l"
15903  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15904	(vec_select:V2SI
15905	 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15906			  (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
15907	 (parallel [(const_int 0) (const_int 2)])))]
15908  "TARGET_SHMEDIA"
15909{
15910  return (TARGET_LITTLE_ENDIAN
15911	  ? "mshflo.l	%N1, %N2, %0"
15912	  : "mshfhi.l	%N1, %N2, %0");
15913}
15914  [(set_attr "type" "arith_media")
15915   (set (attr "highpart")
15916	(cond [(eq_attr "endian" "little") (const_string "ignore")]
15917	 (const_string "user")))])
15918
15919(define_expand "mshfhi_w"
15920  [(match_operand:V4HI 0 "arith_reg_dest" "")
15921   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15922   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
15923  "TARGET_SHMEDIA"
15924{
15925  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
15926	     (operands[0], operands[1], operands[2]));
15927  DONE;
15928})
15929
15930(define_expand "mshflo_w"
15931  [(match_operand:V4HI 0 "arith_reg_dest" "")
15932   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15933   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
15934  "TARGET_SHMEDIA"
15935{
15936  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
15937	     (operands[0], operands[1], operands[2]));
15938  DONE;
15939})
15940
15941(define_insn "mshf4_w"
15942  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15943	(vec_select:V4HI
15944	 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15945			  (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
15946	 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
15947  "TARGET_SHMEDIA"
15948{
15949  return (TARGET_LITTLE_ENDIAN
15950	  ? "mshfhi.w	%N1, %N2, %0"
15951	  : "mshflo.w	%N1, %N2, %0");
15952}
15953  [(set_attr "type" "arith_media")
15954   (set (attr "highpart")
15955	(cond [(eq_attr "endian" "big") (const_string "ignore")]
15956	 (const_string "user")))])
15957
15958(define_insn "mshf0_w"
15959  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15960	(vec_select:V4HI
15961	 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15962			  (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
15963	 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
15964  "TARGET_SHMEDIA"
15965{
15966  return (TARGET_LITTLE_ENDIAN
15967	  ? "mshflo.w	%N1, %N2, %0"
15968	  : "mshfhi.w	%N1, %N2, %0");
15969}
15970  [(set_attr "type" "arith_media")
15971   (set (attr "highpart")
15972	(cond [(eq_attr "endian" "little") (const_string "ignore")]
15973	 (const_string "user")))])
15974
15975(define_insn "mshflo_w_x"
15976  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15977	(vec_select:V4HI
15978	 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
15979			  (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
15980	 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
15981  "TARGET_SHMEDIA"
15982  "mshflo.w	%N1, %N2, %0"
15983  [(set_attr "type" "arith_media")
15984   (set_attr "highpart" "ignore")])
15985
15986;; These are useful to expand ANDs and as combiner patterns.
15987(define_insn_and_split "mshfhi_l_di"
15988  [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
15989	(ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
15990			     (const_int 32))
15991		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
15992			(const_int -4294967296))))]
15993  "TARGET_SHMEDIA"
15994  "@
15995	mshfhi.l	%N1, %N2, %0
15996	#"
15997  "TARGET_SHMEDIA && reload_completed
15998   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
15999  [(set (match_dup 3) (match_dup 4))
16000   (set (match_dup 5) (match_dup 6))]
16001{
16002  operands[3] = gen_lowpart (SImode, operands[0]);
16003  operands[4] = gen_highpart (SImode, operands[1]);
16004  operands[5] = gen_highpart (SImode, operands[0]);
16005  operands[6] = gen_highpart (SImode, operands[2]);
16006}
16007  [(set_attr "type" "arith_media")])
16008
16009(define_insn "*mshfhi_l_di_rev"
16010  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16011	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16012			(const_int -4294967296))
16013		(lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16014			     (const_int 32))))]
16015  "TARGET_SHMEDIA"
16016  "mshfhi.l	%N2, %N1, %0"
16017  [(set_attr "type" "arith_media")])
16018
16019(define_split
16020  [(set (match_operand:DI 0 "arith_reg_dest" "")
16021	(ior:DI (zero_extend:DI (match_operand:SI 1
16022					      "extend_reg_or_0_operand" ""))
16023		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
16024			(const_int -4294967296))))
16025   (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
16026  "TARGET_SHMEDIA"
16027  [(const_int 0)]
16028{
16029  emit_insn (gen_ashldi3_media (operands[3],
16030				simplify_gen_subreg (DImode, operands[1],
16031						     SImode, 0),
16032				GEN_INT (32)));
16033  emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
16034  DONE;
16035})
16036
16037(define_insn "mshflo_l_di"
16038  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16039	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16040			(const_int 4294967295))
16041		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16042			   (const_int 32))))]
16043
16044  "TARGET_SHMEDIA"
16045  "mshflo.l	%N1, %N2, %0"
16046  [(set_attr "type" "arith_media")
16047   (set_attr "highpart" "ignore")])
16048
16049(define_insn "*mshflo_l_di_rev"
16050  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16051	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16052			   (const_int 32))
16053		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16054			(const_int 4294967295))))]
16055
16056  "TARGET_SHMEDIA"
16057  "mshflo.l	%N2, %N1, %0"
16058  [(set_attr "type" "arith_media")
16059   (set_attr "highpart" "ignore")])
16060
16061;; Combiner pattern for trampoline initialization.
16062(define_insn_and_split "*double_shori"
16063  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16064	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
16065			   (const_int 32))
16066		(match_operand:DI 2 "const_int_operand" "n")))]
16067  "TARGET_SHMEDIA
16068   && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
16069  "#"
16070  "rtx_equal_p (operands[0], operands[1])"
16071  [(const_int 0)]
16072{
16073  HOST_WIDE_INT v = INTVAL (operands[2]);
16074
16075  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
16076  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
16077  DONE;
16078}
16079  [(set_attr "highpart" "ignore")])
16080
16081(define_insn "*mshflo_l_di_x"
16082  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16083	(ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
16084				 "rZ"))
16085		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16086			   (const_int 32))))]
16087  "TARGET_SHMEDIA"
16088  "mshflo.l	%N1, %N2, %0"
16089  [(set_attr "type" "arith_media")
16090   (set_attr "highpart" "ignore")])
16091
16092(define_insn_and_split "concat_v2sf"
16093  [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
16094;;	(vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
16095	(vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
16096			 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
16097  "TARGET_SHMEDIA"
16098  "@
16099	mshflo.l	%N1, %N2, %0
16100	#
16101	#"
16102  "TARGET_SHMEDIA && reload_completed
16103   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
16104  [(set (match_dup 3) (match_dup 1))
16105   (set (match_dup 4) (match_dup 2))]
16106{
16107  operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
16108  operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
16109}
16110  [(set_attr "type" "arith_media")
16111   (set_attr "highpart" "ignore")])
16112
16113(define_insn "*mshflo_l_di_x_rev"
16114  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16115	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16116			   (const_int 32))
16117		(zero_extend:DI
16118		  (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
16119  "TARGET_SHMEDIA"
16120  "mshflo.l	%N2, %N1, %0"
16121  [(set_attr "type" "arith_media")
16122   (set_attr "highpart" "ignore")])
16123
16124(define_insn "ashlv2si3"
16125  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16126	(ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
16127		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16128  "TARGET_SHMEDIA"
16129  "mshlld.l	%1, %2, %0"
16130  [(set_attr "type" "arith_media")
16131   (set_attr "highpart" "depend")])
16132
16133(define_split
16134  [(set (match_operand 0 "any_register_operand" "")
16135	(match_operator 3 "shift_operator"
16136	  [(match_operand 1 "any_register_operand" "")
16137	   (match_operand 2 "shift_count_reg_operand" "")]))]
16138  "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
16139  [(set (match_dup 0) (match_dup 3))]
16140{
16141  rtx count = operands[2];
16142  machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
16143
16144  while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
16145	 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
16146	 || GET_CODE (count) == TRUNCATE)
16147    count = XEXP (count, 0);
16148  inner_mode = GET_MODE (count);
16149  count = simplify_gen_subreg (outer_mode, count, inner_mode,
16150			       subreg_lowpart_offset (outer_mode, inner_mode));
16151  operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
16152				operands[1], count);
16153})
16154
16155(define_insn "ashlv4hi3"
16156  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16157	(ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
16158		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16159  "TARGET_SHMEDIA"
16160  "mshlld.w	%1, %2, %0"
16161  [(set_attr "type" "arith_media")
16162   (set_attr "highpart" "depend")])
16163
16164(define_insn "lshrv2si3"
16165  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16166	(lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
16167		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16168  "TARGET_SHMEDIA"
16169  "mshlrd.l	%1, %2, %0"
16170  [(set_attr "type" "arith_media")
16171   (set_attr "highpart" "depend")])
16172
16173(define_insn "lshrv4hi3"
16174  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16175	(lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
16176		       (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16177  "TARGET_SHMEDIA"
16178  "mshlrd.w	%1, %2, %0"
16179  [(set_attr "type" "arith_media")
16180   (set_attr "highpart" "depend")])
16181
16182(define_insn "subv2si3"
16183  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16184	(minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16185		    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
16186  "TARGET_SHMEDIA"
16187  "msub.l	%N1, %2, %0"
16188  [(set_attr "type" "arith_media")
16189   (set_attr "highpart" "depend")])
16190
16191(define_insn "subv4hi3"
16192  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16193	(minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16194		    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
16195  "TARGET_SHMEDIA"
16196  "msub.w	%N1, %2, %0"
16197  [(set_attr "type" "arith_media")
16198   (set_attr "highpart" "depend")])
16199
16200(define_insn_and_split "subv2hi3"
16201  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
16202	(minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
16203		   (match_operand:V2HI 2 "arith_reg_operand" "r")))]
16204  "TARGET_SHMEDIA"
16205  "#"
16206  "TARGET_SHMEDIA"
16207  [(const_int 0)]
16208{
16209  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
16210  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
16211  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
16212  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
16213  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
16214
16215  emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
16216  emit_insn (gen_truncdisi2 (si_dst, di_dst));
16217  DONE;
16218}
16219  [(set_attr "highpart" "must_split")])
16220
16221(define_insn "sssubv2si3"
16222  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16223	(ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16224		       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
16225  "TARGET_SHMEDIA"
16226  "msubs.l	%N1, %2, %0"
16227  [(set_attr "type" "mcmp_media")
16228   (set_attr "highpart" "depend")])
16229
16230(define_insn "ussubv8qi3"
16231  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
16232	(us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
16233		       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
16234  "TARGET_SHMEDIA"
16235  "msubs.ub	%N1, %2, %0"
16236  [(set_attr "type" "mcmp_media")
16237   (set_attr "highpart" "depend")])
16238
16239(define_insn "sssubv4hi3"
16240  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16241	(ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16242		       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
16243  "TARGET_SHMEDIA"
16244  "msubs.w	%N1, %2, %0"
16245  [(set_attr "type" "mcmp_media")
16246   (set_attr "highpart" "depend")])
16247
16248;; -------------------------------------------------------------------------
16249;; Floating Point Intrinsics
16250;; -------------------------------------------------------------------------
16251
16252(define_insn "fcosa_s"
16253  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16254	(unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
16255		   UNSPEC_FCOSA))]
16256  "TARGET_SHMEDIA"
16257  "fcosa.s	%1, %0"
16258  [(set_attr "type" "atrans_media")])
16259
16260(define_insn "fsina_s"
16261  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16262	(unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
16263		   UNSPEC_FSINA))]
16264  "TARGET_SHMEDIA"
16265  "fsina.s	%1, %0"
16266  [(set_attr "type" "atrans_media")])
16267
16268(define_insn "fipr"
16269  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16270	(plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
16271						    "fp_arith_reg_operand" "f")
16272						   (match_operand:V4SF 2
16273						    "fp_arith_reg_operand" "f"))
16274					 (parallel [(const_int 0)]))
16275			  (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
16276					 (parallel [(const_int 1)])))
16277		 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
16278					 (parallel [(const_int 2)]))
16279			  (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
16280					 (parallel [(const_int 3)])))))]
16281  "TARGET_SHMEDIA"
16282  "fipr.s	%1, %2, %0"
16283  [(set_attr "type" "fparith_media")])
16284
16285(define_insn "fsrra_s"
16286  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16287	(unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
16288		   UNSPEC_FSRRA))]
16289  "TARGET_SHMEDIA"
16290  "fsrra.s	%1, %0"
16291  [(set_attr "type" "atrans_media")])
16292
16293(define_insn "ftrv"
16294  [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
16295	(plus:V4SF
16296	 (plus:V4SF
16297	  (mult:V4SF
16298	   (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
16299			    (parallel [(const_int 0) (const_int 5)
16300				       (const_int 10) (const_int 15)]))
16301	   (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
16302	  (mult:V4SF
16303	   (vec_select:V4SF (match_dup 1)
16304			    (parallel [(const_int 4) (const_int 9)
16305				       (const_int 14) (const_int 3)]))
16306	   (vec_select:V4SF (match_dup 2)
16307			    (parallel [(const_int 1) (const_int 2)
16308				       (const_int 3) (const_int 0)]))))
16309	 (plus:V4SF
16310	  (mult:V4SF
16311	   (vec_select:V4SF (match_dup 1)
16312			    (parallel [(const_int 8) (const_int 13)
16313				       (const_int 2) (const_int 7)]))
16314	   (vec_select:V4SF (match_dup 2)
16315			    (parallel [(const_int 2) (const_int 3)
16316				       (const_int 0) (const_int 1)])))
16317	  (mult:V4SF
16318	   (vec_select:V4SF (match_dup 1)
16319			    (parallel [(const_int 12) (const_int 1)
16320				       (const_int 6) (const_int 11)]))
16321	   (vec_select:V4SF (match_dup 2)
16322			    (parallel [(const_int 3) (const_int 0)
16323				       (const_int 1) (const_int 2)]))))))]
16324  "TARGET_SHMEDIA"
16325  "ftrv.s %1, %2, %0"
16326  [(set_attr "type" "fparith_media")])
16327
16328(define_insn "ldhi_l"
16329  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16330	(zero_extract:SI
16331	 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
16332				  (const_int 3))
16333			  (const_int -3)))
16334	 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
16335	 (const_int 0)))]
16336  "TARGET_SHMEDIA32"
16337  "ldhi.l	%U1, %0"
16338  [(set_attr "type" "load_media")])
16339
16340(define_insn "ldhi_q"
16341  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16342	(zero_extract:DI
16343	 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
16344				  (const_int 7))
16345			  (const_int -7)))
16346	 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
16347	 (const_int 0)))]
16348  "TARGET_SHMEDIA32"
16349  "ldhi.q	%U1, %0"
16350  [(set_attr "type" "load_media")])
16351
16352(define_insn_and_split "*ldhi_q_comb0"
16353  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16354	(zero_extract:DI
16355	 (mem:DI (plus:SI (ior:SI (plus:SI
16356				    (match_operand:SI 1 "register_operand" "r")
16357				    (match_operand:SI 2 "ua_offset" "I06"))
16358				  (const_int 7))
16359			  (const_int -7)))
16360	 (plus:SI (and:SI (match_dup 1) (const_int 7))
16361		  (const_int 1))
16362	 (const_int 0)))]
16363  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
16364  "#"
16365  ""
16366  [(pc)]
16367{
16368  emit_insn (gen_ldhi_q (operands[0],
16369			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16370  DONE;
16371})
16372
16373(define_insn_and_split "*ldhi_q_comb1"
16374  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16375	(zero_extract:DI
16376	 (mem:DI (plus:SI (ior:SI (plus:SI
16377				    (match_operand:SI 1 "register_operand" "r")
16378				    (match_operand:SI 2 "ua_offset" "I06"))
16379				  (const_int 7))
16380			  (const_int -7)))
16381	 (plus:SI (and:SI (plus:SI (match_dup 1)
16382				   (match_operand:SI 3 "ua_offset" "I06"))
16383			  (const_int 7))
16384		  (const_int 1))
16385	 (const_int 0)))]
16386  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
16387   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
16388  "#"
16389  ""
16390  [(pc)]
16391{
16392  emit_insn (gen_ldhi_q (operands[0],
16393			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16394  DONE;
16395})
16396
16397(define_insn "ldlo_l"
16398  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16399	(zero_extract:SI
16400	 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
16401			 (const_int -4)))
16402	 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
16403	 (and:SI (match_dup 1) (const_int 3))))]
16404  "TARGET_SHMEDIA32"
16405  "ldlo.l	%U1, %0"
16406  [(set_attr "type" "load_media")])
16407
16408(define_insn "ldlo_q"
16409  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16410	(zero_extract:DI
16411	 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
16412			 (const_int -8)))
16413	 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
16414	 (and:SI (match_dup 1) (const_int 7))))]
16415  "TARGET_SHMEDIA32"
16416  "ldlo.q	%U1, %0"
16417  [(set_attr "type" "load_media")])
16418
16419(define_insn_and_split "*ldlo_q_comb0"
16420  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16421	(zero_extract:DI
16422	 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
16423				  (match_operand:SI 2 "ua_offset" "I06"))
16424			 (const_int -8)))
16425	 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
16426	 (and:SI (match_dup 1) (const_int 7))))]
16427  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
16428  "#"
16429  ""
16430  [(pc)]
16431{
16432  emit_insn (gen_ldlo_q (operands[0],
16433			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16434  DONE;
16435})
16436
16437(define_insn_and_split "*ldlo_q_comb1"
16438  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16439	(zero_extract:DI
16440	 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
16441				  (match_operand:SI 2 "ua_offset" "I06"))
16442			 (const_int -8)))
16443	 (minus:SI (const_int 8)
16444		   (and:SI (plus:SI (match_dup 1)
16445				    (match_operand:SI 3 "ua_offset" "I06"))
16446			   (const_int 7)))
16447	 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
16448  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
16449   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
16450  "#"
16451  ""
16452  [(pc)]
16453{
16454  emit_insn (gen_ldlo_q (operands[0],
16455			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16456  DONE;
16457})
16458
16459(define_insn "sthi_l"
16460  [(set (zero_extract:SI
16461	 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
16462				  (const_int 3))
16463			  (const_int -3)))
16464	 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
16465	 (const_int 0))
16466	(match_operand:SI 1 "arith_reg_operand" "r"))]
16467  "TARGET_SHMEDIA32"
16468  "sthi.l	%U0, %1"
16469  [(set_attr "type" "ustore_media")])
16470
16471;; All unaligned stores are considered to be 'narrow' because they typically
16472;; operate on less that a quadword, and when they operate on a full quadword,
16473;; the vanilla store high / store low sequence will cause a stall if not
16474;; scheduled apart.
16475(define_insn "sthi_q"
16476  [(set (zero_extract:DI
16477	 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
16478				  (const_int 7))
16479			  (const_int -7)))
16480	 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
16481	 (const_int 0))
16482	(match_operand:DI 1 "arith_reg_operand" "r"))]
16483  "TARGET_SHMEDIA32"
16484  "sthi.q	%U0, %1"
16485  [(set_attr "type" "ustore_media")])
16486
16487(define_insn_and_split "*sthi_q_comb0"
16488  [(set (zero_extract:DI
16489	 (mem:DI (plus:SI (ior:SI (plus:SI
16490				    (match_operand:SI 0 "register_operand" "r")
16491				    (match_operand:SI 1 "ua_offset" "I06"))
16492				  (const_int 7))
16493			  (const_int -7)))
16494	 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
16495	 (const_int 0))
16496	(match_operand:DI 2 "arith_reg_operand" "r"))]
16497  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
16498  "#"
16499  ""
16500  [(pc)]
16501{
16502  emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16503			 operands[2]));
16504  DONE;
16505})
16506
16507(define_insn_and_split "*sthi_q_comb1"
16508  [(set (zero_extract:DI
16509	 (mem:DI (plus:SI (ior:SI (plus:SI
16510				    (match_operand:SI 0 "register_operand" "r")
16511				    (match_operand:SI 1 "ua_offset" "I06"))
16512				  (const_int 7))
16513			  (const_int -7)))
16514	 (plus:SI (and:SI (plus:SI (match_dup 0)
16515				   (match_operand:SI 2 "ua_offset" "I06"))
16516			  (const_int 7))
16517		  (const_int 1))
16518	 (const_int 0))
16519	(match_operand:DI 3 "arith_reg_operand" "r"))]
16520  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
16521   && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
16522  "#"
16523  ""
16524  [(pc)]
16525{
16526  emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16527			 operands[3]));
16528  DONE;
16529})
16530
16531;; This is highpart user because the address is used as full 64 bit.
16532(define_insn "stlo_l"
16533  [(set (zero_extract:SI
16534	 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
16535			 (const_int -4)))
16536	 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
16537	 (and:SI (match_dup 0) (const_int 3)))
16538	(match_operand:SI 1 "arith_reg_operand" "r"))]
16539  "TARGET_SHMEDIA32"
16540  "stlo.l	%U0, %1"
16541  [(set_attr "type" "ustore_media")])
16542
16543(define_insn "stlo_q"
16544  [(set (zero_extract:DI
16545	 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
16546			 (const_int -8)))
16547	 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
16548	 (and:SI (match_dup 0) (const_int 7)))
16549	(match_operand:DI 1 "arith_reg_operand" "r"))]
16550  "TARGET_SHMEDIA32"
16551  "stlo.q	%U0, %1"
16552  [(set_attr "type" "ustore_media")])
16553
16554(define_insn_and_split "*stlo_q_comb0"
16555  [(set (zero_extract:DI
16556	 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
16557				  (match_operand:SI 1 "ua_offset" "I06"))
16558			 (const_int -8)))
16559	 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
16560	 (and:SI (match_dup 0) (const_int 7)))
16561	(match_operand:DI 2 "arith_reg_operand" "r"))]
16562  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
16563  "#"
16564  ""
16565  [(pc)]
16566{
16567  emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16568			 operands[2]));
16569  DONE;
16570})
16571
16572(define_insn_and_split "*stlo_q_comb1"
16573  [(set (zero_extract:DI
16574	 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
16575				  (match_operand:SI 1 "ua_offset" "I06"))
16576			 (const_int -8)))
16577	 (minus:SI (const_int 8)
16578		   (and:SI (plus:SI (match_dup 0)
16579				    (match_operand:SI 2 "ua_offset" "I06"))
16580			   (const_int 7)))
16581	 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
16582	(match_operand:DI 3 "arith_reg_operand" "r"))]
16583  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
16584  "#"
16585  ""
16586  [(pc)]
16587{
16588  emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16589			 operands[3]));
16590   DONE;
16591})
16592
16593(define_insn "ldhi_l64"
16594  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16595	(zero_extract:SI
16596	 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
16597				  (const_int 3))
16598			  (const_int -3)))
16599	 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
16600	 (const_int 0)))]
16601  "TARGET_SHMEDIA64"
16602  "ldhi.l	%U1, %0"
16603  [(set_attr "type" "load_media")])
16604
16605(define_insn "ldhi_q64"
16606  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16607	(zero_extract:DI
16608	 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
16609				  (const_int 7))
16610			  (const_int -7)))
16611	 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
16612	 (const_int 0)))]
16613  "TARGET_SHMEDIA64"
16614  "ldhi.q	%U1, %0"
16615  [(set_attr "type" "load_media")])
16616
16617(define_insn "ldlo_l64"
16618  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16619	(zero_extract:SI
16620	 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
16621			 (const_int -4)))
16622	 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
16623	 (and:DI (match_dup 1) (const_int 3))))]
16624  "TARGET_SHMEDIA64"
16625  "ldlo.l	%U1, %0"
16626  [(set_attr "type" "load_media")])
16627
16628(define_insn "ldlo_q64"
16629  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16630	(zero_extract:DI
16631	 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
16632			 (const_int -8)))
16633	 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
16634	 (and:DI (match_dup 1) (const_int 7))))]
16635  "TARGET_SHMEDIA64"
16636  "ldlo.q	%U1, %0"
16637  [(set_attr "type" "load_media")])
16638
16639(define_insn "sthi_l64"
16640  [(set (zero_extract:SI
16641	 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
16642				  (const_int 3))
16643			  (const_int -3)))
16644	 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
16645	 (const_int 0))
16646	(match_operand:SI 1 "arith_reg_operand" "r"))]
16647  "TARGET_SHMEDIA64"
16648  "sthi.l	%U0, %1"
16649  [(set_attr "type" "ustore_media")])
16650
16651(define_insn "sthi_q64"
16652  [(set (zero_extract:DI
16653	 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
16654				  (const_int 7))
16655			  (const_int -7)))
16656	 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
16657	 (const_int 0))
16658	(match_operand:DI 1 "arith_reg_operand" "r"))]
16659  "TARGET_SHMEDIA64"
16660  "sthi.q	%U0, %1"
16661  [(set_attr "type" "ustore_media")])
16662
16663(define_insn "stlo_l64"
16664  [(set (zero_extract:SI
16665	 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
16666			 (const_int -4)))
16667	 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
16668	 (and:DI (match_dup 0) (const_int 3)))
16669	(match_operand:SI 1 "arith_reg_operand" "r"))]
16670  "TARGET_SHMEDIA64"
16671  "stlo.l	%U0, %1"
16672  [(set_attr "type" "ustore_media")])
16673
16674(define_insn "stlo_q64"
16675  [(set (zero_extract:DI
16676	 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
16677			 (const_int -8)))
16678	 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
16679	 (and:DI (match_dup 0) (const_int 7)))
16680	(match_operand:DI 1 "arith_reg_operand" "r"))]
16681  "TARGET_SHMEDIA64"
16682  "stlo.q	%U0, %1"
16683  [(set_attr "type" "ustore_media")])
16684
16685(define_insn "nsb"
16686  [(set (match_operand:QI 0 "arith_reg_dest" "=r")
16687	(unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
16688		   UNSPEC_NSB))]
16689  "TARGET_SHMEDIA"
16690  "nsb	%1, %0"
16691  [(set_attr "type" "arith_media")])
16692
16693(define_insn "nsbsi"
16694  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16695	(zero_extend:SI
16696	 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
16697		    UNSPEC_NSB)))]
16698  "TARGET_SHMEDIA"
16699  "nsb	%1, %0"
16700  [(set_attr "type" "arith_media")])
16701
16702(define_insn "nsbdi"
16703  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16704	(zero_extend:DI
16705	 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
16706		    UNSPEC_NSB)))]
16707  "TARGET_SHMEDIA"
16708  "nsb	%1, %0"
16709  [(set_attr "type" "arith_media")])
16710
16711(define_expand "ffsdi2"
16712  [(set (match_operand:DI 0 "arith_reg_dest" "")
16713	(ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
16714  "TARGET_SHMEDIA"
16715{
16716  rtx scratch = gen_reg_rtx (DImode);
16717  rtx last;
16718
16719  emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
16720  emit_insn (gen_xordi3 (scratch, operands[1], scratch));
16721  emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
16722  emit_insn (gen_nsbdi (scratch, scratch));
16723  emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
16724  emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
16725  last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
16726  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
16727
16728  DONE;
16729})
16730
16731(define_expand "ffssi2"
16732  [(set (match_operand:SI 0 "arith_reg_dest" "")
16733	(ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
16734  "TARGET_SHMEDIA"
16735{
16736  rtx scratch = gen_reg_rtx (SImode);
16737  rtx discratch = gen_reg_rtx (DImode);
16738  rtx last;
16739
16740  emit_insn (gen_adddi3 (discratch,
16741			 simplify_gen_subreg (DImode, operands[1], SImode, 0),
16742			 constm1_rtx));
16743  emit_insn (gen_andcdi3 (discratch,
16744			  simplify_gen_subreg (DImode, operands[1], SImode, 0),
16745			  discratch));
16746  emit_insn (gen_nsbsi (scratch, discratch));
16747  last = emit_insn (gen_subsi3 (operands[0],
16748				force_reg (SImode, GEN_INT (63)), scratch));
16749  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
16750
16751  DONE;
16752})
16753
16754(define_insn "byterev"
16755  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
16756	(vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
16757			 (parallel [(const_int 7) (const_int 6) (const_int 5)
16758				    (const_int 4) (const_int 3) (const_int 2)
16759				    (const_int 1) (const_int 0)])))]
16760  "TARGET_SHMEDIA"
16761  "byterev	%1, %0"
16762  [(set_attr "type" "arith_media")])
16763
16764;; In user mode, the "pref" instruction will raise a RADDERR exception
16765;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
16766;; implementation of __builtin_prefetch for VxWorks RTPs.
16767(define_expand "prefetch"
16768  [(prefetch (match_operand 0 "address_operand" "")
16769	     (match_operand:SI 1 "const_int_operand" "")
16770	     (match_operand:SI 2 "const_int_operand" ""))]
16771  "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
16772   && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
16773
16774(define_insn "*prefetch"
16775  [(prefetch (match_operand:SI 0 "register_operand" "r")
16776	     (match_operand:SI 1 "const_int_operand" "n")
16777	     (match_operand:SI 2 "const_int_operand" "n"))]
16778  "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
16779  "pref	@%0"
16780  [(set_attr "type" "other")])
16781
16782(define_insn "*prefetch_media"
16783  [(prefetch (match_operand:QI 0 "address_operand" "p")
16784	     (match_operand:SI 1 "const_int_operand" "n")
16785	     (match_operand:SI 2 "const_int_operand" "n"))]
16786  "TARGET_SHMEDIA"
16787{
16788  operands[0] = gen_rtx_MEM (QImode, operands[0]);
16789  output_asm_insn ("ld%M0.b	%m0,r63", operands);
16790  return "";
16791}
16792  [(set_attr "type" "other")])
16793
16794(define_insn "alloco_i"
16795  [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
16796	(unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
16797  "TARGET_SHMEDIA32"
16798{
16799  rtx xops[2];
16800
16801  if (GET_CODE (operands[0]) == PLUS)
16802    {
16803      xops[0] = XEXP (operands[0], 0);
16804      xops[1] = XEXP (operands[0], 1);
16805    }
16806  else
16807    {
16808      xops[0] = operands[0];
16809      xops[1] = const0_rtx;
16810    }
16811  output_asm_insn ("alloco	%0, %1", xops);
16812  return "";
16813}
16814  [(set_attr "type" "other")])
16815
16816(define_split
16817  [(set (match_operand 0 "any_register_operand" "")
16818	(match_operand 1 "" ""))]
16819  "TARGET_SHMEDIA && reload_completed"
16820  [(set (match_dup 0) (match_dup 1))]
16821{
16822  if (!shmedia_cleanup_truncate (operands[1]))
16823    FAIL;
16824})
16825
16826;; -------------------------------------------------------------------------
16827;; Stack Protector Patterns
16828;; -------------------------------------------------------------------------
16829
16830(define_expand "stack_protect_set"
16831  [(set (match_operand 0 "memory_operand" "")
16832	(match_operand 1 "memory_operand" ""))]
16833  ""
16834{
16835  if (TARGET_SHMEDIA)
16836    {
16837      if (TARGET_SHMEDIA64)
16838	emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
16839      else
16840	emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
16841    }
16842  else
16843    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
16844
16845  DONE;
16846})
16847
16848(define_insn "stack_protect_set_si"
16849  [(set (match_operand:SI 0 "memory_operand" "=m")
16850	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
16851   (set (match_scratch:SI 2 "=&r") (const_int 0))]
16852  "!TARGET_SHMEDIA"
16853{
16854  return       "mov.l	%1,%2"	"\n"
16855	 "	mov.l	%2,%0"	"\n"
16856	 "	mov	#0,%2";
16857}
16858  [(set_attr "type" "other")
16859   (set_attr "length" "6")])
16860
16861(define_insn "stack_protect_set_si_media"
16862  [(set (match_operand:SI 0 "memory_operand" "=m")
16863	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
16864   (set (match_scratch:SI 2 "=&r") (const_int 0))]
16865  "TARGET_SHMEDIA"
16866{
16867  return       "ld%M1.l	%m1,%2"	"\n"
16868	 "	st%M0.l	%m0,%2"	"\n"
16869	 "	movi	0,%2";
16870}
16871  [(set_attr "type" "other")
16872   (set_attr "length" "12")])
16873
16874(define_insn "stack_protect_set_di_media"
16875  [(set (match_operand:DI 0 "memory_operand" "=m")
16876	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
16877   (set (match_scratch:DI 2 "=&r") (const_int 0))]
16878  "TARGET_SHMEDIA64"
16879{
16880  return       "ld%M1.q	%m1,%2"	"\n"
16881	 "	st%M0.q	%m0,%2"	"\n"
16882	 "	movi	0,%2";
16883}
16884  [(set_attr "type" "other")
16885   (set_attr "length" "12")])
16886
16887(define_expand "stack_protect_test"
16888  [(match_operand 0 "memory_operand" "")
16889   (match_operand 1 "memory_operand" "")
16890   (match_operand 2 "" "")]
16891  ""
16892{
16893  if (TARGET_SHMEDIA)
16894    {
16895      rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
16896      rtx test;
16897
16898      test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
16899      if (TARGET_SHMEDIA64)
16900	{
16901	  emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
16902						      operands[1]));
16903	  emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
16904	}
16905      else
16906	{
16907	  emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
16908						      operands[1]));
16909	  emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
16910	}
16911    }
16912  else
16913    {
16914      emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
16915      emit_jump_insn (gen_branch_true (operands[2]));
16916    }
16917
16918  DONE;
16919})
16920
16921(define_insn "stack_protect_test_si"
16922  [(set (reg:SI T_REG)
16923	(unspec:SI [(match_operand:SI 0 "memory_operand" "m")
16924		    (match_operand:SI 1 "memory_operand" "m")]
16925		   UNSPEC_SP_TEST))
16926  (set (match_scratch:SI 2 "=&r") (const_int 0))
16927  (set (match_scratch:SI 3 "=&r") (const_int 0))]
16928  "!TARGET_SHMEDIA"
16929{
16930  return       "mov.l	%0,%2"	"\n"
16931	 "	mov.l	%1,%3"	"\n"
16932	 "	cmp/eq	%2,%3"	"\n"
16933	 "	mov	#0,%2"	"\n"
16934	 "	mov	#0,%3";
16935}
16936  [(set_attr "type" "other")
16937   (set_attr "length" "10")])
16938
16939(define_insn "stack_protect_test_si_media"
16940  [(set (match_operand:SI 0 "register_operand" "=&r")
16941	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")
16942		    (match_operand:SI 2 "memory_operand" "m")]
16943		   UNSPEC_SP_TEST))
16944  (set (match_scratch:SI 3 "=&r") (const_int 0))]
16945  "TARGET_SHMEDIA"
16946{
16947  return       "ld%M1.l	%m1,%0"		"\n"
16948	 "	ld%M2.l	%m2,%3"		"\n"
16949	 "	cmpeq	%0,%3,%0"	"\n"
16950	 "	movi	0,%3";
16951}
16952  [(set_attr "type" "other")
16953   (set_attr "length" "16")])
16954
16955(define_insn "stack_protect_test_di_media"
16956  [(set (match_operand:DI 0 "register_operand" "=&r")
16957	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")
16958		    (match_operand:DI 2 "memory_operand" "m")]
16959		   UNSPEC_SP_TEST))
16960  (set (match_scratch:DI 3 "=&r") (const_int 0))]
16961  "TARGET_SHMEDIA64"
16962{
16963  return       "ld%M1.q	%m1,%0"		"\n"
16964	 "	ld%M2.q	%m2,%3"		"\n"
16965	 "	cmpeq	%0,%3,%0"	"\n"
16966	 "	movi	0,%3";
16967}
16968  [(set_attr "type" "other")
16969   (set_attr "length" "16")])
16970
16971;; -------------------------------------------------------------------------
16972;; Atomic operations
16973;; -------------------------------------------------------------------------
16974
16975(include "sync.md")
16976