sh.md revision 1.6
1;;- Machine description for Renesas / SuperH SH.
2;;  Copyright (C) 1993-2016 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_PCREL
139  UNSPEC_ICACHE
140  UNSPEC_INIT_TRAMP
141  UNSPEC_FCOSA
142  UNSPEC_FSRRA
143  UNSPEC_FSINA
144  UNSPEC_NSB
145  UNSPEC_ALLOCO
146  UNSPEC_TLSGD
147  UNSPEC_TLSLDM
148  UNSPEC_TLSIE
149  UNSPEC_DTPOFF
150  UNSPEC_GOTTPOFF
151  UNSPEC_TPOFF
152  UNSPEC_RA
153  UNSPEC_DIV_INV_M0
154  UNSPEC_DIV_INV_M1
155  UNSPEC_DIV_INV_M2
156  UNSPEC_DIV_INV_M3
157  UNSPEC_DIV_INV20
158  UNSPEC_DIV_INV_TABLE
159  UNSPEC_ASHIFTRT
160  UNSPEC_THUNK
161  UNSPEC_CHKADD
162  UNSPEC_SP_SET
163  UNSPEC_SP_TEST
164  UNSPEC_MOVUA
165  ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
166  ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
167  UNSPEC_EXTRACT_S16
168  UNSPEC_EXTRACT_U16
169  ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
170  UNSPEC_SYMOFF
171  ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
172  UNSPEC_PCREL_SYMOFF
173  ;; For FDPIC
174  UNSPEC_GOTFUNCDESC
175  UNSPEC_GOTOFFFUNCDESC
176  ;; Misc builtins
177  UNSPEC_BUILTIN_STRLEN
178])
179
180(define_c_enum "unspecv" [
181  ;; These are used with unspec_volatile.
182  UNSPECV_BLOCKAGE
183  UNSPECV_ALIGN
184  UNSPECV_CONST2
185  UNSPECV_CONST4
186  UNSPECV_CONST8
187  UNSPECV_WINDOW_END
188  UNSPECV_CONST_END
189  UNSPECV_EH_RETURN
190  UNSPECV_GBR
191  UNSPECV_SP_SWITCH_B
192  UNSPECV_SP_SWITCH_E
193
194  UNSPECV_FPSCR_MODES
195  UNSPECV_FPSCR_STAT
196])
197
198;; -------------------------------------------------------------------------
199;; Attributes
200;; -------------------------------------------------------------------------
201
202;; Target CPU.
203
204(define_attr "cpu"
205 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
206  (const (symbol_ref "sh_cpu_attr")))
207
208(define_attr "endian" "big,little"
209 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
210		      (const_string "little") (const_string "big"))))
211
212;; Indicate if the default fpu mode is single precision.
213(define_attr "fpu_single" "yes,no"
214  (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
215		       (const_string "yes") (const_string "no"))))
216
217(define_attr "fmovd" "yes,no"
218  (const (if_then_else (symbol_ref "TARGET_FMOVD")
219		       (const_string "yes") (const_string "no"))))
220;; pipeline model
221(define_attr "pipe_model" "sh1,sh4,sh5media"
222  (const
223   (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
224          (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
225         (const_string "sh1"))))
226
227;; cbranch	conditional branch instructions
228;; jump		unconditional jumps
229;; arith	ordinary arithmetic
230;; arith3	a compound insn that behaves similarly to a sequence of
231;;		three insns of type arith
232;; arith3b	like above, but might end with a redirected branch
233;; load		from memory
234;; load_si	Likewise, SImode variant for general register.
235;; fload	Likewise, but load to fp register.
236;; store	to memory
237;; fstore	floating point register to memory
238;; move		general purpose register to register
239;; movi8	8-bit immediate to general purpose register
240;; mt_group	other sh4 mt instructions
241;; fmove	register to register, floating point
242;; smpy		word precision integer multiply
243;; dmpy		longword or doublelongword precision integer multiply
244;; return	rts
245;; pload	load of pr reg, which can't be put into delay slot of rts
246;; prset	copy register to pr reg, ditto
247;; pstore	store of pr reg, which can't be put into delay slot of jsr
248;; prget	copy pr to register, ditto
249;; pcload	pc relative load of constant value
250;; pcfload	Likewise, but load to fp register.
251;; pcload_si	Likewise, SImode variant for general register.
252;; rte		return from exception
253;; sfunc	special function call with known used registers
254;; call		function call
255;; fp		floating point
256;; fpscr_toggle	toggle a bit in the fpscr
257;; fdiv		floating point divide (or square root)
258;; gp_fpul	move from general purpose register to fpul
259;; fpul_gp	move from fpul to general purpose register
260;; mac_gp	move from mac[lh] to general purpose register
261;; gp_mac	move from general purpose register to mac[lh]
262;; mac_mem	move from mac[lh] to memory
263;; mem_mac	move from memory to mac[lh]
264;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
265;; ftrc_s	fix_truncsfsi2_i4
266;; dfdiv	double precision floating point divide (or square root)
267;; cwb		ic_invalidate_line_i
268;; movua	SH4a unaligned load
269;; fsrra	square root reciprocal approximate
270;; fsca		sine and cosine approximate
271;; tls_load     load TLS related address
272;; arith_media	SHmedia arithmetic, logical, and shift instructions
273;; cbranch_media SHmedia conditional branch instructions
274;; cmp_media	SHmedia compare instructions
275;; dfdiv_media	SHmedia double precision divide and square root
276;; dfmul_media	SHmedia double precision multiply instruction
277;; dfparith_media SHmedia double precision floating point arithmetic
278;; dfpconv_media SHmedia double precision floating point conversions
279;; dmpy_media	SHmedia longword multiply
280;; fcmp_media	SHmedia floating point compare instructions
281;; fdiv_media	SHmedia single precision divide and square root
282;; fload_media	SHmedia floating point register load instructions
283;; fmove_media	SHmedia floating point register moves (inc. fabs and fneg)
284;; fparith_media SHmedia single precision floating point arithmetic
285;; fpconv_media	SHmedia single precision floating point conversions
286;; fstore_media	SHmedia floating point register store instructions
287;; gettr_media	SHmedia gettr instruction
288;; invalidate_line_media SHmedia invalidate_line sequence
289;; jump_media	SHmedia unconditional branch instructions
290;; load_media	SHmedia general register load instructions
291;; pt_media	SHmedia pt instruction (expanded by assembler)
292;; ptabs_media	SHmedia ptabs instruction
293;; store_media	SHmedia general register store instructions
294;; mcmp_media	SHmedia multimedia compare, absolute, saturating ops
295;; mac_media	SHmedia mac-style fixed point operations
296;; d2mpy_media	SHmedia: two 32-bit integer multiplies
297;; atrans_media	SHmedia approximate transcendental functions
298;; ustore_media	SHmedia unaligned stores
299;; nil		no-op move, will be deleted.
300
301(define_attr "type"
302 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,
303  fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,
304  prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,
305  dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,
306  gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,
307  arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,
308  dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,
309  fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,
310  jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,
311  d2mpy_media,atrans_media,ustore_media,nil,other"
312  (const_string "other"))
313
314;; We define a new attribute namely "insn_class".We use
315;; this for the DFA based pipeline description.
316;;
317;; mt_group      SH4 "mt" group instructions.
318;;
319;; ex_group      SH4 "ex" group instructions.
320;;
321;; ls_group      SH4 "ls" group instructions.
322;;
323(define_attr "insn_class"
324  "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
325  (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
326	 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
327	 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,
328			  store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
329	 (eq_attr "type" "cbranch,jump") (const_string "br_group")
330	 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
331	   (const_string "fe_group")
332	 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,
333			  prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,
334			  gp_mac,mac_mem,mem_mac") (const_string "co_group")]
335	(const_string "none")))
336
337;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
338;; so these do not belong in an insn group, although they are modeled
339;; with their own define_insn_reservations.
340
341;; Indicate what precision must be selected in fpscr for this insn, if any.
342(define_attr "fp_mode" "single,double,none" (const_string "none"))
343
344;; Indicate if the fpu mode is set by this instruction
345;; "unknown" must have the value as "none" in fp_mode, and means
346;; that the instruction/abi has left the processor in an unknown
347;; state.
348;; "none" means that nothing has changed and no mode is set.
349;; This attribute is only used for the Renesas ABI.
350(define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
351
352; If a conditional branch destination is within -252..258 bytes away
353; from the instruction it can be 2 bytes long.  Something in the
354; range -4090..4100 bytes can be 6 bytes long.  All other conditional
355; branches are initially assumed to be 16 bytes long.
356; In machine_dependent_reorg, we split all branches that are longer than
357; 2 bytes.
358
359;; The maximum range used for SImode constant pool entries is 1018.  A final
360;; instruction can add 8 bytes while only being 4 bytes in size, thus we
361;; can have a total of 1022 bytes in the pool.  Add 4 bytes for a branch
362;; instruction around the pool table, 2 bytes of alignment before the table,
363;; and 30 bytes of alignment after the table.  That gives a maximum total
364;; pool size of 1058 bytes.
365;; Worst case code/pool content size ratio is 1:2 (using asms).
366;; Thus, in the worst case, there is one instruction in front of a maximum
367;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
368;; code.  For the last n bytes of code, there are 2n + 36 bytes of pool.
369;; If we have a forward branch, the initial table will be put after the
370;; unconditional branch.
371;;
372;; ??? We could do much better by keeping track of the actual pcloads within
373;; the branch range and in the pcload range in front of the branch range.
374
375;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
376;; inside an le.
377(define_attr "short_cbranch_p" "no,yes"
378  (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
379	 (const_string "no")
380	 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
381	 (const_string "yes")
382	 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
383	 (const_string "no")
384	 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
385	 (const_string "yes")
386	 ] (const_string "no")))
387
388(define_attr "med_branch_p" "no,yes"
389  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
390	      (const_int 1988))
391	 (const_string "yes")
392	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
393	 (const_string "no")
394	 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
395	      (const_int 8186))
396	 (const_string "yes")
397	 ] (const_string "no")))
398
399(define_attr "med_cbranch_p" "no,yes"
400  (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
401	      (const_int 1986))
402	 (const_string "yes")
403	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
404	 (const_string "no")
405	 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
406	       (const_int 8184))
407	 (const_string "yes")
408	 ] (const_string "no")))
409
410(define_attr "braf_branch_p" "no,yes"
411  (cond [(match_test "! TARGET_SH2")
412	 (const_string "no")
413	 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
414	      (const_int 20660))
415	 (const_string "yes")
416	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
417	 (const_string "no")
418	 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
419	      (const_int 65530))
420	 (const_string "yes")
421	 ] (const_string "no")))
422
423(define_attr "braf_cbranch_p" "no,yes"
424  (cond [(match_test "! TARGET_SH2")
425	 (const_string "no")
426	 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
427	      (const_int 20658))
428	 (const_string "yes")
429	 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
430	 (const_string "no")
431	 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
432	      (const_int 65528))
433	 (const_string "yes")
434	 ] (const_string "no")))
435
436;; An unconditional jump in the range -4092..4098 can be 2 bytes long.
437;; For wider ranges, we need a combination of a code and a data part.
438;; If we can get a scratch register for a long range jump, the code
439;; part can be 4 bytes long; otherwise, it must be 8 bytes long.
440;; If the jump is in the range -32764..32770, the data part can be 2 bytes
441;; long; otherwise, it must be 6 bytes long.
442
443;; All other instructions are two bytes long by default.
444
445;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
446;; but getattrtab doesn't understand this.
447(define_attr "length" ""
448  (cond [(eq_attr "type" "cbranch")
449	 (cond [(eq_attr "short_cbranch_p" "yes")
450		(const_int 2)
451		(eq_attr "med_cbranch_p" "yes")
452		(const_int 6)
453		(eq_attr "braf_cbranch_p" "yes")
454		(const_int 12)
455;; ??? using pc is not computed transitively.
456		(ne (match_dup 0) (match_dup 0))
457		(const_int 14)
458		(match_test "flag_pic")
459		(const_int 24)
460		] (const_int 16))
461	 (eq_attr "type" "jump")
462	 (cond [(eq_attr "med_branch_p" "yes")
463		(const_int 2)
464		(and (match_test "prev_nonnote_insn (insn)")
465		     (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
466			      (symbol_ref "INSN"))
467			  (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
468			      (symbol_ref "code_for_indirect_jump_scratch"))))
469		(cond [(eq_attr "braf_branch_p" "yes")
470		       (const_int 6)
471		       (not (match_test "flag_pic"))
472		       (const_int 10)
473		       (match_test "TARGET_SH2")
474		       (const_int 10)] (const_int 18))
475		(eq_attr "braf_branch_p" "yes")
476		(const_int 10)
477;; ??? using pc is not computed transitively.
478		(ne (match_dup 0) (match_dup 0))
479		(const_int 12)
480		(match_test "flag_pic")
481		(const_int 22)
482		] (const_int 14))
483	 (eq_attr "type" "pt_media")
484	 (if_then_else (match_test "TARGET_SHMEDIA64")
485		       (const_int 20) (const_int 12))
486	 (and (eq_attr "type" "jump_media")
487	      (match_test "TARGET_SH5_CUT2_WORKAROUND"))
488	 (const_int 8)
489	 ] (if_then_else (match_test "TARGET_SHMEDIA")
490			 (const_int 4)
491			 (const_int 2))))
492
493;; DFA descriptions for the pipelines
494
495(include "sh1.md")
496(include "shmedia.md")
497(include "sh4.md")
498
499(include "iterators.md")
500(include "predicates.md")
501(include "constraints.md")
502
503;; Definitions for filling delay slots
504
505(define_attr "needs_delay_slot" "yes,no" (const_string "no"))
506
507(define_attr "banked" "yes,no" 
508	(cond [(match_test "sh_loads_bankedreg_p (insn)")
509	       (const_string "yes")]
510	      (const_string "no")))
511
512;; ??? This should be (nil) instead of (const_int 0)
513(define_attr "hit_stack" "yes,no"
514	(cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
515	       (const_string "no")]
516	      (const_string "yes")))
517
518(define_attr "interrupt_function" "no,yes"
519  (const (symbol_ref "current_function_interrupt")))
520
521(define_attr "in_delay_slot" "yes,no"
522  (cond [(eq_attr "type" "cbranch") (const_string "no")
523	 (eq_attr "type" "pcload,pcload_si") (const_string "no")
524	 (eq_attr "type" "fpscr_toggle") (const_string "no")
525	 (eq_attr "needs_delay_slot" "yes") (const_string "no")
526	 (eq_attr "length" "2") (const_string "yes")
527	 ] (const_string "no")))
528
529(define_attr "cond_delay_slot" "yes,no"
530  (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
531	 ] (const_string "no")))
532
533(define_attr "is_sfunc" ""
534  (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
535
536(define_attr "is_mac_media" ""
537  (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
538
539(define_attr "branch_zero" "yes,no"
540  (cond [(eq_attr "type" "!cbranch") (const_string "no")
541	 (ne (symbol_ref "(next_active_insn (insn)\
542			   == (prev_active_insn\
543			       (XEXP (SET_SRC (PATTERN (insn)), 1))))\
544			  && get_attr_length (next_active_insn (insn)) == 2")
545	     (const_int 0))
546	 (const_string "yes")]
547	(const_string "no")))
548
549;; SH4 Double-precision computation with double-precision result -
550;; the two halves are ready at different times.
551(define_attr "dfp_comp" "yes,no"
552  (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
553	(const_string "no")))
554
555;; Insns for which the latency of a preceding fp insn is decreased by one.
556(define_attr "late_fp_use" "yes,no" (const_string "no"))
557;; And feeding insns for which this relevant.
558(define_attr "any_fp_comp" "yes,no"
559  (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
560	 (const_string "yes")]
561	(const_string "no")))
562
563(define_attr "any_int_load" "yes,no"
564  (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
565	 (const_string "yes")]
566	(const_string "no")))
567
568(define_attr "highpart" "user, ignore, extend, depend, must_split"
569  (const_string "user"))
570
571(define_delay
572  (eq_attr "needs_delay_slot" "yes")
573  [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
574
575;; Since a normal return (rts) implicitly uses the PR register,
576;; we can't allow PR register loads in an rts delay slot.
577;; On the SH1* and SH2*, the rte instruction reads the return pc from the
578;; stack, and thus we can't put a pop instruction in its delay slot.
579;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
580;; pop instruction can go in the delay slot, unless it references a banked
581;; register (the register bank is switched by rte).
582(define_delay
583  (eq_attr "type" "return")
584  [(and (eq_attr "in_delay_slot" "yes")
585	(ior (and (eq_attr "interrupt_function" "no")
586		  (eq_attr "type" "!pload,prset"))
587	     (and (eq_attr "interrupt_function" "yes")
588		  (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
589		  (eq_attr "banked" "no"))))
590   (nil) (nil)])
591
592;; Since a call implicitly uses the PR register, we can't allow
593;; a PR register store in a jsr delay slot.
594
595(define_delay
596  (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
597  [(and (eq_attr "in_delay_slot" "yes")
598	(eq_attr "type" "!pstore,prget")) (nil) (nil)])
599
600;; Conditional branches with delay slots are available starting with SH2.
601(define_delay
602  (and (eq_attr "type" "cbranch") (match_test "TARGET_SH2"))
603  [(eq_attr "cond_delay_slot" "yes") (nil) (nil)])
604
605;; -------------------------------------------------------------------------
606;; SImode signed integer comparisons
607;; -------------------------------------------------------------------------
608
609;; Patterns to generate the tst instruction which are usually formed by
610;; the combine pass.
611;; The canonical form here being used is (eq (and (op) (op)) 0).
612;; For some bit patterns, such as contiguous bits, we also must accept
613;; zero_extract forms.  Single bit tests are also handled via zero_extract
614;; patterns in the 'bit field extract patterns' section.  All variants
615;; are eventually converted to the 'tstsi_t' insn.
616;; As long as pseudos can be created (before RA), 'tstsi_t' will also accept
617;; constants that won't fit into 8 bits.  After having captured the constant
618;; we can decide better whether/how to load it into a register and do other
619;; post-combine optimizations such as bypassing sign/zero extensions.
620(define_insn_and_split "tstsi_t"
621  [(set (reg:SI T_REG)
622	(eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "%z,r")
623		       (match_operand:SI 1 "arith_or_int_operand" "K08,?r"))
624	       (const_int 0)))]
625  "TARGET_SH1
626   && (can_create_pseudo_p () || arith_reg_operand (operands[1], SImode)
627       || satisfies_constraint_K08 (operands[1]))"
628  "tst	%1,%0"
629  "TARGET_SH1 && can_create_pseudo_p () && CONST_INT_P (operands[1])
630   && !sh_in_recog_treg_set_expr ()"
631  [(const_int 0)]
632{
633  gcc_assert (CONST_INT_P (operands[1]));
634
635  HOST_WIDE_INT op1val = INTVAL (operands[1]);
636  bool op0_dead_after_this =
637	sh_reg_dead_or_unused_after_insn (curr_insn, REGNO (operands[0]));
638
639  if (optimize)
640    {
641      if (dump_file)
642	fprintf (dump_file,
643		 "tstsi_t: trying to optimize const_int 0x%08x\n",
644		 (uint32_t)op1val);
645
646      /* See if we can convert a test with a reg and a constant into
647	 something simpler, if the reg is known to be zero or sign
648	 extended.  */
649      sh_extending_set_of_reg eop0 = sh_find_extending_set_of_reg (operands[0],
650								   curr_insn);
651      if (eop0.ext_code != UNKNOWN)
652	{
653	  /* Adjust the constant, trying to eliminate bits that are not
654	     contributing to the result.  */
655	  if (eop0.from_mode == QImode)
656	    op1val = (op1val
657                      | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFFFF80)
658			 ? 0x80 : 0)) & 0xFF;
659	  else if (eop0.from_mode == HImode)
660	    op1val = (op1val
661		      | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFF8000)
662			 ? 0x8000 : 0)) & 0xFFFF;
663
664	  if (dump_file)
665	    fprintf (dump_file, "tstsi_t: using effective const_int: 0x%08x\n",
666		     (uint32_t)op1val);
667
668	  /* Try to bypass the sign/zero extension first if op0 dies after
669	     this insn.  */
670	  if (op0_dead_after_this && eop0.can_use_as_unextended_reg ())
671	    {
672	      if (dump_file)
673		fprintf (dump_file, "tstsi_t: bypassing sign/zero extension\n");
674
675	      operands[0] = eop0.use_as_unextended_reg (curr_insn);
676	    }
677	  else if ((eop0.from_mode == QImode && op1val == 0xFF)
678		   || (eop0.from_mode == HImode && op1val == 0xFFFF))
679	    {
680	      if (dump_file)
681		fprintf (dump_file, "tstsi_t: converting to cmpeqsi_t\n");
682	      emit_insn (gen_cmpeqsi_t (eop0.use_as_extended_reg (curr_insn),
683					const0_rtx));
684	      DONE;
685	    }
686	  else if (eop0.ext_code == SIGN_EXTEND
687		   && ((eop0.from_mode == QImode && op1val == 0x80)
688		       || (eop0.from_mode == HImode && op1val == 0x8000)))
689	    {
690	      if (dump_file)
691		fprintf (dump_file, "tstsi_t: converting to cmpgesi_t\n");
692	      emit_insn (gen_cmpgesi_t (eop0.use_as_extended_reg (curr_insn),
693					const0_rtx));
694	      DONE;
695	    }
696	  else if (!CONST_OK_FOR_K08 (op1val))
697	    {
698	      if (dump_file)
699		fprintf (dump_file, "tstsi_t: converting const_int to signed "
700			 "value\n");
701
702	      /* If here we haven't done anything yet.  Convert the constant
703		 to a signed value to reduce the constant pool size.  */
704	      operands[0] = eop0.use_as_extended_reg (curr_insn);
705
706	      if (eop0.from_mode == QImode)
707		op1val |= (op1val & 0x80) ? 0xFFFFFFFFFFFFFF00LL : 0;
708	      else if (eop0.from_mode == HImode)
709		op1val |= (op1val & 0x8000) ? 0xFFFFFFFFFFFF0000LL : 0;
710	    }
711	  else
712	    operands[0] = eop0.use_as_extended_reg (curr_insn);
713	}
714    }
715
716    if (dump_file)
717      fprintf (dump_file, "tstsi_t: using const_int 0x%08x\n",
718	       (uint32_t)op1val);
719
720  /* Try to fit the constant into 8 bits by shuffling the value in the
721     register operand.
722     Doing that usually results in smaller code as the constants in the
723     pools are avoided (32 bit constant = load + constant = 6 bytes).
724     However, if the constant load (LS insn) can be hoisted insn dependencies
725     can be avoided and chances for parallel execution increase.  The common
726     usage pattern is:
727       - load reg from mem
728       - test bits
729       - conditional branch
730
731     FIXME: For now we do that only when optimizing for size until there is
732     a better heuristic.
733
734     FIXME: If there are multiple tst insns in the block with the same
735     constant, avoid the #imm variant to avoid R0 loads.  Use the 'tst Rn,Rm'
736     variant instead and load the constant into a reg.  For that we'd need
737     to do some analysis.  */
738
739  if (CONST_OK_FOR_K08 (op1val))
740    {
741      /* Do nothing.  */
742    }
743  else if ((op1val & 0xFFFF) == 0
744	   && CONST_OK_FOR_K08 (op1val >> 16) && optimize_size)
745    {
746      /* Use a swap.w insn to do a shift + reg copy (to R0) in one insn.  */
747      op1val = op1val >> 16;
748      rtx r = gen_reg_rtx (SImode);
749      emit_insn (gen_rotlsi3_16 (r, operands[0]));
750      operands[0] = r;
751    }
752  else if ((op1val & 0xFF) == 0
753	   && CONST_OK_FOR_K08 (op1val >> 8) && optimize_size)
754    {
755      /* Use a swap.b insn to do a shift + reg copy (to R0) in one insn.  */
756      op1val = op1val >> 8;
757      rtx r = gen_reg_rtx (SImode);
758      emit_insn (gen_swapbsi2 (r, operands[0]));
759      operands[0] = r;
760    }
761  else if ((op1val & 3) == 0
762	   && CONST_OK_FOR_K08 (op1val >> 2) && optimize_size)
763    {
764      op1val = op1val >> 2;
765      rtx r = gen_reg_rtx (SImode);
766      emit_insn (gen_lshrsi3_k (r, operands[0], GEN_INT (2)));
767      operands[0] = r;
768    }
769  else if ((op1val & 1) == 0
770	   && CONST_OK_FOR_K08 (op1val >> 1) && optimize_size)
771    {
772      op1val = op1val >> 1;
773      rtx r = gen_reg_rtx (SImode);
774      emit_insn (gen_shlr (r, operands[0]));
775      operands[0] = r;
776    }
777
778  operands[1] = GEN_INT (op1val);
779
780  if (!satisfies_constraint_K08 (operands[1]))
781    operands[1] = force_reg (SImode, operands[1]);
782
783  emit_insn (gen_tstsi_t (operands[0], operands[1]));
784  DONE;
785}
786  [(set_attr "type" "mt_group")])
787
788;; This pattern is used by combine when testing QI/HImode subregs with a
789;; negative constant.  Ignore high bits by masking them out in the constant.
790(define_insn_and_split "*tst<mode>_t"
791  [(set (reg:SI T_REG)
792	(eq:SI (subreg:SI
793		 (and:QIHI (match_operand:QIHI 0 "arith_reg_operand")
794			   (match_operand 1 "const_int_operand")) 0)
795	       (const_int 0)))]
796  "TARGET_SH1 && can_create_pseudo_p ()"
797  "#"
798  "&& 1"
799  [(set (reg:SI T_REG)
800	(eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))]
801{
802  operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
803  operands[1] = GEN_INT (INTVAL (operands[1])
804			 & (<MODE>mode == HImode ? 0xFFFF : 0xFF));
805})
806
807;; This pattern might be risky because it also tests the upper bits and not
808;; only the subreg.  We have to check whether the operands have been sign
809;; or zero extended.  In the worst case, a zero extension has to be inserted
810;; to mask out the unwanted bits.
811(define_insn_and_split "*tst<mode>_t_subregs"
812  [(set (reg:SI T_REG)
813	(eq:SI
814	  (subreg:QIHI
815	    (and:SI (match_operand:SI 0 "arith_reg_operand")
816		    (match_operand:SI 1 "arith_reg_operand")) <lowpart_le>)
817	  (const_int 0)))]
818  "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()"
819  "#"
820  "&& !sh_in_recog_treg_set_expr ()"
821  [(const_int 0)]
822{
823  sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_le>, operands);
824  DONE;
825})
826
827(define_insn_and_split "*tst<mode>_t_subregs"
828  [(set (reg:SI T_REG)
829	(eq:SI
830	  (subreg:QIHI
831	    (and:SI (match_operand:SI 0 "arith_reg_operand")
832		    (match_operand:SI 1 "arith_reg_operand")) <lowpart_be>)
833	  (const_int 0)))]
834  "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()"
835  "#"
836  "&& !sh_in_recog_treg_set_expr ()"
837  [(const_int 0)]
838{
839  sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_be>, operands);
840  DONE;
841})
842
843;; Extract contiguous bits and compare them against zero.
844;; Notice that this will not be used for single bits.  Special single bit
845;; extraction patterns are in the 'bit field extract patterns' section.
846(define_insn_and_split "*tst<mode>_t_zero_extract"
847  [(set (reg:SI T_REG)
848	(eq:SI (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand")
849				(match_operand 1 "const_int_operand")
850				(match_operand 2 "const_int_operand"))
851	       (const_int 0)))]
852  "TARGET_SH1 && can_create_pseudo_p ()"
853  "#"
854  "&& 1"
855  [(set (reg:SI T_REG)
856	(eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))]
857{
858  operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
859  if (GET_MODE (operands[0]) != SImode)
860    operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
861})
862
863;; Convert '(reg << shift) & mask' into 'reg & (mask >> shift)'.
864;; The shifted-out bits in the mask will always be zero, since the
865;; shifted-in bits in the reg will also be always zero.
866(define_insn_and_split "*tstsi_t_shift_mask"
867  [(set (reg:SI T_REG)
868	(eq:SI (and:SI (ashift:SI (match_operand:SI 0 "arith_reg_operand")
869				  (match_operand 1 "const_int_operand"))
870		       (match_operand 2 "const_int_operand"))
871	       (const_int 0)))]
872  "TARGET_SH1 && can_create_pseudo_p ()"
873  "#"
874  "&& 1"
875  [(set (reg:SI T_REG)
876	(eq:SI (and:SI (match_dup 0) (match_dup 2)) (const_int 0)))]
877{
878  operands[2] = GEN_INT (INTVAL (operands[2]) >> INTVAL (operands[1]));
879})
880
881(define_insn "cmpeqsi_t"
882  [(set (reg:SI T_REG)
883	(eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
884	       (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
885  "TARGET_SH1"
886  "@
887	tst	%0,%0
888	cmp/eq	%1,%0
889	cmp/eq	%1,%0"
890  [(set_attr "type" "mt_group")])
891
892;; Sometimes combine fails to form the (eq (and (op) (op)) 0) tst insn.
893;; Try to fix that in the split1 pass by looking for the previous set
894;; of the tested op.  Also see if there is a preceeding sign/zero
895;; extension that can be avoided.
896(define_split
897  [(set (reg:SI T_REG)
898	(eq:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))]
899  "TARGET_SH1 && can_create_pseudo_p () && optimize
900   && !sh_in_recog_treg_set_expr ()"
901  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
902{
903  if (dump_file)
904    fprintf (dump_file, "cmpeqsi_t: trying to optimize const_int 0\n");
905
906  /* If the tested reg is not dead after this insn, it's probably used by
907     something else after the comparison.  It's probably better to leave
908     it as it is.  */
909  if (find_regno_note (curr_insn, REG_DEAD, REGNO (operands[0])) == NULL_RTX)
910    FAIL;
911
912  /* FIXME: Maybe also search the predecessor basic blocks to catch
913     more cases.  */
914  set_of_reg op = sh_find_set_of_reg (operands[0], curr_insn,
915				      prev_nonnote_insn_bb);
916
917  if (op.set_src != NULL && GET_CODE (op.set_src) == AND
918      && !sh_insn_operands_modified_between_p (op.insn, op.insn, curr_insn))
919    {
920      if (dump_file)
921	fprintf (dump_file, "cmpeqsi_t: found preceeding and in insn %d\n",
922		 INSN_UID (op.insn));
923
924      if (!(arith_reg_operand (XEXP (op.set_src, 0), SImode)
925	    && (arith_reg_operand (XEXP (op.set_src, 1), SImode)
926		|| CONST_INT_P (XEXP (op.set_src, 1)))))
927	FAIL;
928
929      /* Assume that the operands of the andsi insn are compatible with the
930	 operands of the tstsi_t insn, which is generally the case.  */
931      if (dump_file)
932	fprintf (dump_file, "cmpeqsi_t: replacing with tstsi_t\n");
933      emit_insn (gen_tstsi_t (XEXP (op.set_src, 0), XEXP (op.set_src, 1)));
934      DONE;
935    }
936
937  /* Converting HImode into tests against 0xFFFF tends to increase the code
938     size, as it will create constant pool entries.  Disable it for now.  */
939  const bool enable_himode = false;
940
941  /* FIXME: try to keep the (eq (reg) (const_int 0)).  Even if the zero
942     extended reg is used after this insn, if we know that _before_ the zero
943     extension the value was loaded via sign extending mem load, we can just
944     use the value of the mem load directly.  */
945  sh_extending_set_of_reg eop = sh_find_extending_set_of_reg (operands[0],
946							      curr_insn);
947
948  if (eop.ext_code != UNKNOWN
949      && (eop.from_mode == QImode || (eop.from_mode == HImode && enable_himode))
950      && eop.can_use_as_unextended_reg ()
951      && !reg_used_between_p (operands[0], eop.insn, curr_insn))
952    {
953      /* Bypass the sign/zero extension and test against the bit mask, but
954	 only if it's the only use of the sign/zero extracted value.
955	 Otherwise we'd be introducing new constants in the pool.  */
956      if (dump_file)
957	fprintf (dump_file, "cmpeqsi_t: bypassing sign/zero extension in "
958		 "insn %d and using tstsi_t\n", INSN_UID (op.insn));
959
960      emit_insn (gen_tstsi_t (
961	  eop.use_as_unextended_reg (curr_insn),
962	  GEN_INT (eop.from_mode == QImode ? 0xFF : 0xFFFF)));
963      DONE;
964    }
965
966  if (dump_file)
967    fprintf (dump_file, "cmpeqsi_t: nothing optimized\n");
968  FAIL;
969})
970
971;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
972;; pattern by itself.  What this actually does is:
973;;	x == 0: (1 >> 0-0) & 1 = 1
974;;	x != 0: (1 >> 0-x) & 1 = 0
975;; Without this the test pr51244-8.c fails on SH2A and SH4A.
976(define_insn_and_split "*cmpeqsi_t"
977  [(set (reg:SI T_REG)
978	(and:SI (lshiftrt:SI
979		  (const_int 1)
980		  (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
981		(const_int 1)))]
982  "TARGET_SH1"
983  "#"
984  "&& 1"
985  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
986
987(define_insn "cmpgtsi_t"
988  [(set (reg:SI T_REG)
989	(gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
990	       (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
991  "TARGET_SH1"
992  "@
993	cmp/pl	%0
994	cmp/gt	%1,%0"
995  [(set_attr "type" "mt_group")])
996
997(define_insn "cmpgesi_t"
998  [(set (reg:SI T_REG)
999	(ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
1000	       (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
1001  "TARGET_SH1"
1002  "@
1003	cmp/pz	%0
1004	cmp/ge	%1,%0"
1005  [(set_attr "type" "mt_group")])
1006
1007;; Recombine a cmp/pz followed by a nott into a shll.
1008;; On non-SH2A recombine a cmp/pz followed by a movrt into shll-movt.
1009;; On SH2A cmp/pz-movrt is slightly better, as it does not mutate the input.
1010(define_split
1011  [(set (reg:SI T_REG)
1012	(ge:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))]
1013
1014  "TARGET_SH1 && can_create_pseudo_p () && optimize
1015   && !sh_in_recog_treg_set_expr ()"
1016  [(const_int 0)]
1017{
1018  if (dump_file)
1019    fprintf (dump_file, "cmpgesi_t: trying to optimize for const_int 0\n");
1020
1021  rtx_insn* i = next_nonnote_insn_bb (curr_insn);
1022
1023  if (dump_file)
1024    {
1025      fprintf (dump_file, "cmpgesi_t: following insn is \n");
1026      print_rtl_single (dump_file, i);
1027      fprintf (dump_file, "\n");
1028    }
1029
1030  if (sh_is_nott_insn (i))
1031    {
1032      if (dump_file)
1033	fprintf (dump_file,
1034		 "cmpgesi_t: replacing (cmp/pz, nott) with (shll)\n");
1035      emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
1036      set_insn_deleted (i);
1037      DONE;
1038    }
1039
1040  /* On non-SH2A negc is used as movrt replacement, which sets T = 1.
1041     Thus we can remove it only if T is marked as dead afterwards.  */
1042  if (rtx dest_reg = !TARGET_SH2A
1043		     && sh_reg_dead_or_unused_after_insn (i, T_REG)
1044		     ? sh_movrt_set_dest (i) : NULL)
1045    {
1046      if (dump_file)
1047	fprintf (dump_file,
1048		 "cmpgesi_t: replacing (cmp/pz, movrt) with (shll, movt)\n");
1049      emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
1050      add_reg_note (emit_insn (gen_movt (dest_reg, get_t_reg_rtx ())),
1051		    REG_DEAD, get_t_reg_rtx ());
1052      set_insn_deleted (i);
1053      DONE;
1054    }
1055
1056  if (dump_file)
1057    fprintf (dump_file, "cmpgesi_t: nothing optimized\n");
1058
1059  FAIL;
1060})
1061
1062;; FIXME: This is actually wrong.  There is no way to literally move a
1063;; general reg to t reg.  Luckily, it seems that this pattern will be only
1064;; used when the general reg is known be either '0' or '1' during combine.
1065;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
1066;; Due to interactions with other patterns, combine fails to pick the latter
1067;; and invert the dependent logic.
1068(define_insn "*negtstsi"
1069  [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
1070  "TARGET_SH1 && !sh_in_recog_treg_set_expr ()"
1071  "cmp/pl	%0"
1072  [(set_attr "type" "mt_group")])
1073
1074;; Some integer sign comparison patterns can be realized with the div0s insn.
1075;;	div0s	Rm,Rn		T = (Rm >> 31) ^ (Rn >> 31)
1076;;
1077;; The 'cmp_div0s' pattern is our canonical form, into which all the other
1078;; variations are converted.  The negative forms will split into a trailing
1079;; nott sequence, which will be eliminated either by the
1080;; 'any_treg_expr_to_reg' pattern, or by the 'sh_treg_combine' pass.
1081(define_insn "cmp_div0s"
1082  [(set (reg:SI T_REG)
1083	(lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
1084			     (match_operand:SI 1 "arith_reg_operand" "r"))
1085		     (const_int 31)))]
1086  "TARGET_SH1"
1087  "div0s	%0,%1"
1088  [(set_attr "type" "arith")])
1089
1090(define_insn_and_split "*cmp_div0s_1"
1091  [(set (reg:SI T_REG)
1092	(xor:SI (ge:SI (match_operand:SI 0 "arith_reg_operand")
1093		       (const_int 0))
1094		(ge:SI (match_operand:SI 1 "arith_reg_operand")
1095		       (const_int 0))))]
1096  "TARGET_SH1 && can_create_pseudo_p ()"
1097  "#"
1098  "&& 1"
1099  [(set (reg:SI T_REG)
1100	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))])
1101
1102(define_insn_and_split "*cmp_div0s_2"
1103  [(set (reg:SI T_REG)
1104	(eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
1105			    (const_int 31))
1106	       (ge:SI (match_operand:SI 1 "arith_reg_operand")
1107		      (const_int 0))))]
1108  "TARGET_SH1 && can_create_pseudo_p ()"
1109  "#"
1110  "&& 1"
1111  [(set (reg:SI T_REG)
1112	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))])
1113
1114(define_insn_and_split "*cmp_div0s_3"
1115  [(set (reg:SI T_REG)
1116	(eq:SI (ge:SI (match_operand:SI 0 "arith_reg_operand")
1117		      (const_int 0))
1118	       (ge:SI (match_operand:SI 1 "arith_reg_operand")
1119		      (const_int 0))))]
1120  "TARGET_SH1 && can_create_pseudo_p ()"
1121  "#"
1122  "&& 1"
1123  [(set (reg:SI T_REG)
1124	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1125   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1126
1127(define_insn_and_split "*cmp_div0s_4"
1128  [(set (reg:SI T_REG)
1129	(ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand")
1130		       (match_operand:SI 1 "arith_reg_operand"))
1131	       (const_int 0)))]
1132  "TARGET_SH1 && can_create_pseudo_p ()"
1133  "#"
1134  "&& 1"
1135  [(set (reg:SI T_REG)
1136	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1137   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1138
1139(define_insn_and_split "*cmp_div0s_5"
1140  [(set (reg:SI T_REG)
1141	(xor:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
1142			     (const_int 31))
1143		(ge:SI (match_operand:SI 1 "arith_reg_operand")
1144		       (const_int 0))))]
1145  "TARGET_SH1 && can_create_pseudo_p ()"
1146  "#"
1147  "&& 1"
1148  [(set (reg:SI T_REG)
1149	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1150   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1151
1152(define_insn_and_split "*cmp_div0s_6"
1153  [(set (reg:SI T_REG)
1154	(eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
1155			    (const_int 31))
1156	       (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
1157			    (const_int 31))))]
1158  "TARGET_SH1 && can_create_pseudo_p ()"
1159  "#"
1160  "&& 1"
1161  [(set (reg:SI T_REG)
1162	(lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1163   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1164
1165;; -------------------------------------------------------------------------
1166;; SImode compare and branch
1167;; -------------------------------------------------------------------------
1168
1169(define_expand "cbranchsi4"
1170  [(set (pc)
1171	(if_then_else (match_operator 0 "comparison_operator"
1172			[(match_operand:SI 1 "arith_operand" "")
1173			 (match_operand:SI 2 "arith_operand" "")])
1174		      (label_ref (match_operand 3 "" ""))
1175		      (pc)))
1176   (clobber (reg:SI T_REG))]
1177  ""
1178{
1179  if (TARGET_SHMEDIA)
1180    emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1181					   operands[2], operands[3]));
1182  else
1183    expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
1184
1185  DONE;
1186})
1187
1188;; Combine patterns to invert compare and branch operations for which we
1189;; don't have actual comparison insns.  These patterns are used in cases
1190;; which appear after the initial cbranchsi expansion, which also does
1191;; some condition inversion.
1192(define_split
1193  [(set (pc)
1194	(if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
1195			  (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1196		      (label_ref (match_operand 2))
1197		      (pc)))
1198   (clobber (reg:SI T_REG))]
1199  "TARGET_SH1"
1200  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
1201   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1202			   (label_ref (match_dup 2))
1203			   (pc)))])
1204
1205;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
1206;; and SH2A combine fails to simplify this pattern by itself.
1207;; What this actually does is:
1208;;	x == 0: (1 >> 0-0) & 1 = 1
1209;;	x != 0: (1 >> 0-x) & 1 = 0
1210;; Without this the test pr51244-8.c fails on SH2A and SH4A.
1211(define_split
1212  [(set (pc)
1213	(if_then_else
1214	  (eq (and:SI (lshiftrt:SI
1215			(const_int 1)
1216			(neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
1217		      (const_int 1))
1218	      (const_int 0))
1219	  (label_ref (match_operand 2))
1220	  (pc)))
1221   (clobber (reg:SI T_REG))]
1222  "TARGET_SH1"
1223  [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
1224   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1225			   (label_ref (match_dup 2))
1226			   (pc)))])
1227
1228;; FIXME: These could probably use code iterators for the compare op.
1229(define_split
1230  [(set (pc)
1231	(if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
1232			  (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1233		      (label_ref (match_operand 2))
1234		      (pc)))
1235   (clobber (reg:SI T_REG))]
1236  "TARGET_SH1"
1237  [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
1238   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1239			   (label_ref (match_dup 2))
1240			   (pc)))])
1241
1242(define_split
1243  [(set (pc)
1244	(if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
1245			  (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1246		      (label_ref (match_operand 2))
1247		      (pc)))
1248   (clobber (reg:SI T_REG))]
1249  "TARGET_SH1"
1250  [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
1251   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1252			   (label_ref (match_dup 2))
1253			   (pc)))])
1254
1255(define_split
1256  [(set (pc)
1257	(if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
1258			   (match_operand:SI 1 "arith_reg_operand" ""))
1259		      (label_ref (match_operand 2))
1260		      (pc)))
1261   (clobber (reg:SI T_REG))]
1262  "TARGET_SH1"
1263  [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
1264   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1265			   (label_ref (match_dup 2))
1266			   (pc)))])
1267
1268(define_split
1269  [(set (pc)
1270	(if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
1271			   (match_operand:SI 1 "arith_reg_operand" ""))
1272		      (label_ref (match_operand 2))
1273		      (pc)))
1274   (clobber (reg:SI T_REG))]
1275  "TARGET_SH1"
1276  [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
1277   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1278			   (label_ref (match_dup 2))
1279			   (pc)))])
1280
1281;; -------------------------------------------------------------------------
1282;; SImode unsigned integer comparisons
1283;; -------------------------------------------------------------------------
1284
1285;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1286;; However, especially when optimizations are off (e.g. -O0) such comparisons
1287;; might remain and we have to handle them.  If the '>= 0' case wasn't
1288;; handled here, something else would just load a '0' into the second operand
1289;; and do the comparison.  We can do slightly better by just setting the
1290;; T bit to '1'.
1291(define_insn_and_split "cmpgeusi_t"
1292  [(set (reg:SI T_REG)
1293	(geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1294		(match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1295  "TARGET_SH1"
1296  "cmp/hs	%1,%0"
1297  "&& satisfies_constraint_Z (operands[1])"
1298  [(set (reg:SI T_REG) (const_int 1))]
1299  ""
1300  [(set_attr "type" "mt_group")])
1301
1302(define_insn "cmpgtusi_t"
1303  [(set (reg:SI T_REG)
1304	(gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1305		(match_operand:SI 1 "arith_reg_operand" "r")))]
1306  "TARGET_SH1"
1307  "cmp/hi	%1,%0"
1308  [(set_attr "type" "mt_group")])
1309
1310;; -------------------------------------------------------------------------
1311;; DImode compare and branch
1312;; -------------------------------------------------------------------------
1313
1314;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1315;; Therefore, we aim to have a set of three branches that go straight to the
1316;; destination, i.e. only one of them is taken at any one time.
1317;; This mechanism should also be slightly better for the sh4-200.
1318
1319(define_expand "cbranchdi4"
1320  [(set (pc)
1321	(if_then_else (match_operator 0 "comparison_operator"
1322			[(match_operand:DI 1 "arith_operand" "")
1323			 (match_operand:DI 2 "arith_operand" "")])
1324		      (label_ref (match_operand 3 "" ""))
1325		      (pc)))
1326   (clobber (match_dup 4))
1327   (clobber (reg:SI T_REG))]
1328  "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1329{
1330  enum rtx_code comparison;
1331
1332  if (TARGET_SHMEDIA)
1333    {
1334      emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1335					     operands[2], operands[3]));
1336      DONE;
1337    }
1338  else if (!TARGET_CBRANCHDI4)
1339    {
1340      sh_emit_compare_and_branch (operands, DImode);
1341      DONE;
1342    }
1343  else
1344    {
1345      if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1346	DONE;
1347
1348      comparison = prepare_cbranch_operands (operands, DImode,
1349					     LAST_AND_UNUSED_RTX_CODE);
1350      if (comparison != GET_CODE (operands[0]))
1351	operands[0]
1352	  = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1353       operands[4] = gen_rtx_SCRATCH (SImode);
1354    }
1355})
1356
1357(define_insn_and_split "cbranchdi4_i"
1358  [(set (pc)
1359	(if_then_else (match_operator 0 "comparison_operator"
1360			[(match_operand:DI 1 "arith_operand" "r,r")
1361			 (match_operand:DI 2 "arith_operand" "rN,I08")])
1362		      (label_ref (match_operand 3 "" ""))
1363		      (pc)))
1364   (clobber (match_scratch:SI 4 "=X,&r"))
1365   (clobber (reg:SI T_REG))]
1366  "TARGET_CBRANCHDI4"
1367  "#"
1368  "&& reload_completed"
1369  [(pc)]
1370{
1371  if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1372    FAIL;
1373  DONE;
1374})
1375
1376;; -------------------------------------------------------------------------
1377;; DImode signed integer comparisons
1378;; -------------------------------------------------------------------------
1379
1380(define_insn ""
1381  [(set (reg:SI T_REG)
1382	(eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1383		       (match_operand:DI 1 "arith_operand" "r"))
1384	       (const_int 0)))]
1385  "TARGET_SH1"
1386{
1387  return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1388			      insn, operands);
1389}
1390  [(set_attr "length" "6")
1391   (set_attr "type" "arith3b")])
1392
1393(define_insn "cmpeqdi_t"
1394  [(set (reg:SI T_REG)
1395	(eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1396	       (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1397  "TARGET_SH1"
1398{
1399  static const char* alt[] =
1400  {
1401       "tst	%S0,%S0"	"\n"
1402    "	bf	0f"		"\n"
1403    "	tst	%R0,%R0"	"\n"
1404    "0:",
1405
1406       "cmp/eq	%S1,%S0"	"\n"
1407    "	bf	0f"		"\n"
1408    "	cmp/eq	%R1,%R0"	"\n"
1409    "0:"
1410  };
1411  return alt[which_alternative];
1412}
1413  [(set_attr "length" "6")
1414   (set_attr "type" "arith3b")])
1415
1416(define_split
1417  [(set (reg:SI T_REG)
1418	(eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1419	       (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1420;; If we applied this split when not optimizing, it would only be
1421;; applied during the machine-dependent reorg, when no new basic blocks
1422;; may be created.
1423  "TARGET_SH1 && reload_completed && optimize"
1424  [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1425   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1426			   (label_ref (match_dup 6))
1427			   (pc)))
1428   (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1429   (match_dup 6)]
1430{
1431  operands[2] = gen_highpart (SImode, operands[0]);
1432  operands[3] = operands[1] == const0_rtx
1433		? const0_rtx
1434		: gen_highpart (SImode, operands[1]);
1435  operands[4] = gen_lowpart (SImode, operands[0]);
1436  operands[5] = gen_lowpart (SImode, operands[1]);
1437  operands[6] = gen_label_rtx ();
1438})
1439
1440(define_insn "cmpgtdi_t"
1441  [(set (reg:SI T_REG)
1442	(gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1443	       (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1444  "TARGET_SH2"
1445{
1446  static const char* alt[] =
1447  {
1448       "cmp/eq	%S1,%S0"	"\n"
1449    "	bf{.|/}s	0f"	"\n"
1450    "	cmp/gt	%S1,%S0"	"\n"
1451    "	cmp/hi	%R1,%R0"	"\n"
1452    "0:",
1453
1454        "tst	%S0,%S0"	"\n"
1455    "	bf{.|/}s	0f"	"\n"
1456    "	cmp/pl	%S0"		"\n"
1457    "	cmp/hi	%S0,%R0"	"\n"
1458    "0:"
1459  };
1460  return alt[which_alternative];
1461}
1462  [(set_attr "length" "8")
1463   (set_attr "type" "arith3")])
1464
1465(define_insn "cmpgedi_t"
1466  [(set (reg:SI T_REG)
1467	(ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1468	       (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1469  "TARGET_SH2"
1470{
1471  static const char* alt[] =
1472  {
1473       "cmp/eq	%S1,%S0"	"\n"
1474    "	bf{.|/}s	0f"	"\n"
1475    "	cmp/ge	%S1,%S0"	"\n"
1476    "	cmp/hs	%R1,%R0"	"\n"
1477    "0:",
1478
1479       "cmp/pz	%S0"
1480  };
1481  return alt[which_alternative];
1482}
1483  [(set_attr "length" "8,2")
1484   (set_attr "type" "arith3,mt_group")])
1485
1486;; -------------------------------------------------------------------------
1487;; DImode unsigned integer comparisons
1488;; -------------------------------------------------------------------------
1489
1490(define_insn "cmpgeudi_t"
1491  [(set (reg:SI T_REG)
1492	(geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1493		(match_operand:DI 1 "arith_reg_operand" "r")))]
1494  "TARGET_SH2"
1495{
1496  return       "cmp/eq	%S1,%S0"	"\n"
1497	 "	bf{.|/}s	0f"	"\n"
1498	 "	cmp/hs	%S1,%S0"	"\n"
1499	 "	cmp/hs	%R1,%R0"	"\n"
1500	 "0:";
1501}
1502  [(set_attr "length" "8")
1503   (set_attr "type" "arith3")])
1504
1505(define_insn "cmpgtudi_t"
1506  [(set (reg:SI T_REG)
1507	(gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1508		(match_operand:DI 1 "arith_reg_operand" "r")))]
1509  "TARGET_SH2"
1510{
1511  return       "cmp/eq	%S1,%S0"	"\n"
1512	 "	bf{.|/}s	0f"	"\n"
1513	 "	cmp/hi	%S1,%S0"	"\n"
1514	 "	cmp/hi	%R1,%R0"	"\n"
1515	 "0:";
1516}
1517  [(set_attr "length" "8")
1518   (set_attr "type" "arith3")])
1519
1520(define_insn "cmpeqsi_media"
1521  [(set (match_operand:SI 0 "register_operand" "=r")
1522	(eq:SI (match_operand:SI 1 "logical_operand" "%r")
1523	       (match_operand:SI 2 "cmp_operand" "Nr")))]
1524  "TARGET_SHMEDIA"
1525  "cmpeq	%1, %N2, %0"
1526  [(set_attr "type" "cmp_media")])
1527
1528(define_insn "cmpeqdi_media"
1529  [(set (match_operand:SI 0 "register_operand" "=r")
1530	(eq:SI (match_operand:DI 1 "register_operand" "%r")
1531	       (match_operand:DI 2 "cmp_operand" "Nr")))]
1532  "TARGET_SHMEDIA"
1533  "cmpeq	%1, %N2, %0"
1534  [(set_attr "type" "cmp_media")])
1535
1536(define_insn "cmpgtsi_media"
1537  [(set (match_operand:SI 0 "register_operand" "=r")
1538	(gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1539	       (match_operand:SI 2 "cmp_operand" "rN")))]
1540  "TARGET_SHMEDIA"
1541  "cmpgt	%N1, %N2, %0"
1542  [(set_attr "type" "cmp_media")])
1543
1544(define_insn "cmpgtdi_media"
1545  [(set (match_operand:SI 0 "register_operand" "=r")
1546	(gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1547	       (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1548  "TARGET_SHMEDIA"
1549  "cmpgt	%N1, %N2, %0"
1550  [(set_attr "type" "cmp_media")])
1551
1552(define_insn "cmpgtusi_media"
1553  [(set (match_operand:SI 0 "register_operand" "=r")
1554	(gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1555		(match_operand:SI 2 "cmp_operand" "rN")))]
1556  "TARGET_SHMEDIA"
1557  "cmpgtu	%N1, %N2, %0"
1558  [(set_attr "type" "cmp_media")])
1559
1560(define_insn "cmpgtudi_media"
1561  [(set (match_operand:SI 0 "register_operand" "=r")
1562	(gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1563		(match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1564  "TARGET_SHMEDIA"
1565  "cmpgtu	%N1, %N2, %0"
1566  [(set_attr "type" "cmp_media")])
1567
1568; This pattern is for combine.
1569(define_insn "*cmpne0sisi_media"
1570  [(set (match_operand:SI 0 "register_operand" "=r")
1571	(ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1572  "TARGET_SHMEDIA"
1573  "cmpgtu	%1,r63,%0"
1574  [(set_attr "type" "cmp_media")])
1575
1576;; -------------------------------------------------------------------------
1577;; Conditional move instructions
1578;; -------------------------------------------------------------------------
1579
1580;; The insn names may seem reversed, but note that cmveq performs the move
1581;; if op1 == 0, and cmvne does it if op1 != 0.
1582
1583(define_insn "movdicc_false"
1584  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1585	(if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1586			     (const_int 0))
1587	 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1588	 (match_operand:DI 3 "arith_reg_operand" "0")))]
1589  "TARGET_SHMEDIA"
1590  "cmveq	%1, %N2, %0"
1591  [(set_attr "type" "arith_media")])
1592
1593(define_insn "movdicc_true"
1594  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1595	(if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1596			     (const_int 0))
1597	 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1598	 (match_operand:DI 3 "arith_reg_operand" "0")))]
1599  "TARGET_SHMEDIA"
1600  "cmvne	%1, %N2, %0"
1601  [(set_attr "type" "arith_media")])
1602
1603(define_peephole2
1604  [(set (match_operand:DI 0 "arith_reg_dest" "")
1605	(if_then_else:DI (match_operator 3 "equality_comparison_operator"
1606			   [(match_operand:DI 1 "arith_reg_operand" "")
1607			    (const_int 0)])
1608	 (match_operand:DI 2 "arith_reg_dest" "")
1609	 (match_dup 0)))
1610   (set (match_dup 2) (match_dup 0))]
1611  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1612  [(set (match_dup 2)
1613	(if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1614{
1615  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1616				VOIDmode, operands[1], CONST0_RTX (DImode));
1617})
1618
1619(define_peephole2
1620  [(set (match_operand:DI 0 "general_movdst_operand" "")
1621	(match_operand:DI 1 "arith_reg_or_0_operand" ""))
1622   (set (match_operand:DI 2 "arith_reg_dest" "")
1623	(if_then_else:DI (match_operator 4 "equality_comparison_operator"
1624			   [(match_operand:DI 3 "arith_reg_operand" "")
1625			    (const_int 0)])
1626	 (match_dup 0)
1627	 (match_dup 2)))]
1628  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1629  [(set (match_dup 2)
1630	(if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1631  "")
1632
1633(define_expand "movdicc"
1634  [(set (match_operand:DI 0 "register_operand" "")
1635	(if_then_else:DI (match_operand 1 "comparison_operator" "")
1636			 (match_operand:DI 2 "register_operand" "")
1637			 (match_operand:DI 3 "register_operand" "")))]
1638  "TARGET_SHMEDIA"
1639{
1640  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1641      && GET_MODE (XEXP (operands[1], 0)) == DImode
1642      && XEXP (operands[1], 1) == const0_rtx)
1643    ;
1644  else
1645    {
1646      if (!can_create_pseudo_p ())
1647	FAIL;
1648
1649      operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1650					      GET_CODE (operands[1]),
1651					      XEXP (operands[1], 0),
1652					      XEXP (operands[1], 1));
1653      if (!operands[1])
1654	FAIL;
1655    }
1656})
1657
1658;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1659;; SImode to DImode.
1660(define_insn "movsicc_false"
1661  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1662	(if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1663			  (const_int 0))
1664	 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1665	 (match_operand:SI 3 "arith_reg_operand" "0")))]
1666  "TARGET_SHMEDIA"
1667  "cmveq	%1, %N2, %0"
1668  [(set_attr "type" "arith_media")])
1669
1670(define_insn "movsicc_true"
1671  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1672	(if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1673			  (const_int 0))
1674	 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1675	 (match_operand:SI 3 "arith_reg_operand" "0")))]
1676  "TARGET_SHMEDIA"
1677  "cmvne	%1, %N2, %0"
1678  [(set_attr "type" "arith_media")])
1679
1680(define_peephole2
1681  [(set (match_operand:SI 0 "arith_reg_dest" "")
1682	(if_then_else:SI (match_operator 3 "equality_comparison_operator"
1683			   [(match_operand:SI 1 "arith_reg_operand" "")
1684			    (const_int 0)])
1685	 (match_operand:SI 2 "arith_reg_dest" "")
1686	 (match_dup 0)))
1687   (set (match_dup 2) (match_dup 0))]
1688  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1689  [(set (match_dup 2)
1690	(if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1691{
1692  operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1693				VOIDmode, operands[1], CONST0_RTX (SImode));
1694})
1695
1696(define_peephole2
1697  [(set (match_operand:SI 0 "general_movdst_operand" "")
1698	(match_operand:SI 1 "arith_reg_or_0_operand" ""))
1699   (set (match_operand:SI 2 "arith_reg_dest" "")
1700	(if_then_else:SI (match_operator 4 "equality_comparison_operator"
1701			   [(match_operand:SI 3 "arith_reg_operand" "")
1702			    (const_int 0)])
1703	 (match_dup 0)
1704	 (match_dup 2)))]
1705  "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1706   && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1707  [(set (match_dup 2)
1708	(if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1709{
1710  replace_rtx (operands[4], operands[0], operands[1]);
1711})
1712
1713;; The register allocator is rather clumsy in handling multi-way conditional
1714;; moves, so allow the combiner to make them, and we split them up after
1715;; reload.  */
1716(define_insn_and_split "*movsicc_umin"
1717  [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1718	(umin:SI (if_then_else:SI
1719		   (eq (match_operand:SI 1 "arith_reg_operand" "r")
1720		       (const_int 0))
1721		   (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1722		   (match_operand:SI 3 "register_operand" "0"))
1723		 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1724   (clobber (match_scratch:SI 5 "=&r"))]
1725  "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1726  "#"
1727  "TARGET_SHMEDIA && reload_completed"
1728  [(pc)]
1729{
1730  emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1731				operands[3]));
1732  emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1733  emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1734				operands[0]));
1735  DONE;
1736})
1737
1738(define_insn "*movsicc_t_false"
1739  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1740	(if_then_else (eq (reg:SI T_REG) (const_int 0))
1741		      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1742		      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1743  "TARGET_PRETEND_CMOVE
1744   && (arith_reg_operand (operands[1], SImode)
1745       || (immediate_operand (operands[1], SImode)
1746	   && satisfies_constraint_I08 (operands[1])))"
1747{
1748  return       "bt	0f"	"\n"
1749	 "	mov	%1,%0"	"\n"
1750	 "0:";
1751}
1752  [(set_attr "type" "mt_group,arith") ;; poor approximation
1753   (set_attr "length" "4")])
1754
1755(define_insn "*movsicc_t_true"
1756  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1757	(if_then_else (ne (reg:SI T_REG) (const_int 0))
1758		      (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1759		      (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1760  "TARGET_PRETEND_CMOVE
1761   && (arith_reg_operand (operands[1], SImode)
1762       || (immediate_operand (operands[1], SImode)
1763	   && satisfies_constraint_I08 (operands[1])))"
1764{
1765  return       "bf	0f"	"\n"
1766	 "	mov	%1,%0"	"\n"
1767	 "0:";
1768}
1769  [(set_attr "type" "mt_group,arith") ;; poor approximation
1770   (set_attr "length" "4")])
1771
1772(define_expand "movsicc"
1773  [(set (match_operand:SI 0 "arith_reg_dest" "")
1774	(if_then_else:SI (match_operand 1 "comparison_operator" "")
1775			 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1776			 (match_operand:SI 3 "arith_reg_operand" "")))]
1777  "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1778{
1779  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1780      && GET_MODE (XEXP (operands[1], 0)) == SImode
1781      && (TARGET_SHMEDIA
1782	  || (REG_P (XEXP (operands[1], 0))
1783	      && REGNO (XEXP (operands[1], 0)) == T_REG))
1784      && XEXP (operands[1], 1) == const0_rtx)
1785    ;
1786
1787  else if (TARGET_PRETEND_CMOVE)
1788    {
1789      enum rtx_code code = GET_CODE (operands[1]);
1790      enum rtx_code new_code = code;
1791      rtx op0 = XEXP (operands[1], 0);
1792      rtx op1 = XEXP (operands[1], 1);
1793
1794      if (! currently_expanding_to_rtl)
1795	FAIL;
1796      switch (code)
1797	{
1798	case LT: case LE: case LEU: case LTU:
1799	  if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1800	    break;
1801	case NE:
1802	  new_code = reverse_condition (code);
1803	  break;
1804	case EQ: case GT: case GE: case GEU: case GTU:
1805	  break;
1806	default:
1807	  FAIL;
1808	}
1809      sh_emit_scc_to_t (new_code, op0, op1);
1810      operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1811				    gen_rtx_REG (SImode, T_REG), const0_rtx);
1812    }
1813  else
1814    {
1815      if (!can_create_pseudo_p ())
1816	FAIL;
1817
1818      operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1819					      GET_CODE (operands[1]),
1820					      XEXP (operands[1], 0),
1821					      XEXP (operands[1], 1));
1822      if (!operands[1])
1823	FAIL;
1824    }
1825})
1826
1827(define_expand "movqicc"
1828  [(set (match_operand:QI 0 "register_operand" "")
1829	(if_then_else:QI (match_operand 1 "comparison_operator" "")
1830			 (match_operand:QI 2 "register_operand" "")
1831			 (match_operand:QI 3 "register_operand" "")))]
1832  "TARGET_SHMEDIA"
1833{
1834  operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1835  operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1836  operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1837  emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1838  DONE;
1839})
1840
1841;; -------------------------------------------------------------------------
1842;; Addition instructions
1843;; -------------------------------------------------------------------------
1844
1845(define_expand "adddi3"
1846  [(set (match_operand:DI 0 "arith_reg_operand")
1847	(plus:DI (match_operand:DI 1 "arith_reg_operand")
1848		 (match_operand:DI 2 "arith_operand")))]
1849  ""
1850{
1851  if (TARGET_SH1)
1852    {
1853      operands[2] = force_reg (DImode, operands[2]);
1854      emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1855      DONE;
1856    }
1857})
1858
1859(define_insn "*adddi3_media"
1860  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1861	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1862		 (match_operand:DI 2 "arith_operand" "r,I10")))]
1863  "TARGET_SHMEDIA"
1864  "@
1865	add	%1, %2, %0
1866	addi	%1, %2, %0"
1867  [(set_attr "type" "arith_media")])
1868
1869(define_insn "*adddisi3_media"
1870  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1871	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1872		 (match_operand:DI 2 "arith_operand" "r,I10")))]
1873  "TARGET_SHMEDIA"
1874  "@
1875	add.l	%1, %2, %0
1876	addi.l	%1, %2, %0"
1877  [(set_attr "type" "arith_media")
1878   (set_attr "highpart" "ignore")])
1879
1880(define_insn "adddi3z_media"
1881  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1882	(zero_extend:DI
1883	 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1884		  (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1885  "TARGET_SHMEDIA"
1886  "addz.l	%1, %N2, %0"
1887  [(set_attr "type" "arith_media")
1888   (set_attr "highpart" "ignore")])
1889
1890(define_insn_and_split "adddi3_compact"
1891  [(set (match_operand:DI 0 "arith_reg_dest")
1892	(plus:DI (match_operand:DI 1 "arith_reg_operand")
1893		 (match_operand:DI 2 "arith_reg_operand")))
1894   (clobber (reg:SI T_REG))]
1895  "TARGET_SH1"
1896  "#"
1897  "&& can_create_pseudo_p ()"
1898  [(const_int 0)]
1899{
1900  emit_insn (gen_clrt ());
1901  emit_insn (gen_addc (gen_lowpart (SImode, operands[0]),
1902		       gen_lowpart (SImode, operands[1]),
1903		       gen_lowpart (SImode, operands[2])));
1904  emit_insn (gen_addc (gen_highpart (SImode, operands[0]),
1905		       gen_highpart (SImode, operands[1]),
1906		       gen_highpart (SImode, operands[2])));
1907  DONE;
1908})
1909
1910(define_insn "addc"
1911  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1912	(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1913			  (match_operand:SI 2 "arith_reg_operand" "r"))
1914		 (reg:SI T_REG)))
1915   (set (reg:SI T_REG)
1916	(ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1917  "TARGET_SH1"
1918  "addc	%2,%0"
1919  [(set_attr "type" "arith")])
1920
1921;; A simplified version of the addc insn, where the exact value of the
1922;; T bit doesn't matter.  This is easier for combine to pick up.
1923;; We allow a reg or 0 for one of the operands in order to be able to
1924;; do 'reg + T' sequences.
1925(define_insn_and_split "*addc"
1926  [(set (match_operand:SI 0 "arith_reg_dest")
1927	(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand")
1928			  (match_operand:SI 2 "arith_reg_or_0_operand"))
1929		 (match_operand 3 "treg_set_expr")))
1930   (clobber (reg:SI T_REG))]
1931  "TARGET_SH1 && can_create_pseudo_p ()"
1932  "#"
1933  "&& 1"
1934  [(const_int 0)]
1935{
1936  sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn);
1937  if (ti.has_trailing_nott ())
1938    {
1939      if (operands[2] == const0_rtx)
1940	{
1941	  /* op1 + 0 + (1 - T) = op1 + 1 - T = op1 - (-1) - T  */
1942	  remove_insn (ti.trailing_nott ());
1943	  emit_insn (gen_subc (operands[0], operands[1],
1944			       force_reg (SImode, GEN_INT (-1))));
1945	  DONE;
1946	}
1947      else if (!TARGET_SH2A)
1948	{
1949	  /* op1 + op2 + (1 - T) = op1 - (0 - op2 - 1) - T = op1 - ~op2 - T
1950	     On SH2A keep the nott insn, because nott-addc sequence doesn't
1951	     mutate the inputs.  */
1952	  remove_insn (ti.trailing_nott ());
1953	  rtx tmp = gen_reg_rtx (SImode);
1954	  emit_insn (gen_one_cmplsi2 (tmp, operands[2]));
1955	  emit_insn (gen_subc (operands[0], operands[1], tmp));
1956	  DONE;
1957	}
1958    }
1959
1960  emit_insn (gen_addc (operands[0], operands[1],
1961		       force_reg (SImode, operands[2])));
1962  DONE;
1963})
1964
1965(define_insn_and_split "*addc"
1966  [(set (match_operand:SI 0 "arith_reg_dest")
1967	(plus:SI (plus:SI (match_operand 1 "treg_set_expr")
1968			  (match_operand:SI 2 "arith_reg_operand"))
1969		 (match_operand:SI 3 "arith_reg_operand")))
1970   (clobber (reg:SI T_REG))]
1971  "TARGET_SH1 && can_create_pseudo_p ()"
1972  "#"
1973  "&& 1"
1974  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1975				          (match_dup 1)))
1976	      (clobber (reg:SI T_REG))])])
1977
1978(define_insn_and_split "*addc"
1979  [(set (match_operand:SI 0 "arith_reg_dest")
1980	(plus:SI (match_operand 1 "treg_set_expr")
1981		 (plus:SI (match_operand:SI 2 "arith_reg_operand")
1982			  (match_operand:SI 3 "arith_reg_operand"))))
1983   (clobber (reg:SI T_REG))]
1984  "TARGET_SH1 && can_create_pseudo_p ()"
1985  "#"
1986  "&& 1"
1987  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1988					  (match_dup 1)))
1989	      (clobber (reg:SI T_REG))])])
1990
1991;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1992;; matched.  Split this up into a simple sub add sequence, as this will save
1993;; us one sett insn.
1994(define_insn_and_split "*minus_plus_one"
1995  [(set (match_operand:SI 0 "arith_reg_dest" "")
1996	(plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1997			   (match_operand:SI 2 "arith_reg_operand" ""))
1998		 (const_int 1)))]
1999  "TARGET_SH1"
2000  "#"
2001  "&& 1"
2002  [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
2003   (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
2004
2005
2006;; The tree optimiziers canonicalize 
2007;;    reg + (reg & 1)
2008;; into
2009;;    (reg + 1) & -2
2010;;
2011;; On SH2A an add-bclr sequence will be used to handle this.
2012;; On non-SH2A re-emit the add-and sequence to improve register utilization.
2013(define_insn_and_split "*round_int_even"
2014  [(set (match_operand:SI 0 "arith_reg_dest")
2015	(and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand")
2016			 (const_int 1))
2017		(const_int -2)))]
2018  "TARGET_SH1 && !TARGET_SH2A && can_create_pseudo_p ()
2019   && !reg_overlap_mentioned_p (operands[0], operands[1])"
2020  "#"
2021  "&& 1"
2022  [(set (match_dup 0) (const_int -2))
2023   (set (match_dup 2) (plus:SI (match_dup 1) (const_int 1)))
2024   (set (match_dup 0) (and:SI (match_dup 0) (match_dup 2)))]
2025{
2026  operands[2] = gen_reg_rtx (SImode);
2027})
2028
2029;; If the *round_int_even pattern is combined with another plus,
2030;; convert it into an addc pattern to emit an shlr-addc sequence.
2031;; This split is taken by combine on non-SH2A and SH2A.
2032(define_split
2033  [(set (match_operand:SI 0 "arith_reg_dest")
2034	(plus:SI (and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand")
2035				  (const_int 1))
2036			 (const_int -2))
2037		 (match_operand:SI 2 "arith_reg_operand")))]
2038  "TARGET_SH1 && can_create_pseudo_p ()"
2039  [(parallel [(set (match_dup 0)
2040		   (plus:SI (plus:SI (match_dup 1) (match_dup 2))
2041			    (and:SI (match_dup 1) (const_int 1))))
2042	      (clobber (reg:SI T_REG))])])
2043
2044;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
2045;; If the 0 constant can be CSE-ed, this becomes a one instruction
2046;; operation, as opposed to sequences such as
2047;;	movt	r2
2048;;	add	r2,r3
2049;;
2050;; Even if the constant is not CSE-ed, a sequence such as
2051;;	mov	#0,r2
2052;;	addc	r2,r3
2053;; can be scheduled much better since the load of the constant can be
2054;; done earlier, before any comparison insns that store the result in
2055;; the T bit.
2056;; However, avoid things like 'reg + 1', which would expand into a
2057;; 3 insn sequence, instead of add #imm8.
2058(define_insn_and_split "*addc_t_r"
2059  [(set (match_operand:SI 0 "arith_reg_dest")
2060	(plus:SI (match_operand 1 "treg_set_expr_not_const01")
2061		 (match_operand:SI 2 "arith_reg_operand")))
2062   (clobber (reg:SI T_REG))]
2063  "TARGET_SH1 && can_create_pseudo_p ()"
2064  "#"
2065  "&& 1"
2066  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (const_int 0))
2067					  (match_dup 1)))
2068	      (clobber (reg:SI T_REG))])])
2069
2070(define_insn_and_split "*addc_r_t"
2071  [(set (match_operand:SI 0 "arith_reg_dest")
2072	(plus:SI (match_operand:SI 1 "arith_reg_operand")
2073		 (match_operand 2 "treg_set_expr_not_const01")))
2074   (clobber (reg:SI T_REG))]
2075  "TARGET_SH1 && can_create_pseudo_p ()"
2076  "#"
2077  "&& 1"
2078  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (const_int 0))
2079					  (match_dup 2)))
2080	      (clobber (reg:SI T_REG))])])
2081
2082;; Convert '2 * reg + T' into 'reg + reg + T'.
2083(define_insn_and_split "*addc_2r_t"
2084  [(set (match_operand:SI 0 "arith_reg_dest")
2085	(plus:SI (match_operand 1 "treg_set_expr")
2086		 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
2087			    (const_int 1))))
2088   (clobber (reg:SI T_REG))]
2089  "TARGET_SH1 && can_create_pseudo_p ()"
2090  "#"
2091  "&& 1"
2092  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 2))
2093					  (match_dup 1)))
2094	      (clobber (reg:SI T_REG))])])
2095
2096(define_insn_and_split "*addc_2r_t"
2097  [(set (match_operand:SI 0 "arith_reg_dest")
2098	(plus:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
2099			    (const_int 1))
2100		 (match_operand 2 "treg_set_expr")))
2101   (clobber (reg:SI T_REG))]
2102  "TARGET_SH1 && can_create_pseudo_p ()"
2103  "#"
2104  "&& 1"
2105  [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
2106					  (match_dup 2)))
2107	      (clobber (reg:SI T_REG))])])
2108
2109;; Convert '(op2 + T) - op3' into 'op2 + (-op3) + T'
2110(define_insn_and_split "*addc_negreg_t"
2111  [(set (match_operand:SI 0 "arith_reg_dest")
2112	(minus:SI (plus:SI (match_operand 1 "treg_set_expr")
2113			   (match_operand:SI 2 "arith_reg_operand"))
2114		  (match_operand:SI 3 "arith_reg_operand")))
2115   (clobber (reg:SI T_REG))]
2116  "TARGET_SH1 && can_create_pseudo_p ()"
2117  "#"
2118  "&& 1"
2119  [(set (match_dup 4) (neg:SI (match_dup 3)))
2120   (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 4))
2121					  (match_dup 1)))
2122	      (clobber (reg:SI T_REG))])]
2123{
2124  operands[4] = gen_reg_rtx (SImode);
2125})
2126
2127(define_expand "addsi3"
2128  [(set (match_operand:SI 0 "arith_reg_dest")
2129	(plus:SI (match_operand:SI 1 "arith_reg_operand")
2130		 (match_operand:SI 2 "arith_or_int_operand")))]
2131  ""
2132{
2133  if (TARGET_SH1 && !arith_operand (operands[2], SImode))
2134    {
2135      if (!sh_lra_p () || reg_overlap_mentioned_p (operands[0], operands[1]))
2136	{
2137	  emit_insn (gen_addsi3_scr (operands[0], operands[1], operands[2]));
2138	  DONE;
2139	}
2140    }
2141})
2142
2143(define_insn "addsi3_media"
2144  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
2145	(plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
2146		 (match_operand:SI 2 "arith_operand" "r,I10")))]
2147  "TARGET_SHMEDIA"
2148  "@
2149	add.l	%1, %2, %0
2150	addi.l	%1, %2, %0"
2151  [(set_attr "type" "arith_media")
2152   (set_attr "highpart" "ignore")])
2153
2154(define_insn "addsidi3_media"
2155  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
2156	(sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
2157				  "%r,r")
2158				 (match_operand:SI 2 "arith_operand"
2159				  "r,I10"))))]
2160  "TARGET_SHMEDIA"
2161  "@
2162	add.l	%1, %2, %0
2163	addi.l	%1, %2, %0"
2164  [(set_attr "type" "arith_media")
2165   (set_attr "highpart" "ignore")])
2166
2167;; The *addsi3_compact is made an insn_and_split and accepts actually
2168;; impossible constraints to make LRA's register elimination work well on SH.
2169;; The problem is that LRA expects something like
2170;;    (set rA (plus rB (const_int N)))
2171;; to work.  We can do that, but we have to split out an additional reg-reg
2172;; copy or constant load before the actual add insn.
2173;; Use u constraint for that case to avoid the invalid value in the stack
2174;; pointer.
2175;; This also results in better code when LRA is not used.  However, we have
2176;; to use different sets of patterns and the order of these patterns is
2177;; important.
2178;; In some cases the constant zero might end up in operands[2] of the
2179;; patterns.  We have to accept that and convert it into a reg-reg move.
2180(define_insn_and_split "*addsi3_compact_lra"
2181  [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u")
2182	(plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r")
2183		 (match_operand:SI 2 "arith_or_int_operand" "rI08,rn")))]
2184  "TARGET_SH1 && sh_lra_p ()
2185   && (! reg_overlap_mentioned_p (operands[0], operands[1])
2186       || arith_operand (operands[2], SImode))"
2187  "@
2188	add	%2,%0
2189	#"
2190  "&& reload_completed
2191   && ! reg_overlap_mentioned_p (operands[0], operands[1])"
2192  [(set (match_dup 0) (match_dup 2))
2193   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
2194{
2195  /* Prefer 'mov r0,r1; add #imm8,r1' over 'mov #imm8,r1; add r0,r1'  */
2196  if (satisfies_constraint_I08 (operands[2]))
2197    std::swap (operands[1], operands[2]);
2198}
2199  [(set_attr "type" "arith")])
2200
2201(define_insn_and_split "addsi3_scr"
2202  [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u,&u")
2203	(plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r,r")
2204		 (match_operand:SI 2 "arith_or_int_operand" "rI08,r,n")))
2205   (clobber (match_scratch:SI 3 "=X,X,&u"))]
2206  "TARGET_SH1"
2207  "@
2208	add	%2,%0
2209	#
2210	#"
2211  "&& reload_completed"
2212  [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
2213{
2214  if (operands[2] == const0_rtx)
2215    {
2216      emit_move_insn (operands[0], operands[1]);
2217      DONE;
2218    }
2219
2220  if (CONST_INT_P (operands[2]) && !satisfies_constraint_I08 (operands[2]))
2221    {
2222      if (reg_overlap_mentioned_p (operands[0], operands[1]))
2223	{
2224	  emit_move_insn (operands[3], operands[2]);
2225	  emit_move_insn (operands[0], operands[1]);
2226	  operands[2] = operands[3];
2227	}
2228      else
2229	{
2230	  emit_move_insn (operands[0], operands[2]);
2231	  operands[2] = operands[1];
2232	}
2233    }
2234  else if (!reg_overlap_mentioned_p (operands[0], operands[1]))
2235    {
2236      if (!reg_overlap_mentioned_p (operands[0], operands[2]))
2237	emit_move_insn (operands[0], operands[1]);
2238      else
2239	operands[2] = operands[1];
2240    }
2241}
2242  [(set_attr "type" "arith")])
2243
2244;; Old reload might generate add insns directly (not through the expander) for
2245;; address register calculations when reloading, in which case it won't try
2246;; the addsi_scr pattern.  Because reload will sometimes try to validate
2247;; the generated insns and their constraints, this pattern must be
2248;; recognizable during and after reload.  However, when reload generates
2249;; address register calculations for the stack pointer, we don't allow this
2250;; pattern.  This will make reload prefer using indexed @(reg + reg) address
2251;; modes when the displacement of a @(disp + reg) doesn't fit.
2252(define_insn_and_split "*addsi3"
2253  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2254	(plus:SI (match_operand:SI 1 "arith_reg_operand" "r")
2255		 (match_operand:SI 2 "arith_or_int_operand" "rn")))]
2256  "TARGET_SH1 && !sh_lra_p ()
2257   && (reload_completed || reload_in_progress)
2258   && !reg_overlap_mentioned_p (operands[0], operands[1])
2259   && (!reload_in_progress
2260       || ((!REG_P (operands[1]) || REGNO (operands[1]) != SP_REG)
2261	   && (!REG_P (operands[2]) || REGNO (operands[2]) != SP_REG)))"
2262  "#"
2263  "&& 1"
2264  [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
2265{
2266  if (operands[2] == const0_rtx)
2267    {
2268      emit_move_insn (operands[0], operands[1]);
2269      DONE;
2270    }
2271
2272  if (CONST_INT_P (operands[2]))
2273    {
2274      if (satisfies_constraint_I08 (operands[2]))
2275	emit_move_insn (operands[0], operands[1]);
2276      else
2277	{
2278	  emit_move_insn (operands[0], operands[2]);
2279	  operands[2] = operands[1];
2280	}
2281    }
2282  else if (!reg_overlap_mentioned_p (operands[0], operands[2]))
2283    emit_move_insn (operands[0], operands[1]);
2284  else
2285    operands[2] = operands[1];
2286})
2287
2288(define_insn_and_split "*addsi3"
2289  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
2290	(plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r")
2291		 (match_operand:SI 2 "arith_operand" "rI08,Z")))]
2292  "TARGET_SH1 && !sh_lra_p ()"
2293  "@
2294	add	%2,%0
2295	#"
2296  "&& operands[2] == const0_rtx"
2297  [(set (match_dup 0) (match_dup 1))]
2298{
2299}
2300  [(set_attr "type" "arith")])
2301
2302;; -------------------------------------------------------------------------
2303;; Subtraction instructions
2304;; -------------------------------------------------------------------------
2305
2306(define_expand "subdi3"
2307  [(set (match_operand:DI 0 "arith_reg_operand" "")
2308	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
2309		  (match_operand:DI 2 "arith_reg_operand" "")))]
2310  ""
2311{
2312  if (TARGET_SH1)
2313    {
2314      operands[1] = force_reg (DImode, operands[1]);
2315      emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
2316      DONE;
2317    }
2318})
2319
2320(define_insn "*subdi3_media"
2321  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2322	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2323		  (match_operand:DI 2 "arith_reg_operand" "r")))]
2324  "TARGET_SHMEDIA"
2325  "sub	%N1, %2, %0"
2326  [(set_attr "type" "arith_media")])
2327  
2328(define_insn "subdisi3_media"
2329  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
2330	(minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2331		  (match_operand:DI 2 "arith_reg_operand" "r")))]
2332  "TARGET_SHMEDIA"
2333  "sub.l	%N1, %2, %0"
2334  [(set_attr "type" "arith_media")
2335   (set_attr "highpart" "ignore")])
2336
2337(define_insn_and_split "subdi3_compact"
2338  [(set (match_operand:DI 0 "arith_reg_dest")
2339	(minus:DI (match_operand:DI 1 "arith_reg_operand")
2340		 (match_operand:DI 2 "arith_reg_operand")))
2341   (clobber (reg:SI T_REG))]
2342  "TARGET_SH1"
2343  "#"
2344  "&& can_create_pseudo_p ()"
2345  [(const_int 0)]
2346{
2347  emit_insn (gen_clrt ());
2348  emit_insn (gen_subc (gen_lowpart (SImode, operands[0]),
2349		       gen_lowpart (SImode, operands[1]),
2350		       gen_lowpart (SImode, operands[2])));
2351  emit_insn (gen_subc (gen_highpart (SImode, operands[0]),
2352		       gen_highpart (SImode, operands[1]),
2353		       gen_highpart (SImode, operands[2])));
2354  DONE;
2355})
2356
2357(define_insn "subc"
2358  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2359	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2360			    (match_operand:SI 2 "arith_reg_operand" "r"))
2361		  (reg:SI T_REG)))
2362   (set (reg:SI T_REG)
2363	(gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
2364			  (reg:SI T_REG))
2365		(match_dup 1)))]
2366  "TARGET_SH1"
2367  "subc	%2,%0"
2368  [(set_attr "type" "arith")])
2369
2370;; A simplified version of the subc insn, where the exact value of the
2371;; T bit doesn't matter.  This is easier for combine to pick up.
2372;; We allow a reg or 0 for one of the operands in order to be able to
2373;; do 'reg - T' sequences.  Reload will load the constant 0 into the reg
2374;; as needed.
2375(define_insn_and_split "*subc"
2376  [(set (match_operand:SI 0 "arith_reg_dest")
2377	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand")
2378			    (match_operand:SI 2 "arith_reg_or_0_operand"))
2379		  (match_operand 3 "treg_set_expr")))
2380   (clobber (reg:SI T_REG))]
2381  "TARGET_SH1 && can_create_pseudo_p ()"
2382  "#"
2383  "&& 1"
2384  [(const_int 0)]
2385{
2386  sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn);
2387  if (ti.has_trailing_nott ())
2388    {
2389      if (operands[2] == const0_rtx)
2390	{
2391	  /* op1 - (1 - T) = op1 - 1 + T = op1 + (-1) + T  */
2392	  remove_insn (ti.trailing_nott ());
2393	  emit_insn (gen_addc (operands[0], operands[1],
2394			       force_reg (SImode, GEN_INT (-1))));
2395	  DONE;
2396	}
2397      else if (!TARGET_SH2A)
2398	{
2399	  /* op1 - op2 - (1 - T) = op1 + (0 - op2 - 1) + T = op1 + ~op2 + T
2400	     On SH2A keep the nott insn, because nott-subc sequence doesn't
2401	     mutate the inputs.  */
2402	  remove_insn (ti.trailing_nott ());
2403	  rtx tmp = gen_reg_rtx (SImode);
2404	  emit_insn (gen_one_cmplsi2 (tmp, operands[2]));
2405	  emit_insn (gen_addc (operands[0], operands[1], tmp));
2406	  DONE;
2407	}
2408    }
2409
2410  emit_insn (gen_subc (operands[0], operands[1],
2411		       force_reg (SImode, operands[2])));
2412  DONE;
2413})
2414
2415;; Convert reg - T - reg = reg - reg - T
2416(define_insn_and_split "*subc"
2417  [(set (match_operand:SI 0 "arith_reg_dest")
2418	(minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand")
2419			    (match_operand 2 "treg_set_expr"))
2420		  (match_operand:SI 3 "arith_reg_operand")))
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) (match_dup 3))
2427			     (match_dup 2)))
2428	      (clobber (reg:SI T_REG))])])
2429
2430;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
2431;; better, if the sett insn can be done early.
2432;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
2433(define_insn_and_split "*subc"
2434  [(set (match_operand:SI 0 "arith_reg_dest" "")
2435	(plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
2436		 (match_operand:SI 2 "arith_reg_operand" "")))
2437   (clobber (reg:SI T_REG))]
2438  "TARGET_SH1 && can_create_pseudo_p ()"
2439  "#"
2440  "&& 1"
2441  [(parallel [(set (match_dup 0)
2442		   (minus:SI (minus:SI (match_dup 2) (match_dup 1))
2443			     (const_int 1)))
2444	      (clobber (reg:SI T_REG))])])
2445
2446;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
2447;; If the 0 constant can be CSE-ed, this becomes a one instruction
2448;; operation, as opposed to sequences such as
2449;;	movt	r2
2450;;	sub	r2,r3
2451;;
2452;; Even if the constant is not CSE-ed, a sequence such as
2453;;	mov	#0,r2
2454;;	subc	r2,r3
2455;; can be scheduled much better since the load of the constant can be
2456;; done earlier, before any comparison insns that store the result in
2457;; the T bit.
2458;; However, avoid things like 'reg - 1', which would expand into a
2459;; 3 insn sequence, instead of add #imm8.
2460(define_insn_and_split "*subc"
2461  [(set (match_operand:SI 0 "arith_reg_dest" "")
2462	(minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2463		  (match_operand 2 "treg_set_expr_not_const01")))
2464   (clobber (reg:SI T_REG))]
2465  "TARGET_SH1 && can_create_pseudo_p ()"
2466  "#"
2467  "&& 1"
2468  [(parallel [(set (match_dup 0)
2469		   (minus:SI (minus:SI (match_dup 1) (const_int 0))
2470			     (match_dup 2)))
2471	      (clobber (reg:SI T_REG))])])
2472
2473;; Convert
2474;;   (1 - T) - op2 = 1 - op2 - T
2475(define_insn_and_split "*subc_negt_reg"
2476  [(set (match_operand:SI 0 "arith_reg_dest")
2477	(minus:SI (match_operand 1 "treg_set_expr_not_const01")
2478		  (match_operand:SI 2 "arith_reg_operand")))
2479   (clobber (reg:SI T_REG))]
2480  "TARGET_SH1 && can_create_pseudo_p ()"
2481  "#"
2482  "&& 1"
2483  [(const_int 0)]
2484{
2485  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
2486  if (ti.remove_trailing_nott ())
2487    {
2488      /* (1 - T) - op2 = 1 - op2 - T  */
2489      emit_insn (gen_subc (operands[0],
2490			   force_reg (SImode, GEN_INT (1)), operands[2]));
2491    }
2492  else
2493    {
2494      /* T - op2: use movt,sub sequence.  */
2495      rtx tmp = gen_reg_rtx (SImode);
2496      emit_insn (gen_movt (tmp, get_t_reg_rtx ()));
2497      emit_insn (gen_subsi3 (operands[0], tmp, operands[2]));
2498    }
2499  DONE;
2500})
2501
2502;; Convert
2503;;   op1 - (1 - T) + op3 = op1 - 1 + T + op3
2504;;   (op1 - T) + op3 = op1 - (-op3) - T
2505(define_insn_and_split "*subc_negreg_t"
2506  [(set (match_operand:SI 0 "arith_reg_dest")
2507	(plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand")
2508			   (match_operand 2 "treg_set_expr"))
2509		 (match_operand:SI 3 "arith_reg_operand")))
2510   (clobber (reg:SI T_REG))]
2511  "TARGET_SH1 && can_create_pseudo_p ()"
2512  "#"
2513  "&& 1"
2514  [(const_int 0)]
2515{
2516  sh_treg_insns ti = sh_split_treg_set_expr (operands[2], curr_insn);
2517  if (ti.remove_trailing_nott ())
2518    {
2519      /* op1 - (1 - T) + op3 = (op1 - 1) + op3 + T  */
2520      rtx tmp = gen_reg_rtx (SImode);
2521      emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (-1)));
2522      emit_insn (gen_addc (operands[0], tmp, operands[3]));
2523    }
2524  else
2525    {
2526      /* (op1 - T) + op3' = 'op1 - (-op3) - T  */
2527      rtx tmp = gen_reg_rtx (SImode);
2528      emit_insn (gen_negsi2 (tmp, operands[3]));
2529      emit_insn (gen_subc (operands[0], operands[1], tmp));
2530    }
2531  DONE;
2532})
2533
2534(define_insn "*subsi3_internal"
2535  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2536	(minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2537		  (match_operand:SI 2 "arith_reg_operand" "r")))]
2538  "TARGET_SH1"
2539  "sub	%2,%0"
2540  [(set_attr "type" "arith")])
2541
2542(define_insn_and_split "*subsi3_media"
2543  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2544	(minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2545		  (match_operand:SI 2 "extend_reg_operand" "r")))]
2546  "TARGET_SHMEDIA
2547   && (operands[1] != constm1_rtx
2548       || (GET_CODE (operands[2]) != TRUNCATE
2549	   && GET_CODE (operands[2]) != SUBREG))"
2550  "sub.l	%N1, %2, %0"
2551  "operands[1] == constm1_rtx"
2552  [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2553  ""
2554  [(set_attr "type" "arith_media")
2555   (set_attr "highpart" "ignore")])
2556
2557(define_split
2558  [(set (match_operand:SI 0 "arith_reg_dest" "")
2559	(zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2560						       "general_extend_operand"
2561						       "") 0)) 0)))]
2562  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2563  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2564   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2565  "")
2566
2567(define_split
2568  [(set (match_operand:SI 0 "arith_reg_dest" "")
2569	(zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2570						       "general_extend_operand"
2571						       "") 0)) 3)))]
2572  "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
2573  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2574   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2575  "")
2576
2577;; Convert
2578;;	constant - reg
2579;; to
2580;;	neg reg
2581;;	add reg, #const
2582;; since this will sometimes save one instruction.
2583;; Otherwise we might get a sequence like
2584;;	mov #const, rY
2585;;	sub rY, rX
2586;;	mov rX, rY
2587;; if the source and dest regs are the same.
2588(define_expand "subsi3"
2589  [(set (match_operand:SI 0 "arith_reg_operand" "")
2590	(minus:SI (match_operand:SI 1 "arith_operand" "")
2591		  (match_operand:SI 2 "arith_reg_operand" "")))]
2592  ""
2593{
2594  if (TARGET_SH1 && CONST_INT_P (operands[1]))
2595    {
2596      emit_insn (gen_negsi2 (operands[0], operands[2]));
2597      emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2598      DONE;
2599    }
2600  if (TARGET_SHMEDIA)
2601    {
2602      if (!can_create_pseudo_p ()
2603	  && ! arith_reg_or_0_operand (operands[1], SImode))
2604	FAIL;
2605      if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2606	operands[1] = force_reg (SImode, operands[1]);
2607    }
2608})
2609
2610;; -------------------------------------------------------------------------
2611;; Division instructions
2612;; -------------------------------------------------------------------------
2613
2614;; We take advantage of the library routines which don't clobber as many
2615;; registers as a normal function call would.
2616
2617;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2618;; also has an effect on the register that holds the address of the sfunc.
2619;; To make this work, we have an extra dummy insn that shows the use
2620;; of this register for reorg.
2621
2622(define_insn "use_sfunc_addr"
2623  [(set (reg:SI PR_REG)
2624	(unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2625  "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2626  ""
2627  [(set_attr "length" "0")])
2628
2629(define_insn "udivsi3_sh2a"
2630  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2631	(udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2632		(match_operand:SI 2 "arith_reg_operand" "z")))]
2633  "TARGET_SH2A"
2634  "divu	%2,%1"
2635  [(set_attr "type" "arith")
2636   (set_attr "in_delay_slot" "no")])
2637
2638;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2639;; hard register 0.  If we used hard register 0, then the next instruction
2640;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg
2641;; gets allocated to a stack slot that needs its address reloaded, then
2642;; there is nothing to prevent reload from using r0 to reload the address.
2643;; This reload would clobber the value in r0 we are trying to store.
2644;; If we let reload allocate r0, then this problem can never happen.
2645(define_insn "udivsi3_i1"
2646  [(set (match_operand:SI 0 "register_operand" "=z,z")
2647	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2648   (clobber (reg:SI T_REG))
2649   (clobber (reg:SI PR_REG))
2650   (clobber (reg:SI R1_REG))
2651   (clobber (reg:SI R4_REG))
2652   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
2653   (use (match_operand 2 "" "Z,Ccl"))]
2654  "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2655  "@
2656	jsr	@%1%#
2657	bsrf	%1\n%O2:%#"
2658  [(set_attr "type" "sfunc")
2659   (set_attr "needs_delay_slot" "yes")])
2660
2661; Since shmedia-nofpu code could be linked against shcompact code, and
2662; the udivsi3 libcall has the same name, we must consider all registers
2663; clobbered that are in the union of the registers clobbered by the
2664; shmedia and the shcompact implementation.  Note, if the shcompact
2665; implementation actually used shcompact code, we'd need to clobber
2666; also r23 and fr23.
2667(define_insn "udivsi3_i1_media"
2668  [(set (match_operand:SI 0 "register_operand" "=z")
2669	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2670   (clobber (reg:SI T_MEDIA_REG))
2671   (clobber (reg:SI PR_MEDIA_REG))
2672   (clobber (reg:SI R20_REG))
2673   (clobber (reg:SI R21_REG))
2674   (clobber (reg:SI R22_REG))
2675   (clobber (reg:DI TR0_REG))
2676   (clobber (reg:DI TR1_REG))
2677   (clobber (reg:DI TR2_REG))
2678   (use (match_operand 1 "target_reg_operand" "b"))]
2679  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2680  "blink	%1, r18"
2681  [(set_attr "type" "sfunc")
2682   (set_attr "needs_delay_slot" "yes")])
2683
2684(define_expand "udivsi3_i4_media"
2685  [(set (match_dup 3)
2686	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2687   (set (match_dup 4)
2688	(zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2689   (set (match_dup 5) (float:DF (match_dup 3)))
2690   (set (match_dup 6) (float:DF (match_dup 4)))
2691   (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2692   (set (match_dup 8) (fix:DI (match_dup 7)))
2693   (set (match_operand:SI 0 "register_operand" "")
2694	(truncate:SI (match_dup 8)))]
2695  "TARGET_SHMEDIA_FPU"
2696{
2697  operands[3] = gen_reg_rtx (DImode);
2698  operands[4] = gen_reg_rtx (DImode);
2699  operands[5] = gen_reg_rtx (DFmode);
2700  operands[6] = gen_reg_rtx (DFmode);
2701  operands[7] = gen_reg_rtx (DFmode);
2702  operands[8] = gen_reg_rtx (DImode);
2703})
2704
2705(define_insn "udivsi3_i4"
2706  [(set (match_operand:SI 0 "register_operand" "=y,y")
2707	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2708   (clobber (reg:SI T_REG))
2709   (clobber (reg:SI PR_REG))
2710   (clobber (reg:DF DR0_REG))
2711   (clobber (reg:DF DR2_REG))
2712   (clobber (reg:DF DR4_REG))
2713   (clobber (reg:SI R0_REG))
2714   (clobber (reg:SI R1_REG))
2715   (clobber (reg:SI R4_REG))
2716   (clobber (reg:SI R5_REG))
2717   (clobber (reg:SI FPSCR_STAT_REG))
2718   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
2719   (use (match_operand 2 "" "Z,Ccl"))
2720   (use (reg:SI FPSCR_MODES_REG))]
2721  "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2722  "@
2723	jsr	@%1%#
2724	bsrf	%1\n%O2:%#"
2725  [(set_attr "type" "sfunc")
2726   (set_attr "fp_mode" "double")
2727   (set_attr "needs_delay_slot" "yes")])
2728
2729(define_insn "udivsi3_i4_single"
2730  [(set (match_operand:SI 0 "register_operand" "=y,y")
2731	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2732   (clobber (reg:SI T_REG))
2733   (clobber (reg:SI PR_REG))
2734   (clobber (reg:DF DR0_REG))
2735   (clobber (reg:DF DR2_REG))
2736   (clobber (reg:DF DR4_REG))
2737   (clobber (reg:SI R0_REG))
2738   (clobber (reg:SI R1_REG))
2739   (clobber (reg:SI R4_REG))
2740   (clobber (reg:SI R5_REG))
2741   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
2742   (use (match_operand 2 "" "Z,Ccl"))]
2743  "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2744   && TARGET_FPU_SINGLE"
2745  "@
2746	jsr	@%1%#
2747	bsrf	%1\n%O2:%#"
2748  [(set_attr "type" "sfunc")
2749   (set_attr "needs_delay_slot" "yes")])
2750
2751(define_insn "udivsi3_i4_int"
2752  [(set (match_operand:SI 0 "register_operand" "=z")
2753	(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2754   (clobber (reg:SI T_REG))
2755   (clobber (reg:SI R1_REG))
2756   (clobber (reg:SI PR_REG))
2757   (clobber (reg:SI MACH_REG))
2758   (clobber (reg:SI MACL_REG))
2759   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2760  "TARGET_SH1"
2761  "jsr	@%1%#"
2762  [(set_attr "type" "sfunc")
2763   (set_attr "needs_delay_slot" "yes")])
2764
2765
2766(define_expand "udivsi3"
2767  [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2768   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2769   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2770   (parallel [(set (match_operand:SI 0 "register_operand" "")
2771		   (udiv:SI (reg:SI R4_REG)
2772			    (reg:SI R5_REG)))
2773	      (clobber (reg:SI T_REG))
2774	      (clobber (reg:SI PR_REG))
2775	      (clobber (reg:SI R4_REG))
2776	      (use (match_dup 3))])]
2777  ""
2778{
2779  rtx last;
2780
2781  operands[3] = gen_reg_rtx (Pmode);
2782  /* Emit the move of the address to a pseudo outside of the libcall.  */
2783  if (TARGET_DIVIDE_CALL_TABLE)
2784    {
2785      /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2786	 that causes problems when the divide code is supposed to come from a
2787	 separate library.  Division by zero is undefined, so dividing 1 can be
2788	 implemented by comparing with the divisor.  */
2789      if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2790	{
2791	  rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2792	  emit_insn (gen_cstoresi4 (operands[0], test,
2793				    operands[1], operands[2]));
2794	  DONE;
2795	}
2796      else if (operands[2] == const0_rtx)
2797	{
2798	  emit_move_insn (operands[0], operands[2]);
2799	  DONE;
2800	}
2801      function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2802      last = gen_udivsi3_i4_int (operands[0], operands[3]);
2803    }
2804  else if (TARGET_DIVIDE_CALL_FP)
2805    {
2806      rtx lab = function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC).lab;
2807      if (TARGET_FPU_SINGLE)
2808	last = gen_udivsi3_i4_single (operands[0], operands[3], lab);
2809      else
2810	last = gen_udivsi3_i4 (operands[0], operands[3], lab);
2811    }
2812  else if (TARGET_SHMEDIA_FPU)
2813    {
2814      operands[1] = force_reg (SImode, operands[1]);
2815      operands[2] = force_reg (SImode, operands[2]);
2816      emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2817      DONE;
2818    }
2819  else if (TARGET_SH2A)
2820    {
2821      operands[1] = force_reg (SImode, operands[1]);
2822      operands[2] = force_reg (SImode, operands[2]);
2823      emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2824      DONE;
2825    }
2826  else if (TARGET_SH5)
2827    {
2828      function_symbol (operands[3],
2829		       TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2830		       SFUNC_STATIC);
2831
2832      if (TARGET_SHMEDIA)
2833	last = gen_udivsi3_i1_media (operands[0], operands[3]);
2834      else if (TARGET_FPU_ANY)
2835	last = gen_udivsi3_i4_single (operands[0], operands[3], const0_rtx);
2836      else
2837	last = gen_udivsi3_i1 (operands[0], operands[3], const0_rtx);
2838    }
2839  else
2840    {
2841      rtx lab = function_symbol (operands[3], "__udivsi3", SFUNC_STATIC).lab;
2842      last = gen_udivsi3_i1 (operands[0], operands[3], lab);
2843    }
2844  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2845  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2846  emit_insn (last);
2847  DONE;
2848})
2849
2850(define_insn "divsi3_sh2a"
2851  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2852	(div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2853		(match_operand:SI 2 "arith_reg_operand" "z")))]
2854  "TARGET_SH2A"
2855  "divs	%2,%1"
2856  [(set_attr "type" "arith")
2857   (set_attr "in_delay_slot" "no")])
2858
2859(define_insn "divsi3_i1"
2860  [(set (match_operand:SI 0 "register_operand" "=z")
2861	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2862   (clobber (reg:SI T_REG))
2863   (clobber (reg:SI PR_REG))
2864   (clobber (reg:SI R1_REG))
2865   (clobber (reg:SI R2_REG))
2866   (clobber (reg:SI R3_REG))
2867   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2868  "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2869  "jsr	@%1%#"
2870  [(set_attr "type" "sfunc")
2871   (set_attr "needs_delay_slot" "yes")])
2872
2873(define_insn "divsi3_i1_media"
2874  [(set (match_operand:SI 0 "register_operand" "=z")
2875	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2876   (clobber (reg:SI T_MEDIA_REG))
2877   (clobber (reg:SI PR_MEDIA_REG))
2878   (clobber (reg:SI R1_REG))
2879   (clobber (reg:SI R20_REG))
2880   (clobber (reg:SI R21_REG))
2881   (clobber (reg:SI TR0_REG))
2882   (use (match_operand 1 "target_reg_operand" "b"))]
2883  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2884  "blink	%1, r18"
2885  [(set_attr "type" "sfunc")])
2886
2887(define_insn "divsi3_media_2"
2888  [(set (match_operand:SI 0 "register_operand" "=z")
2889	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2890   (clobber (reg:SI T_MEDIA_REG))
2891   (clobber (reg:SI PR_MEDIA_REG))
2892   (clobber (reg:SI R1_REG))
2893   (clobber (reg:SI R21_REG))
2894   (clobber (reg:SI TR0_REG))
2895   (use (reg:SI R20_REG))
2896   (use (match_operand 1 "target_reg_operand" "b"))]
2897  "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2898  "blink	%1, r18"
2899  [(set_attr "type" "sfunc")])
2900
2901;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2902;; hard reg clobbers and data dependencies that we need when we want
2903;; to rematerialize the division into a call.
2904(define_insn_and_split "divsi_inv_call"
2905  [(set (match_operand:SI 0 "register_operand" "=r")
2906	(div:SI (match_operand:SI 1 "register_operand" "r")
2907		(match_operand:SI 2 "register_operand" "r")))
2908   (clobber (reg:SI R4_REG))
2909   (clobber (reg:SI R5_REG))
2910   (clobber (reg:SI T_MEDIA_REG))
2911   (clobber (reg:SI PR_MEDIA_REG))
2912   (clobber (reg:SI R1_REG))
2913   (clobber (reg:SI R21_REG))
2914   (clobber (reg:SI TR0_REG))
2915   (clobber (reg:SI R20_REG))
2916   (use (match_operand:SI 3 "register_operand" "r"))]
2917  "TARGET_SHMEDIA"
2918  "#"
2919  "&& (reload_in_progress || reload_completed)"
2920  [(set (match_dup 0) (match_dup 3))]
2921  ""
2922  [(set_attr "highpart" "must_split")])
2923
2924;; This is the combiner pattern for -mdiv=inv:call .
2925(define_insn_and_split "*divsi_inv_call_combine"
2926  [(set (match_operand:SI 0 "register_operand" "=z")
2927	(div:SI (match_operand:SI 1 "register_operand" "r")
2928		(match_operand:SI 2 "register_operand" "r")))
2929   (clobber (reg:SI R4_REG))
2930   (clobber (reg:SI R5_REG))
2931   (clobber (reg:SI T_MEDIA_REG))
2932   (clobber (reg:SI PR_MEDIA_REG))
2933   (clobber (reg:SI R1_REG))
2934   (clobber (reg:SI R21_REG))
2935   (clobber (reg:SI TR0_REG))
2936   (clobber (reg:SI R20_REG))
2937   (use (unspec:SI [(match_dup 1)
2938		    (match_operand:SI 3 "" "")
2939		    (unspec:SI [(match_operand:SI 4 "" "")
2940				(match_dup 3)
2941				(match_operand:DI 5 "" "")]
2942		     UNSPEC_DIV_INV_M2)
2943		    (match_operand:DI 6 "" "")
2944		    (const_int 0)
2945		    (const_int 0)]
2946	 UNSPEC_DIV_INV_M3))]
2947  "TARGET_SHMEDIA"
2948  "#"
2949  "&& (reload_in_progress || reload_completed)"
2950  [(pc)]
2951{
2952  const char *name = sh_divsi3_libfunc;
2953  enum sh_function_kind kind = SFUNC_GOT;
2954  rtx sym;
2955
2956  emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2957  emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2958  while (TARGET_DIVIDE_INV_CALL2)
2959    {
2960      rtx x = operands[3];
2961
2962      if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2963	break;
2964      x = XVECEXP (x, 0, 0);
2965      name = "__sdivsi3_2";
2966      kind = SFUNC_STATIC;
2967      emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2968      break;
2969    }
2970  sym = function_symbol (NULL, name, kind).sym;
2971  emit_insn (gen_divsi3_media_2 (operands[0], sym));
2972  DONE;
2973}
2974  [(set_attr "highpart" "must_split")])
2975
2976(define_expand "divsi3_i4_media"
2977  [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2978   (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2979   (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2980   (set (match_operand:SI 0 "register_operand" "=r")
2981	(fix:SI (match_dup 5)))]
2982  "TARGET_SHMEDIA_FPU"
2983{
2984  operands[3] = gen_reg_rtx (DFmode);
2985  operands[4] = gen_reg_rtx (DFmode);
2986  operands[5] = gen_reg_rtx (DFmode);
2987})
2988
2989(define_insn "divsi3_i4"
2990  [(set (match_operand:SI 0 "register_operand" "=y,y")
2991	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2992   (clobber (reg:SI PR_REG))
2993   (clobber (reg:DF DR0_REG))
2994   (clobber (reg:DF DR2_REG))
2995   (clobber (reg:SI FPSCR_STAT_REG))
2996   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
2997   (use (match_operand 2 "" "Z,Ccl"))
2998   (use (reg:SI FPSCR_MODES_REG))]
2999  "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
3000  "@
3001	jsr	@%1%#
3002	bsrf	%1\n%O2:%#"
3003  [(set_attr "type" "sfunc")
3004   (set_attr "fp_mode" "double")
3005   (set_attr "needs_delay_slot" "yes")])
3006
3007(define_insn "divsi3_i4_single"
3008  [(set (match_operand:SI 0 "register_operand" "=y,y")
3009	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3010   (clobber (reg:SI PR_REG))
3011   (clobber (reg:DF DR0_REG))
3012   (clobber (reg:DF DR2_REG))
3013   (clobber (reg:SI R2_REG))
3014   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
3015   (use (match_operand 2 "" "Z,Ccl"))]
3016  "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
3017   && TARGET_FPU_SINGLE"
3018  "@
3019	jsr	@%1%#
3020	bsrf	%1\n%O2:%#"
3021  [(set_attr "type" "sfunc")
3022   (set_attr "needs_delay_slot" "yes")])
3023
3024(define_insn "divsi3_i4_int"
3025  [(set (match_operand:SI 0 "register_operand" "=z")
3026	(div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3027   (clobber (reg:SI T_REG))
3028   (clobber (reg:SI PR_REG))
3029   (clobber (reg:SI R1_REG))
3030   (clobber (reg:SI MACH_REG))
3031   (clobber (reg:SI MACL_REG))
3032   (use (match_operand:SI 1 "arith_reg_operand" "r"))]
3033  "TARGET_SH1"
3034  "jsr	@%1%#"
3035  [(set_attr "type" "sfunc")
3036   (set_attr "needs_delay_slot" "yes")])
3037
3038(define_expand "divsi3"
3039  [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
3040   (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3041   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3042   (parallel [(set (match_operand:SI 0 "register_operand" "")
3043		   (div:SI (reg:SI R4_REG)
3044			   (reg:SI R5_REG)))
3045	      (clobber (reg:SI T_REG))
3046	      (clobber (reg:SI PR_REG))
3047	      (clobber (reg:SI R1_REG))
3048	      (clobber (reg:SI R2_REG))
3049	      (clobber (reg:SI R3_REG))
3050	      (use (match_dup 3))])]
3051  ""
3052{
3053  rtx last;
3054
3055  operands[3] = gen_reg_rtx (Pmode);
3056  /* Emit the move of the address to a pseudo outside of the libcall.  */
3057  if (TARGET_DIVIDE_CALL_TABLE)
3058    {
3059      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
3060      last = gen_divsi3_i4_int (operands[0], operands[3]);
3061    }
3062  else if (TARGET_DIVIDE_CALL_FP)
3063    {
3064      rtx lab = function_symbol (operands[3], sh_divsi3_libfunc,
3065				 SFUNC_STATIC).lab;
3066      if (TARGET_FPU_SINGLE)
3067	last = gen_divsi3_i4_single (operands[0], operands[3], lab);
3068      else
3069	last = gen_divsi3_i4 (operands[0], operands[3], lab);
3070    }
3071  else if (TARGET_SH2A)
3072    {
3073      operands[1] = force_reg (SImode, operands[1]);
3074      operands[2] = force_reg (SImode, operands[2]);
3075      emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
3076      DONE;
3077    }
3078  else if (TARGET_DIVIDE_INV)
3079    {
3080      rtx dividend = operands[1];
3081      rtx divisor = operands[2];
3082      rtx tab_base;
3083      rtx nsb_res = gen_reg_rtx (DImode);
3084      rtx norm64 = gen_reg_rtx (DImode);
3085      rtx tab_ix = gen_reg_rtx (DImode);
3086      rtx norm32 = gen_reg_rtx (SImode);
3087      rtx i92 = force_reg (DImode, GEN_INT (92));
3088      rtx scratch0a = gen_reg_rtx (DImode);
3089      rtx scratch0b = gen_reg_rtx (DImode);
3090      rtx inv0 = gen_reg_rtx (SImode);
3091      rtx scratch1a = gen_reg_rtx (DImode);
3092      rtx scratch1b = gen_reg_rtx (DImode);
3093      rtx shift = gen_reg_rtx (DImode);
3094      rtx i2p27, i43;
3095      rtx inv1 = gen_reg_rtx (SImode);
3096      rtx scratch2a = gen_reg_rtx (DImode);
3097      rtx scratch2b = gen_reg_rtx (SImode);
3098      rtx inv2 = gen_reg_rtx (SImode);
3099      rtx scratch3a = gen_reg_rtx (DImode);
3100      rtx scratch3b = gen_reg_rtx (DImode);
3101      rtx scratch3c = gen_reg_rtx (DImode);
3102      rtx scratch3d = gen_reg_rtx (SImode);
3103      rtx scratch3e = gen_reg_rtx (DImode);
3104      rtx result = gen_reg_rtx (SImode);
3105
3106      if (! arith_reg_or_0_operand (dividend, SImode))
3107	dividend = force_reg (SImode, dividend);
3108      if (! arith_reg_operand (divisor, SImode))
3109	divisor = force_reg (SImode, divisor);
3110      if (flag_pic && Pmode != DImode)
3111	{
3112	  tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
3113	  tab_base = gen_datalabel_ref (tab_base);
3114	  tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
3115	}
3116      else
3117	{
3118	  tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
3119	  tab_base = gen_datalabel_ref (tab_base);
3120	  tab_base = force_reg (DImode, tab_base);
3121	}
3122      if (TARGET_DIVIDE_INV20U)
3123	i2p27 = force_reg (DImode, GEN_INT ((unsigned HOST_WIDE_INT)-2 << 27));
3124      else
3125	i2p27 = GEN_INT (0);
3126      if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
3127	i43 = force_reg (DImode, GEN_INT (43));
3128      else
3129	i43 = GEN_INT (0);
3130      emit_insn (gen_nsbdi (nsb_res,
3131			    simplify_gen_subreg (DImode, divisor, SImode, 0)));
3132      emit_insn (gen_ashldi3_media (norm64,
3133				    gen_rtx_SUBREG (DImode, divisor, 0),
3134				    nsb_res));
3135      emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
3136      emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
3137      emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
3138				   inv0, scratch0a, scratch0b,
3139				   scratch1a, scratch1b));
3140      emit_insn (gen_subdi3 (shift, i92, nsb_res));
3141      emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
3142				   scratch2a));
3143      emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
3144				   i2p27, i43,
3145				   scratch3a, scratch3b, scratch3c,
3146				   scratch2a, scratch2b, scratch3d, scratch3e));
3147      if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
3148	emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
3149      else if (TARGET_DIVIDE_INV_FP)
3150	emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
3151				     gen_reg_rtx (SImode), gen_reg_rtx (SImode),
3152				     gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
3153				     gen_reg_rtx (DFmode)));
3154      else
3155	emit_move_insn (operands[0], result);
3156      DONE;
3157    }
3158  else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
3159    {
3160      operands[1] = force_reg (SImode, operands[1]);
3161      operands[2] = force_reg (SImode, operands[2]);
3162      emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
3163      DONE;
3164    }
3165  else if (TARGET_SH5)
3166    {
3167      if (TARGET_DIVIDE_CALL2)
3168	{
3169	  rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
3170	  tab_base = gen_datalabel_ref (tab_base);
3171	  emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
3172	}
3173      if (TARGET_FPU_ANY && TARGET_SH1)
3174	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
3175      else if (TARGET_DIVIDE_CALL2)
3176	function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
3177      else
3178	function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
3179
3180      if (TARGET_SHMEDIA)
3181	last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
3182		(operands[0], operands[3]));
3183      else if (TARGET_FPU_ANY)
3184	last = gen_divsi3_i4_single (operands[0], operands[3], const0_rtx);
3185      else
3186	last = gen_divsi3_i1 (operands[0], operands[3]);
3187    }
3188  else
3189    {
3190      function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
3191      last = gen_divsi3_i1 (operands[0], operands[3]);
3192    }
3193  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
3194  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
3195  emit_insn (last);
3196  DONE;
3197})
3198
3199;; operands: scratch, tab_base, tab_ix
3200;; These are unspecs because we could generate an indexed addressing mode
3201;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
3202;; confuse reload.  See PR27117.
3203(define_insn "divsi_inv_qitable"
3204  [(set (match_operand:DI 0 "register_operand" "=r")
3205	(zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
3206				    (match_operand:DI 2 "register_operand" "r")]
3207			 UNSPEC_DIV_INV_TABLE)))]
3208  "TARGET_SHMEDIA"
3209  "ldx.ub	%1, %2, %0"
3210  [(set_attr "type" "load_media")
3211   (set_attr "highpart" "user")])
3212
3213;; operands: scratch, tab_base, tab_ix
3214(define_insn "divsi_inv_hitable"
3215  [(set (match_operand:DI 0 "register_operand" "=r")
3216	(sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
3217				    (match_operand:DI 2 "register_operand" "r")]
3218			 UNSPEC_DIV_INV_TABLE)))]
3219  "TARGET_SHMEDIA"
3220  "ldx.w	%1, %2, %0"
3221  [(set_attr "type" "load_media")
3222   (set_attr "highpart" "user")])
3223
3224;; operands: inv0, tab_base, tab_ix, norm32
3225;; scratch equiv in sdivsi3_2: r19, r21
3226(define_expand "divsi_inv_m0"
3227  [(set (match_operand:SI 0 "register_operand" "=r")
3228	(unspec:SI [(match_operand:DI 1 "register_operand" "r")
3229		    (match_operand:DI 2 "register_operand" "r")
3230		    (match_operand:SI 3 "register_operand" "r")]
3231	 UNSPEC_DIV_INV_M0))
3232   (clobber (match_operand:DI 4 "register_operand" "=r"))
3233   (clobber (match_operand:DI 5 "register_operand" "=r"))]
3234  "TARGET_SHMEDIA"
3235{
3236/*
3237tab_base: r20
3238tab_ix: r21
3239norm32: r25
3240 ldx.ub r20, r21, r19 // u0.8
3241 shlli r21, 1, r21
3242 muls.l r25, r19, r19 // s2.38
3243 ldx.w r20, r21, r21  // s2.14
3244 shari r19, 24, r19   // truncate to s2.14
3245 sub r21, r19, r19    // some 11 bit inverse in s1.14
3246*/
3247
3248  rtx inv0 = operands[0];
3249  rtx tab_base = operands[1];
3250  rtx tab_ix = operands[2];
3251  rtx norm32 = operands[3];
3252  rtx scratch0 = operands[4];
3253  rtx scratch0_si = gen_lowpart (SImode, scratch0);
3254  rtx scratch1 = operands[5];
3255
3256  emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
3257  emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
3258  emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
3259  emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
3260  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
3261  emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
3262  DONE;
3263})
3264
3265;; operands: inv1, tab_base, tab_ix, norm32
3266(define_insn_and_split "divsi_inv_m1"
3267  [(set (match_operand:SI 0 "register_operand" "=r")
3268	(unspec:SI [(match_operand:DI 1 "register_operand" "r")
3269		    (match_operand:DI 2 "register_operand" "r")
3270		    (match_operand:SI 3 "register_operand" "r")]
3271	 UNSPEC_DIV_INV_M1))
3272   (clobber (match_operand:SI 4 "register_operand" "=r"))
3273   (clobber (match_operand:DI 5 "register_operand" "=r"))
3274   (clobber (match_operand:DI 6 "register_operand" "=r"))
3275   (clobber (match_operand:DI 7 "register_operand" "=r"))
3276   (clobber (match_operand:DI 8 "register_operand" "=r"))]
3277  "TARGET_SHMEDIA"
3278  "#"
3279  "&& !can_create_pseudo_p ()"
3280  [(pc)]
3281{
3282/* inv0: r19
3283 muls.l r19, r19, r18 // u0.28
3284 muls.l r25, r18, r18 // s2.58
3285 shlli r19, 45, r0    // multiply by two and convert to s2.58
3286 sub r0, r18, r18
3287 shari r18, 28, r18   // some 18 bit inverse in s1.30
3288*/
3289
3290  rtx inv1 = operands[0];
3291  rtx tab_base = operands[1];
3292  rtx tab_ix = operands[2];
3293  rtx norm32 = operands[3];
3294  rtx inv0 = operands[4];
3295  rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
3296  rtx scratch0a = operands[5];
3297  rtx scratch0b = operands[6];
3298  rtx scratch0 = operands[7];
3299  rtx scratch1 = operands[8];
3300  rtx scratch1_si = gen_lowpart (SImode, scratch1);
3301
3302  emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
3303			       scratch0a, scratch0b));
3304  emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
3305  emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3306  emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
3307  emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
3308  emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
3309  DONE;
3310})
3311
3312;; operands: inv2, norm32, inv1, i92
3313(define_insn_and_split "divsi_inv_m2"
3314  [(set (match_operand:SI 0 "register_operand" "=r")
3315	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
3316		    (match_operand:SI 2 "register_operand" "r")
3317		    (match_operand:DI 3 "register_operand" "r")]
3318	 UNSPEC_DIV_INV_M2))
3319   (clobber (match_operand:DI 4 "register_operand" "=r"))]
3320  "TARGET_SHMEDIA"
3321  "#"
3322  "&& !can_create_pseudo_p ()"
3323  [(pc)]
3324{
3325/*
3326 muls.l r18, r25, r0  // s2.60
3327 shari r0, 16, r0     // s-16.44
3328  sub
3329 muls.l r0, r18, r19  // s-16.74
3330 shari r19, 30, r19   // s-16.44
3331*/
3332  rtx inv2 = operands[0];
3333  rtx norm32 = operands[1];
3334  rtx inv1 = operands[2];
3335  rtx i92 = operands[3];
3336  rtx scratch0 = operands[4];
3337  rtx scratch0_si = gen_lowpart (SImode, scratch0);
3338
3339  emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
3340  emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
3341  emit_insn (gen_subdi3 (scratch0, i92, scratch0));
3342  emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
3343  emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
3344  DONE;
3345})
3346
3347(define_insn_and_split "divsi_inv_m3"
3348  [(set (match_operand:SI 0 "register_operand" "=r")
3349	(unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3350		    (match_operand:SI 2 "register_operand" "r")
3351		    (match_operand:SI 3 "register_operand" "r")
3352		    (match_operand:DI 4 "register_operand" "r")
3353		    (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
3354		    (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
3355	 UNSPEC_DIV_INV_M3))
3356   (clobber (match_operand:DI 7 "register_operand" "=r"))
3357   (clobber (match_operand:DI 8 "register_operand" "=r"))
3358   (clobber (match_operand:DI 9 "register_operand" "=r"))
3359   (clobber (match_operand:DI 10 "register_operand" "=r"))
3360   (clobber (match_operand:SI 11 "register_operand" "=r"))
3361   (clobber (match_operand:SI 12 "register_operand" "=r"))
3362   (clobber (match_operand:DI 13 "register_operand" "=r"))]
3363  "TARGET_SHMEDIA"
3364  "#"
3365  "&& !can_create_pseudo_p ()"
3366  [(pc)]
3367{
3368/*
3369  r0: result  r1: shift  r4: dividend  r18: inv1  r19: inv2
3370  r0: scratch0  r19: scratch1 r21: scratch2
3371
3372  muls.l r18, r4, r25 // s32.30
3373 muls.l r19, r4, r19  // s15.30
3374 shari r25, 63, r21
3375  shari r19, 14, r19  // s18.-14
3376 sub r25, r19, r0
3377 shard r0, r1, r0
3378 sub r0, r21, r0
3379*/
3380
3381  rtx result = operands[0];
3382  rtx dividend = operands[1];
3383  rtx inv1 = operands[2];
3384  rtx inv2 = operands[3];
3385  rtx shift = operands[4];
3386  rtx scratch0 = operands[7];
3387  rtx scratch1 = operands[8];
3388  rtx scratch2 = operands[9];
3389
3390  if (satisfies_constraint_N (dividend))
3391    {
3392      emit_move_insn (result, dividend);
3393      DONE;
3394    }
3395
3396  emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
3397  emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
3398  emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
3399  emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
3400  emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
3401  emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
3402  emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
3403  DONE;
3404})
3405
3406;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
3407;; inv1: tab_base, tab_ix, norm32
3408;; inv2: norm32, inv1, i92
3409(define_insn_and_split "divsi_inv_m1_3"
3410  [(set (match_operand:SI 0 "register_operand" "=r")
3411	(unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3412		    (unspec:SI [(match_operand:DI 2 "register_operand" "r")
3413				(match_operand:DI 3 "register_operand" "r")
3414				(match_operand:SI 4 "register_operand" "r")]
3415		     UNSPEC_DIV_INV_M1)
3416		    (unspec:SI [(match_dup 4)
3417				(unspec:SI [(match_dup 2)
3418					    (match_dup 3)
3419					    (match_dup 4)] UNSPEC_DIV_INV_M1)
3420				(match_operand:SI 5 "" "")]
3421		     UNSPEC_DIV_INV_M2)
3422		    (match_operand:DI 6 "register_operand" "r")
3423		    (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
3424		    (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
3425	 UNSPEC_DIV_INV_M3))
3426   (clobber (match_operand:DI 9 "register_operand" "=r"))
3427   (clobber (match_operand:DI 10 "register_operand" "=r"))
3428   (clobber (match_operand:DI 11 "register_operand" "=r"))
3429   (clobber (match_operand:DI 12 "register_operand" "=r"))
3430   (clobber (match_operand:SI 13 "register_operand" "=r"))
3431   (clobber (match_operand:SI 14 "register_operand" "=r"))
3432   (clobber (match_operand:DI 15 "register_operand" "=r"))]
3433  "TARGET_SHMEDIA
3434   && (TARGET_DIVIDE_INV_MINLAT
3435       || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3436  "#"
3437  "&& !can_create_pseudo_p ()"
3438  [(pc)]
3439{
3440  rtx result = operands[0];
3441  rtx dividend = operands[1];
3442  rtx tab_base = operands[2];
3443  rtx tab_ix = operands[3];
3444  rtx norm32 = operands[4];
3445  /* rtx i92 = operands[5]; */
3446  rtx shift = operands[6];
3447  rtx i2p27 = operands[7];
3448  rtx i43 = operands[8];
3449  rtx scratch0 = operands[9];
3450  rtx scratch0_si = gen_lowpart (SImode, scratch0);
3451  rtx scratch1 = operands[10];
3452  rtx scratch1_si = gen_lowpart (SImode, scratch1);
3453  rtx scratch2 = operands[11];
3454  rtx scratch3 = operands[12];
3455  rtx scratch4 = operands[13];
3456  rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
3457  rtx scratch5 = operands[14];
3458  rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
3459  rtx scratch6 = operands[15];
3460
3461  emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
3462			       scratch0, scratch1));
3463  /* inv0 == scratch4 */
3464  if (! TARGET_DIVIDE_INV20U)
3465    {
3466      emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
3467      i2p27 = scratch0;
3468      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
3469    }
3470  else
3471    {
3472      emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
3473      emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3474    }
3475  emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
3476  emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
3477  emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
3478  /* inv1 == scratch4 */
3479
3480  if (TARGET_DIVIDE_INV_MINLAT)
3481    {
3482      emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
3483      emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
3484      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
3485      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
3486      emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
3487      emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
3488      emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
3489      emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
3490      emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
3491      emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
3492      emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
3493    }
3494  else
3495    {
3496      rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
3497      /* Use separate scratch regs for nsb and sign to allow scheduling.  */
3498      emit_insn (gen_nsbdi (scratch6,
3499			    simplify_gen_subreg (DImode, dividend, SImode, 0)));
3500      emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
3501      emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
3502      emit_insn (gen_divsi_inv20 (scratch2,
3503				  norm32, scratch4, dividend,
3504				  scratch6, scratch3, i43,
3505				  /* scratch0 may be shared with i2p27.  */
3506				  scratch0, scratch1, scratch5,
3507				  label, label, i2p27));
3508    }
3509  emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
3510  emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
3511  DONE;
3512})
3513
3514(define_insn "divsi_inv20"
3515  [(set (match_operand:DI 0 "register_operand" "=&r")
3516	(unspec:DI [(match_operand:SI 1 "register_operand" "r")
3517		    (match_operand:SI 2 "register_operand" "r")
3518		    (match_operand:SI 3 "register_operand" "r")
3519		    (match_operand:DI 4 "register_operand" "r")
3520		    (match_operand:DI 5 "register_operand" "r")
3521		    (match_operand:DI 6 "register_operand" "r")
3522		    (match_operand:DI 12 "register_operand" "r")
3523		    (match_operand 10 "target_operand" "b")
3524		    (match_operand 11 "immediate_operand" "i")]
3525	 UNSPEC_DIV_INV20))
3526   (clobber (match_operand:DI 7 "register_operand" "=&r"))
3527   (clobber (match_operand:DI 8 "register_operand" "=&r"))
3528   (clobber (match_operand:SI 9 "register_operand" "=r"))]
3529  "TARGET_SHMEDIA
3530   && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3531{
3532/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
3533	     %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
3534	     %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
3535	     %10 label (tr), %11 label (imm)
3536
3537 muls.l inv1, norm32, scratch0  // s2.60
3538  muls.l inv1, dividend, result // s32.30
3539  xor i2p27, result_sign, round_scratch
3540 bge/u dividend_nsb, i43, tr.. (label)
3541 shari scratch0, 16, scratch0   // s-16.44
3542 muls.l sratch0_si, inv1, scratch0 // s-16.74
3543  sub result, round_scratch, result
3544  shari dividend, 14, scratch1   // s19.-14
3545 shari scratch0, 30, scratch0   // s-16.44
3546 muls.l scratch0, scratch1, round_scratch // s15.30
3547label:
3548 sub result, round_scratch, result */
3549
3550  const bool likely = TARGET_DIVIDE_INV20L;
3551  if (likely)
3552    return
3553	       "muls.l	%2, %3, %0"	"\n"
3554	"	xor	%12, %5, %7"	"\n"
3555	"	bge/l	%4, %6, %10"	"\n"
3556	"	muls.l	%2, %1, %8"	"\n"
3557	"	shari	%8, 16, %8"	"\n"
3558	"	muls.l	%8, %2, %8"	"\n"
3559	"	shari	%3, 14, %9"	"\n"
3560	"	shari	%8, 30, %8"	"\n"
3561	"	muls.l	%8, %9, %8"	"\n"
3562	"	sub	%0, %8, %0"	"\n"
3563	"%11:	add	%0, %7, %0";
3564  else
3565    return
3566	       "muls.l	%2, %1, %8"	"\n"
3567	"	muls.l	%2, %3, %0"	"\n"
3568	"	xor	%12, %5, %7"	"\n"
3569	"	bge/u	%4, %6, %10"	"\n"
3570	"	shari	%8, 16, %8"	"\n"
3571	"	muls.l	%8, %2, %8"	"\n"
3572	"	sub	%0, %7, %0"	"\n"
3573	"	shari	%3, 14, %9"	"\n"
3574	"	shari	%8, 30, %8"	"\n"
3575	"	muls.l	%8, %9, %7"	"\n"
3576	"%11:	sub	%0, %7, %0";
3577})
3578
3579(define_insn_and_split "divsi_inv_fp"
3580  [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3581	(div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3582		(match_operand:SI 2 "register_operand" "rf")))
3583   (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3584   (clobber (match_operand:SI 4 "register_operand" "=r"))
3585   (clobber (match_operand:SI 5 "register_operand" "=r"))
3586   (clobber (match_operand:DF 6 "register_operand" "=r"))
3587   (clobber (match_operand:DF 7 "register_operand" "=r"))
3588   (clobber (match_operand:DF 8 "register_operand" "=r"))]
3589  "TARGET_SHMEDIA_FPU"
3590  "#"
3591  "&& (reload_in_progress || reload_completed)"
3592  [(set (match_dup 0) (match_dup 3))]
3593  ""
3594  [(set_attr "highpart" "must_split")])
3595
3596;; If a matching group of divide-by-inverse instructions is in the same
3597;; basic block after gcse & loop optimizations, we want to transform them
3598;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3599(define_insn_and_split "*divsi_inv_fp_combine"
3600  [(set (match_operand:SI 0 "register_operand" "=f")
3601	(div:SI (match_operand:SI 1 "register_operand" "f")
3602		(match_operand:SI 2 "register_operand" "f")))
3603   (use (unspec:SI [(match_dup 1)
3604		    (match_operand:SI 3 "" "")
3605		    (unspec:SI [(match_operand:SI 4 "" "")
3606				(match_dup 3)
3607				(match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3608		    (match_operand:DI 6 "" "")
3609		    (const_int 0)
3610		    (const_int 0)] UNSPEC_DIV_INV_M3))
3611   (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3612   (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3613   (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3614   (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3615   (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3616  "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3617  "#"
3618  "&& 1"
3619  [(set (match_dup 9) (float:DF (match_dup 1)))
3620   (set (match_dup 10) (float:DF (match_dup 2)))
3621   (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3622   (set (match_dup 8)
3623	(fix:SI (match_dup 11)))
3624   (set (match_dup 0) (match_dup 8))]
3625{
3626  if (! fp_arith_reg_operand (operands[1], SImode))
3627    {
3628      emit_move_insn (operands[7], operands[1]);
3629      operands[1] = operands[7];
3630    }
3631  if (! fp_arith_reg_operand (operands[2], SImode))
3632    {
3633      emit_move_insn (operands[8], operands[2]);
3634      operands[2] = operands[8];
3635    }
3636}
3637  [(set_attr "highpart" "must_split")])
3638
3639;; -------------------------------------------------------------------------
3640;; Multiplication instructions
3641;; -------------------------------------------------------------------------
3642
3643(define_insn "umulhisi3_i"
3644  [(set (reg:SI MACL_REG)
3645	(mult:SI (zero_extend:SI
3646		  (match_operand:HI 0 "arith_reg_operand" "r"))
3647		 (zero_extend:SI
3648		  (match_operand:HI 1 "arith_reg_operand" "r"))))]
3649  "TARGET_SH1"
3650  "mulu.w	%1,%0"
3651  [(set_attr "type" "smpy")])
3652
3653(define_insn "mulhisi3_i"
3654  [(set (reg:SI MACL_REG)
3655	(mult:SI (sign_extend:SI
3656		  (match_operand:HI 0 "arith_reg_operand" "r"))
3657		 (sign_extend:SI
3658		  (match_operand:HI 1 "arith_reg_operand" "r"))))]
3659  "TARGET_SH1"
3660  "muls.w	%1,%0"
3661  [(set_attr "type" "smpy")])
3662
3663(define_expand "mulhisi3"
3664  [(set (reg:SI MACL_REG)
3665	(mult:SI (sign_extend:SI
3666		  (match_operand:HI 1 "arith_reg_operand" ""))
3667		 (sign_extend:SI
3668		  (match_operand:HI 2 "arith_reg_operand" ""))))
3669   (set (match_operand:SI 0 "arith_reg_operand" "")
3670	(reg:SI MACL_REG))]
3671  "TARGET_SH1"
3672{
3673  rtx_insn *insn;
3674  rtx macl;
3675
3676  macl = gen_rtx_REG (SImode, MACL_REG);
3677  start_sequence ();
3678  emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3679  insn = get_insns ();  
3680  end_sequence ();
3681  /* expand_binop can't find a suitable code in umul_widen_optab to
3682     make a REG_EQUAL note from, so make one here.
3683     See also smulsi3_highpart.
3684     ??? Alternatively, we could put this at the calling site of expand_binop,
3685     i.e. expand_expr.  */
3686  /* Use emit_libcall_block for loop invariant code motion and to make
3687     a REG_EQUAL note.  */
3688  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3689
3690  DONE;
3691})
3692
3693(define_expand "umulhisi3"
3694  [(set (reg:SI MACL_REG)
3695	(mult:SI (zero_extend:SI
3696		  (match_operand:HI 1 "arith_reg_operand" ""))
3697		 (zero_extend:SI
3698		  (match_operand:HI 2 "arith_reg_operand" ""))))
3699   (set (match_operand:SI 0 "arith_reg_operand" "")
3700	(reg:SI MACL_REG))]
3701  "TARGET_SH1"
3702{
3703  rtx_insn *insn;
3704  rtx macl;
3705
3706  macl = gen_rtx_REG (SImode, MACL_REG);
3707  start_sequence ();
3708  emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3709  insn = get_insns ();  
3710  end_sequence ();
3711  /* expand_binop can't find a suitable code in umul_widen_optab to
3712     make a REG_EQUAL note from, so make one here.
3713     See also smulsi3_highpart.
3714     ??? Alternatively, we could put this at the calling site of expand_binop,
3715     i.e. expand_expr.  */
3716  /* Use emit_libcall_block for loop invariant code motion and to make
3717     a REG_EQUAL note.  */
3718  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3719
3720  DONE;
3721})
3722
3723;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3724;; a call to a routine which clobbers known registers.
3725(define_insn ""
3726  [(set (match_operand:SI 1 "register_operand" "=z")
3727	(mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3728   (clobber (reg:SI MACL_REG))
3729   (clobber (reg:SI T_REG))
3730   (clobber (reg:SI PR_REG))
3731   (clobber (reg:SI R3_REG))
3732   (clobber (reg:SI R2_REG))
3733   (clobber (reg:SI R1_REG))
3734   (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3735  "TARGET_SH1"
3736  "jsr	@%0%#"
3737  [(set_attr "type" "sfunc")
3738   (set_attr "needs_delay_slot" "yes")])
3739
3740(define_expand "mulsi3_call"
3741  [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3742   (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3743   (parallel[(set (match_operand:SI 0 "register_operand" "")
3744		  (mult:SI (reg:SI R4_REG)
3745			   (reg:SI R5_REG)))
3746	     (clobber (reg:SI MACL_REG))
3747	     (clobber (reg:SI T_REG))
3748	     (clobber (reg:SI PR_REG))
3749	     (clobber (reg:SI R3_REG))
3750	     (clobber (reg:SI R2_REG))
3751	     (clobber (reg:SI R1_REG))
3752	     (use (match_operand:SI 3 "register_operand" ""))])]
3753  "TARGET_SH1"
3754  "")
3755
3756(define_insn "mul_r"
3757  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3758	(mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3759		 (match_operand:SI 2 "arith_reg_operand" "z")))]
3760  "TARGET_SH2A"
3761  "mulr	%2,%0"
3762  [(set_attr "type" "dmpy")])
3763
3764(define_insn "mul_l"
3765  [(set (reg:SI MACL_REG)
3766	(mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3767		 (match_operand:SI 1 "arith_reg_operand" "r")))]
3768  "TARGET_SH2"
3769  "mul.l	%1,%0"
3770  [(set_attr "type" "dmpy")])
3771
3772(define_expand "mulsi3"
3773  [(set (reg:SI MACL_REG)
3774	(mult:SI  (match_operand:SI 1 "arith_reg_operand" "")
3775		  (match_operand:SI 2 "arith_reg_operand" "")))
3776   (set (match_operand:SI 0 "arith_reg_operand" "")
3777	(reg:SI MACL_REG))]
3778  "TARGET_SH1"
3779{
3780  if (!TARGET_SH2)
3781    {
3782      /* The address must be set outside the libcall,
3783	 since it goes into a pseudo.  */
3784      rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC).sym;
3785      rtx addr = force_reg (SImode, sym);
3786      rtx insns = gen_mulsi3_call (operands[0], operands[1],
3787				   operands[2], addr);
3788      emit_insn (insns);
3789    }
3790  else
3791    {
3792      rtx macl = gen_rtx_REG (SImode, MACL_REG);
3793
3794      emit_insn (gen_mul_l (operands[1], operands[2]));
3795      /* consec_sets_giv can only recognize the first insn that sets a
3796	 giv as the giv insn.  So we must tag this also with a REG_EQUAL
3797	 note.  */
3798      emit_insn (gen_movsi_i ((operands[0]), macl));
3799    }
3800  DONE;
3801})
3802
3803(define_insn "mulsidi3_i"
3804  [(set (reg:SI MACH_REG)
3805	(truncate:SI
3806	 (lshiftrt:DI
3807	  (mult:DI
3808	   (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3809	   (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3810	  (const_int 32))))
3811   (set (reg:SI MACL_REG)
3812	(mult:SI (match_dup 0)
3813		 (match_dup 1)))]
3814  "TARGET_SH2"
3815  "dmuls.l	%1,%0"
3816  [(set_attr "type" "dmpy")])
3817
3818(define_expand "mulsidi3"
3819  [(set (match_operand:DI 0 "arith_reg_dest" "")
3820	(mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3821		 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3822  "TARGET_SH2 || TARGET_SHMEDIA"
3823{
3824  if (TARGET_SH2)
3825    {
3826      emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3827      DONE;
3828    }
3829})
3830
3831(define_insn "mulsidi3_media"
3832  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3833	(mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3834		 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3835  "TARGET_SHMEDIA"
3836  "muls.l	%1, %2, %0"
3837  [(set_attr "type" "dmpy_media")
3838   (set_attr "highpart" "ignore")])
3839
3840(define_insn_and_split "mulsidi3_compact"
3841  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3842	(mult:DI
3843	 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3844	 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3845   (clobber (reg:SI MACH_REG))
3846   (clobber (reg:SI MACL_REG))]
3847  "TARGET_SH2"
3848  "#"
3849  "&& 1"
3850  [(const_int 0)]
3851{
3852  rtx low_dst = gen_lowpart (SImode, operands[0]);
3853  rtx high_dst = gen_highpart (SImode, operands[0]);
3854
3855  emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3856
3857  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3858  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3859  /* We need something to tag the possible REG_EQUAL notes on to.  */
3860  emit_move_insn (operands[0], operands[0]);
3861  DONE;
3862})
3863
3864(define_insn "umulsidi3_i"
3865  [(set (reg:SI MACH_REG)
3866	(truncate:SI
3867	 (lshiftrt:DI
3868	  (mult:DI
3869	   (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3870	   (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3871	  (const_int 32))))
3872   (set (reg:SI MACL_REG)
3873	(mult:SI (match_dup 0)
3874		 (match_dup 1)))]
3875  "TARGET_SH2"
3876  "dmulu.l	%1,%0"
3877  [(set_attr "type" "dmpy")])
3878
3879(define_expand "umulsidi3"
3880  [(set (match_operand:DI 0 "arith_reg_dest" "")
3881	(mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3882		 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3883  "TARGET_SH2 || TARGET_SHMEDIA"
3884{
3885  if (TARGET_SH2)
3886    {
3887      emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3888      DONE;
3889    }
3890})
3891
3892(define_insn "umulsidi3_media"
3893  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3894	(mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3895		 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3896  "TARGET_SHMEDIA"
3897  "mulu.l	%1, %2, %0"
3898  [(set_attr "type" "dmpy_media")
3899   (set_attr "highpart" "ignore")])
3900
3901(define_insn_and_split "umulsidi3_compact"
3902  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3903	(mult:DI
3904	 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3905	 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3906   (clobber (reg:SI MACH_REG))
3907   (clobber (reg:SI MACL_REG))]
3908  "TARGET_SH2"
3909  "#"
3910  "&& 1"
3911  [(const_int 0)]
3912{
3913  rtx low_dst = gen_lowpart (SImode, operands[0]);
3914  rtx high_dst = gen_highpart (SImode, operands[0]);
3915
3916  emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3917
3918  emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3919  emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3920  /* We need something to tag the possible REG_EQUAL notes on to.  */
3921  emit_move_insn (operands[0], operands[0]);
3922  DONE;
3923})
3924
3925(define_insn "smulsi3_highpart_i"
3926  [(set (reg:SI MACH_REG)
3927	(truncate:SI
3928	 (lshiftrt:DI
3929	  (mult:DI
3930	   (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3931	   (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3932	  (const_int 32))))
3933   (clobber (reg:SI MACL_REG))]
3934  "TARGET_SH2"
3935  "dmuls.l	%1,%0"
3936  [(set_attr "type" "dmpy")])
3937
3938(define_expand "smulsi3_highpart"
3939  [(parallel
3940    [(set (reg:SI MACH_REG)
3941	  (truncate:SI
3942	   (lshiftrt:DI
3943	    (mult:DI
3944	     (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3945	     (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3946	    (const_int 32))))
3947    (clobber (reg:SI MACL_REG))])
3948   (set (match_operand:SI 0 "arith_reg_operand" "")
3949	(reg:SI MACH_REG))]
3950  "TARGET_SH2"
3951{
3952  rtx_insn *insn;
3953  rtx mach;
3954
3955  mach = gen_rtx_REG (SImode, MACH_REG);
3956  start_sequence ();
3957  emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3958  insn = get_insns ();  
3959  end_sequence ();
3960  /* expand_binop can't find a suitable code in mul_highpart_optab to
3961     make a REG_EQUAL note from, so make one here.
3962     See also {,u}mulhisi.
3963     ??? Alternatively, we could put this at the calling site of expand_binop,
3964     i.e. expand_mult_highpart.  */
3965  /* Use emit_libcall_block for loop invariant code motion and to make
3966     a REG_EQUAL note.  */
3967  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3968
3969  DONE;
3970})
3971
3972(define_insn "umulsi3_highpart_i"
3973  [(set (reg:SI MACH_REG)
3974	(truncate:SI
3975	 (lshiftrt:DI
3976	  (mult:DI
3977	   (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3978	   (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3979	  (const_int 32))))
3980   (clobber (reg:SI MACL_REG))]
3981  "TARGET_SH2"
3982  "dmulu.l	%1,%0"
3983  [(set_attr "type" "dmpy")])
3984
3985(define_expand "umulsi3_highpart"
3986  [(parallel
3987    [(set (reg:SI MACH_REG)
3988	  (truncate:SI
3989	   (lshiftrt:DI
3990	    (mult:DI
3991	     (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3992	     (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3993	    (const_int 32))))
3994    (clobber (reg:SI MACL_REG))])
3995   (set (match_operand:SI 0 "arith_reg_operand" "")
3996	(reg:SI MACH_REG))]
3997  "TARGET_SH2"
3998{
3999  rtx_insn *insn;
4000  rtx mach;
4001
4002  mach = gen_rtx_REG (SImode, MACH_REG);
4003  start_sequence ();
4004  emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
4005  insn = get_insns ();  
4006  end_sequence ();
4007  /* Use emit_libcall_block for loop invariant code motion and to make
4008     a REG_EQUAL note.  */
4009  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
4010
4011  DONE;
4012})
4013
4014(define_insn_and_split "muldi3"
4015  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4016	(mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
4017		 (match_operand:DI 2 "arith_reg_operand" "r")))
4018   (clobber (match_scratch:DI 3 "=&r"))
4019   (clobber (match_scratch:DI 4 "=r"))]
4020  "TARGET_SHMEDIA"
4021  "#"
4022  "reload_completed"
4023  [(const_int 0)]
4024{
4025  rtx op3_v2si, op2_v2si;
4026
4027  op3_v2si = operands[3];
4028  if (GET_CODE (op3_v2si) == SIGN_EXTEND)
4029    {
4030      op3_v2si = XEXP (op3_v2si, 0);
4031      op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
4032    }
4033  op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
4034  op2_v2si = operands[2];
4035  if (GET_CODE (op2_v2si) == SIGN_EXTEND)
4036    {
4037      op2_v2si = XEXP (op2_v2si, 0);
4038      op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
4039    }
4040  op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
4041  emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
4042  emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
4043  emit_insn (gen_umulsidi3_media (operands[4],
4044				 sh_gen_truncate (SImode, operands[1], 0),
4045				 sh_gen_truncate (SImode, operands[2], 0)));
4046  emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
4047  emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
4048  emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
4049  emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
4050  DONE;
4051})
4052
4053;; -------------------------------------------------------------------------
4054;; Logical operations
4055;; -------------------------------------------------------------------------
4056
4057(define_expand "andsi3"
4058  [(set (match_operand:SI 0 "arith_reg_operand" "")
4059	(and:SI (match_operand:SI 1 "logical_reg_operand" "")
4060		(match_operand:SI 2 "logical_and_operand" "")))]
4061  ""
4062{
4063  /* If it is possible to turn the and insn into a zero extension
4064     already, redundant zero extensions will be folded, which results
4065     in better code.  
4066     Ideally the splitter of *andsi_compact would be enough, if redundant
4067     zero extensions were detected after the combine pass, which does not
4068     happen at the moment.  */
4069  if (TARGET_SH1)
4070    {
4071      if (satisfies_constraint_Jmb (operands[2]))
4072	{
4073	  emit_insn (gen_zero_extendqisi2 (operands[0],
4074					   gen_lowpart (QImode, operands[1])));
4075	  DONE;
4076	}
4077      else if (satisfies_constraint_Jmw (operands[2]))
4078	{
4079	  emit_insn (gen_zero_extendhisi2 (operands[0],
4080					   gen_lowpart (HImode, operands[1])));
4081	  DONE;
4082	}
4083    }
4084})
4085
4086(define_insn_and_split "*andsi_compact"
4087  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
4088	(and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
4089		(match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
4090  "TARGET_SH1"
4091  "@
4092	extu.b	%1,%0
4093	extu.w	%1,%0
4094	and	%2,%0
4095	and	%2,%0"
4096  "&& 1"
4097 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
4098{
4099  if (satisfies_constraint_Jmb (operands[2]))
4100    operands[1] = gen_lowpart (QImode, operands[1]);
4101  else if (satisfies_constraint_Jmw (operands[2]))
4102    operands[1] = gen_lowpart (HImode, operands[1]);
4103  else
4104    FAIL;
4105}
4106  [(set_attr "type" "arith")])
4107
4108(define_insn "*andsi3_media"
4109  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4110	(and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
4111		(match_operand:SI 2 "logical_operand" "r,I10")))]
4112  "TARGET_SHMEDIA"
4113  "@
4114	and	%1, %2, %0
4115	andi	%1, %2, %0"
4116  [(set_attr "type" "arith_media")])
4117
4118(define_insn "*andsi3_bclr"
4119  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4120	(and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
4121		(match_operand:SI 2 "const_int_operand" "Psz")))]
4122  "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
4123  "bclr	%W2,%0"
4124  [(set_attr "type" "arith")])
4125
4126(define_insn_and_split "anddi3"
4127  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
4128	(and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
4129		(match_operand:DI 2 "and_operand" "r,I10,J16")))]
4130  "TARGET_SHMEDIA"
4131  "@
4132	and	%1, %2, %0
4133	andi	%1, %2, %0
4134	#"
4135  "reload_completed
4136   && ! logical_operand (operands[2], DImode)"
4137  [(const_int 0)]
4138{
4139  if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
4140    emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
4141  else
4142    emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
4143  DONE;
4144}
4145  [(set_attr "type" "arith_media")])
4146
4147(define_insn "andcsi3"
4148  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4149	(and:SI (match_operand:SI 1 "arith_reg_operand" "r")
4150		(not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4151  "TARGET_SHMEDIA"
4152  "andc	%1,%2,%0"
4153  [(set_attr "type" "arith_media")])
4154
4155(define_insn "andcdi3"
4156  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4157	(and:DI (match_operand:DI 1 "arith_reg_operand" "r")
4158		(not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
4159  "TARGET_SHMEDIA"
4160  "andc	%1,%2,%0"
4161  [(set_attr "type" "arith_media")])
4162
4163(define_expand "iorsi3"
4164  [(set (match_operand:SI 0 "arith_reg_operand" "")
4165	(ior:SI (match_operand:SI 1 "logical_reg_operand" "")
4166		(match_operand:SI 2 "logical_operand" "")))]
4167  ""
4168  "")
4169
4170(define_insn "*iorsi3_compact"
4171  [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
4172	(ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
4173		(match_operand:SI 2 "logical_operand" "r,K08")))]
4174  "TARGET_SH1
4175   && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
4176  "or	%2,%0"
4177  [(set_attr "type" "arith")])
4178
4179(define_insn "*iorsi3_media"
4180  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4181	(ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
4182		(match_operand:SI 2 "logical_operand" "r,I10")))]
4183  "TARGET_SHMEDIA"
4184  "@
4185	or	%1, %2, %0
4186	ori	%1, %2, %0"
4187  [(set_attr "type" "arith_media")])
4188
4189(define_insn "*iorsi3_bset"
4190  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4191	(ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
4192	(match_operand:SI 2 "const_int_operand" "Pso")))]
4193  "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
4194  "bset	%V2,%0"
4195  [(set_attr "type" "arith")])
4196
4197(define_insn "iordi3"
4198  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4199	(ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
4200		(match_operand:DI 2 "logical_operand" "r,I10")))]
4201  "TARGET_SHMEDIA"
4202  "@
4203	or	%1, %2, %0
4204	ori	%1, %2, %0"
4205  [(set_attr "type" "arith_media")])
4206
4207(define_insn_and_split "*logical_sidi3"
4208  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4209	(sign_extend:DI (match_operator:SI 3 "logical_operator"
4210			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
4211			   (match_operand:SI 2 "logical_operand" "r,I10")])))]
4212  "TARGET_SHMEDIA"
4213  "#"
4214  "&& reload_completed"
4215  [(set (match_dup 0) (match_dup 3))]
4216{
4217  operands[3]
4218    = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
4219		      simplify_gen_subreg (DImode, operands[1], SImode, 0),
4220		      simplify_gen_subreg (DImode, operands[2], SImode, 0));
4221})
4222
4223(define_insn_and_split "*logical_sidisi3"
4224  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4225	(truncate:SI (sign_extend:DI
4226			(match_operator:SI 3 "logical_operator"
4227			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
4228			   (match_operand:SI 2 "logical_operand" "r,I10")]))))]
4229  "TARGET_SHMEDIA"
4230  "#"
4231  "&& 1"
4232  [(set (match_dup 0) (match_dup 3))])
4233
4234(define_insn_and_split "*logical_sidi3_2"
4235  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4236	(sign_extend:DI (truncate:SI (sign_extend:DI
4237			(match_operator:SI 3 "logical_operator"
4238			  [(match_operand:SI 1 "arith_reg_operand" "%r,r")
4239			   (match_operand:SI 2 "logical_operand" "r,I10")])))))]
4240  "TARGET_SHMEDIA"
4241  "#"
4242  "&& 1"
4243  [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
4244
4245(define_expand "xorsi3"
4246  [(set (match_operand:SI 0 "arith_reg_operand" "")
4247	(xor:SI (match_operand:SI 1 "logical_reg_operand" "")
4248		(match_operand:SI 2 "xor_operand" "")))]
4249  ""
4250  "")
4251
4252(define_insn "*xorsi3_compact"
4253  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
4254	(xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
4255		(match_operand:SI 2 "logical_operand" "K08,r")))]
4256  "TARGET_SH1"
4257  "xor	%2,%0"
4258  [(set_attr "type" "arith")])
4259
4260;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
4261;; of results where one of the inputs is a T bit store.  Notice that this
4262;; pattern must not match during reload.  If reload picks this pattern it
4263;; will be impossible to split it afterwards.
4264(define_insn_and_split "*logical_op_t"
4265  [(set (match_operand:SI 0 "arith_reg_dest")
4266	(match_operator:SI 3 "logical_operator"
4267	  [(match_operand:SI 1 "arith_reg_operand")
4268	   (match_operand:SI 2 "t_reg_operand")]))]
4269  "TARGET_SH1 && can_create_pseudo_p ()"
4270  "#"
4271  "&& 1"
4272  [(set (match_dup 4) (reg:SI T_REG))
4273   (set (match_dup 0) (match_dup 3))]
4274{
4275  operands[4] = gen_reg_rtx (SImode);
4276  operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
4277				operands[1], operands[4]);
4278})
4279
4280(define_insn "*xorsi3_media"
4281  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4282	(xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
4283		(match_operand:SI 2 "xor_operand" "r,I06")))]
4284  "TARGET_SHMEDIA"
4285  "@
4286	xor	%1, %2, %0
4287	xori	%1, %2, %0"
4288  [(set_attr "type" "arith_media")])
4289
4290(define_insn "xordi3"
4291  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4292	(xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
4293		(match_operand:DI 2 "xor_operand" "r,I06")))]
4294  "TARGET_SHMEDIA"
4295  "@
4296	xor	%1, %2, %0
4297	xori	%1, %2, %0"
4298  [(set_attr "type" "arith_media")])
4299
4300;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
4301;; converts 2 * sign extend -> logical op into logical op -> sign extend
4302(define_split
4303  [(set (match_operand:DI 0 "arith_reg_dest" "")
4304	(sign_extend:DI (match_operator 4 "binary_logical_operator"
4305			  [(match_operand 1 "any_register_operand" "")
4306			   (match_operand 2 "any_register_operand" "")])))]
4307  "TARGET_SHMEDIA"
4308  [(set (match_dup 5) (match_dup 4))
4309   (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
4310{
4311  machine_mode inmode = GET_MODE (operands[1]);
4312  int offset = 0;
4313
4314  if (GET_CODE (operands[0]) == SUBREG)
4315    {
4316      offset = SUBREG_BYTE (operands[0]);
4317      operands[0] = SUBREG_REG (operands[0]);
4318    }
4319  gcc_assert (REG_P (operands[0]));
4320  if (TARGET_BIG_ENDIAN)
4321    offset += 8 - GET_MODE_SIZE (inmode);
4322  operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
4323})
4324
4325;; -------------------------------------------------------------------------
4326;; Shifts and rotates
4327;; -------------------------------------------------------------------------
4328
4329;; Let combine see that we can get the MSB and LSB into the T bit
4330;; via shll and shlr.  This allows it to plug it into insns that can have
4331;; the T bit as an input (e.g. addc).
4332;; On SH2A use bld #0,Rn instead of shlr to avoid mutating the input.
4333(define_insn_and_split "*reg_lsb_t"
4334  [(set (reg:SI T_REG)
4335	(and:SI (match_operand:SI 0 "arith_reg_operand")
4336		(const_int 1)))]
4337  "TARGET_SH1 && can_create_pseudo_p ()"
4338  "#"
4339  "&& 1"
4340  [(const_int 0)]
4341{
4342  emit_insn (TARGET_SH2A ? gen_bldsi_reg (operands[0], const0_rtx)
4343			 : gen_shlr (gen_reg_rtx (SImode), operands[0]));
4344})
4345
4346(define_insn_and_split "*reg_msb_t"
4347  [(set (reg:SI T_REG)
4348	(lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
4349		     (const_int 31)))]
4350  "TARGET_SH1 && can_create_pseudo_p ()"
4351  "#"
4352  "&& 1"
4353  [(const_int 0)]
4354{
4355  emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
4356})
4357
4358(define_expand "rotldi3"
4359  [(set (match_operand:DI 0 "arith_reg_dest" "")
4360	(rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
4361		   (match_operand:HI 2 "mextr_bit_offset" "")))]
4362  "TARGET_SHMEDIA"
4363{
4364  if (! mextr_bit_offset (operands[2], HImode))
4365    FAIL;
4366})
4367
4368(define_insn "rotldi3_mextr"
4369  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4370	(rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
4371		   (match_operand:HI 2 "mextr_bit_offset" "i")))]
4372  "TARGET_SHMEDIA"
4373{
4374  static char templ[16];
4375  sprintf (templ, "mextr%d	%%1,%%1,%%0",
4376	   8 - (int) (INTVAL (operands[2]) >> 3));
4377  return templ;
4378}
4379  [(set_attr "type" "arith_media")])
4380
4381(define_expand "rotrdi3"
4382  [(set (match_operand:DI 0 "arith_reg_dest" "")
4383	(rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
4384		     (match_operand:HI 2 "mextr_bit_offset" "")))]
4385  "TARGET_SHMEDIA"
4386{
4387  if (! mextr_bit_offset (operands[2], HImode))
4388    FAIL;
4389})
4390
4391(define_insn "rotrdi3_mextr"
4392  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4393	(rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
4394		     (match_operand:HI 2 "mextr_bit_offset" "i")))]
4395  "TARGET_SHMEDIA"
4396{
4397  static char templ[16];
4398  sprintf (templ, "mextr%d	%%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
4399  return templ;
4400}
4401  [(set_attr "type" "arith_media")])
4402
4403(define_split
4404  [(set (match_operand:DI 0 "arith_reg_dest" "")
4405	(ior:DI (zero_extend:DI (mem:QI (match_operand 1
4406					 "ua_address_operand" "")))
4407		(ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
4408			   (const_int 8))))
4409   (clobber (match_operand:DI 3 "register_operand" ""))]
4410  "TARGET_SHMEDIA"
4411  [(match_dup 4) (match_dup 5)]
4412{
4413  operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
4414		 (operands[3], operands[1]));
4415  operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
4416			      GEN_INT (56), GEN_INT (8));
4417})
4418
4419(define_expand "rotrsi3"
4420  [(set (match_operand:SI 0 "arith_reg_dest")
4421	(rotatert:SI (match_operand:SI 1 "arith_reg_operand")
4422		     (match_operand:SI 2 "const_int_operand")))]
4423  "TARGET_SH1"
4424{
4425  HOST_WIDE_INT ival = INTVAL (operands[2]);
4426  if (ival == 1)
4427    {
4428      emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
4429      DONE;
4430    }
4431
4432  FAIL;
4433})
4434
4435(define_insn "rotrsi3_1"
4436  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4437	(rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4438		     (const_int 1)))
4439   (set (reg:SI T_REG)
4440	(and:SI (match_dup 1) (const_int 1)))]
4441  "TARGET_SH1"
4442  "rotr	%0"
4443  [(set_attr "type" "arith")])
4444
4445;; A slimplified version of rotr for combine.
4446(define_insn "*rotrsi3_1"
4447  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4448	(rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4449		     (const_int 1)))
4450   (clobber (reg:SI T_REG))]
4451  "TARGET_SH1"
4452  "rotr	%0"
4453  [(set_attr "type" "arith")])
4454
4455(define_insn "rotlsi3_1"
4456  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4457	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4458		   (const_int 1)))
4459   (set (reg:SI T_REG)
4460	(lshiftrt:SI (match_dup 1) (const_int 31)))]
4461  "TARGET_SH1"
4462  "rotl	%0"
4463  [(set_attr "type" "arith")])
4464
4465;; A simplified version of rotl for combine.
4466(define_insn "*rotlsi3_1"
4467  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4468	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4469		   (const_int 1)))
4470   (clobber (reg:SI T_REG))]
4471  "TARGET_SH1"
4472  "rotl	%0"
4473  [(set_attr "type" "arith")])
4474
4475(define_insn "rotlsi3_31"
4476  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4477	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4478		   (const_int 31)))
4479   (clobber (reg:SI T_REG))]
4480  "TARGET_SH1"
4481  "rotr	%0"
4482  [(set_attr "type" "arith")])
4483
4484(define_insn "rotlsi3_16"
4485  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4486	(rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
4487		   (const_int 16)))]
4488  "TARGET_SH1"
4489  "swap.w	%1,%0"
4490  [(set_attr "type" "arith")])
4491
4492(define_expand "rotlsi3"
4493  [(set (match_operand:SI 0 "arith_reg_dest")
4494	(rotate:SI (match_operand:SI 1 "arith_reg_operand")
4495		   (match_operand:SI 2 "const_int_operand")))]
4496  "TARGET_SH1"
4497{
4498  static const char rot_tab[] = {
4499    000, 000, 000, 000, 000, 000, 010, 001,
4500    001, 001, 011, 013, 003, 003, 003, 003,
4501    003, 003, 003, 003, 003, 013, 012, 002,
4502    002, 002, 010, 000, 000, 000, 000, 000,
4503  };
4504
4505  int count = INTVAL (operands[2]);
4506  int choice = rot_tab[count];
4507  if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
4508    FAIL;
4509  choice &= 7;
4510  switch (choice)
4511    {
4512    case 0:
4513      emit_move_insn (operands[0], operands[1]);
4514      count -= (count & 16) * 2;
4515      break;
4516    case 3:
4517     emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
4518     count -= 16;
4519     break;
4520    case 1:
4521    case 2:
4522      {
4523	rtx parts[2];
4524	parts[0] = gen_reg_rtx (SImode);
4525	parts[1] = gen_reg_rtx (SImode);
4526	emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
4527	emit_move_insn (parts[choice-1], operands[1]);
4528	emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
4529	emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
4530	emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
4531	count = (count & ~16) - 8;
4532      }
4533    }
4534
4535  for (; count > 0; count--)
4536    emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
4537  for (; count < 0; count++)
4538    emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4539
4540  DONE;
4541})
4542
4543(define_insn "rotlhi3_8"
4544  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4545	(rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
4546		   (const_int 8)))]
4547  "TARGET_SH1"
4548  "swap.b	%1,%0"
4549  [(set_attr "type" "arith")])
4550
4551(define_expand "rotlhi3"
4552  [(set (match_operand:HI 0 "arith_reg_operand")
4553	(rotate:HI (match_operand:HI 1 "arith_reg_operand")
4554		   (match_operand:HI 2 "const_int_operand")))]
4555  "TARGET_SH1"
4556{
4557  if (INTVAL (operands[2]) != 8)
4558    FAIL;
4559})
4560
4561;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
4562;; They can also be used to implement things like
4563;;	bool t = a == b;
4564;;	int x0 = (y >> 1) | (t << 31);	// rotcr
4565;;	int x1 = (y << 1) | t;		// rotcl
4566(define_insn "rotcr"
4567  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4568	(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4569			     (const_int 1))
4570		(ashift:SI (match_operand:SI 2 "t_reg_operand")
4571			   (const_int 31))))
4572   (set (reg:SI T_REG)
4573	(and:SI (match_dup 1) (const_int 1)))]
4574  "TARGET_SH1"
4575  "rotcr	%0"
4576  [(set_attr "type" "arith")])
4577
4578(define_insn "rotcl"
4579  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4580	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4581			   (const_int 1))
4582		(match_operand:SI 2 "t_reg_operand")))
4583   (set (reg:SI T_REG)
4584	(lshiftrt:SI (match_dup 1) (const_int 31)))]
4585  "TARGET_SH1"
4586  "rotcl	%0"
4587  [(set_attr "type" "arith")])
4588
4589;; Simplified rotcr version for combine, which allows arbitrary shift
4590;; amounts for the reg.  If the shift amount is '1' rotcr can be used
4591;; directly.  Otherwise we have to insert a shift in between.
4592(define_insn_and_split "*rotcr"
4593  [(set (match_operand:SI 0 "arith_reg_dest")
4594	(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_or_0_operand")
4595			     (match_operand:SI 2 "const_int_operand"))
4596		(ashift:SI (match_operand 3 "arith_reg_or_treg_set_expr")
4597			   (const_int 31))))
4598   (clobber (reg:SI T_REG))]
4599  "TARGET_SH1 && can_create_pseudo_p ()"
4600  "#"
4601  "&& 1"
4602  [(const_int 0)]
4603{
4604  rtx prev_set_t_insn = NULL_RTX;
4605
4606  if (!arith_reg_operand (operands[3], SImode))
4607    {
4608      sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn);
4609      if (!ti.was_treg_operand ())
4610	prev_set_t_insn = ti.first_insn ();
4611
4612      operands[3] = get_t_reg_rtx ();
4613
4614      if (TARGET_SH2A && ti.has_trailing_nott () && operands[1] == const0_rtx)
4615	{
4616	  /* Convert to a movrt, rotr sequence.  */
4617	  remove_insn (ti.trailing_nott ());
4618	  rtx tmp = gen_reg_rtx (SImode);
4619	  emit_insn (gen_movnegt (tmp, get_t_reg_rtx ()));
4620	  emit_insn (gen_rotrsi3_1 (operands[0], tmp));
4621	  DONE;
4622	}
4623    }
4624
4625  if (operands[1] == const0_rtx)
4626    {
4627      operands[1] = gen_reg_rtx (SImode);
4628      emit_insn (gen_movt (operands[1], get_t_reg_rtx ()));
4629    }
4630
4631  if (INTVAL (operands[2]) > 1)
4632    {
4633      const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4634      rtx tmp_t_reg = NULL_RTX;
4635
4636      /* If we're going to emit a shift sequence that clobbers the T_REG,
4637	 try to find the previous insn that sets the T_REG and emit the 
4638	 shift insn before that insn, to remove the T_REG dependency.
4639	 If the insn that sets the T_REG cannot be found, store the T_REG
4640	 in a temporary reg and restore it after the shift.  */
4641      if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4642	  && ! sh_dynamicalize_shift_p (shift_count))
4643	{
4644	  if (prev_set_t_insn == NULL)
4645	    prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4646
4647	  /* Skip the nott insn, which was probably inserted by the splitter
4648	     of *rotcr_neg_t.  Don't use one of the recog functions
4649	     here during insn splitting, since that causes problems in later
4650	     passes.  */
4651	  if (prev_set_t_insn != NULL_RTX)
4652	    {
4653	      rtx pat = PATTERN (prev_set_t_insn);
4654	      if (GET_CODE (pat) == SET
4655		  && t_reg_operand (XEXP (pat, 0), SImode)
4656		  && negt_reg_operand (XEXP (pat, 1), SImode))
4657	      prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4658	    }
4659
4660	  if (! (prev_set_t_insn != NULL_RTX
4661		 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4662		 && ! reg_referenced_p (get_t_reg_rtx (),
4663					PATTERN (prev_set_t_insn))))
4664	    {
4665	      prev_set_t_insn = NULL_RTX;
4666	      tmp_t_reg = gen_reg_rtx (SImode);
4667	      emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4668	    } 
4669	}
4670
4671      rtx shift_result = gen_reg_rtx (SImode);
4672      rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4673      operands[1] = shift_result;
4674
4675      /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4676      if (prev_set_t_insn != NULL_RTX)
4677	emit_insn_before (shift_insn, prev_set_t_insn);
4678      else
4679	emit_insn (shift_insn);
4680
4681      /* Restore T_REG if it has been saved before.  */
4682      if (tmp_t_reg != NULL_RTX)
4683	emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4684    }
4685
4686  /* For the rotcr insn to work, operands[3] must be in T_REG.
4687     If it is not we can get it there by shifting it right one bit.
4688     In this case T_REG is not an input for this insn, thus we don't have to
4689     pay attention as of where to insert the shlr insn.  */
4690  if (! t_reg_operand (operands[3], SImode))
4691    {
4692      /* We don't care about the shifted result here, only the T_REG.  */
4693      emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4694      operands[3] = get_t_reg_rtx ();
4695    }
4696
4697  emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4698  DONE;
4699})
4700
4701;; If combine tries the same as above but with swapped operands, split
4702;; it so that it will try the pattern above.
4703(define_split
4704  [(set (match_operand:SI 0 "arith_reg_dest")
4705	(ior:SI (ashift:SI (match_operand 1 "arith_reg_or_treg_set_expr")
4706			   (const_int 31))
4707		(lshiftrt:SI (match_operand:SI 2 "arith_reg_or_0_operand")
4708			     (match_operand:SI 3 "const_int_operand"))))]
4709  "TARGET_SH1 && can_create_pseudo_p ()"
4710  [(parallel [(set (match_dup 0)
4711		   (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4712			   (ashift:SI (match_dup 1) (const_int 31))))
4713	      (clobber (reg:SI T_REG))])])
4714
4715;; Basically the same as the rotcr pattern above, but for rotcl.
4716;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4717(define_insn_and_split "*rotcl"
4718  [(set (match_operand:SI 0 "arith_reg_dest")
4719	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4720			   (match_operand:SI 2 "const_int_operand"))
4721		(and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4722			(const_int 1))))
4723   (clobber (reg:SI T_REG))]
4724  "TARGET_SH1"
4725  "#"
4726  "&& can_create_pseudo_p ()"
4727  [(const_int 0)]
4728{
4729  gcc_assert (INTVAL (operands[2]) > 0);
4730
4731  if (INTVAL (operands[2]) > 1)
4732    {
4733      const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4734      rtx prev_set_t_insn = NULL_RTX;
4735      rtx tmp_t_reg = NULL_RTX;
4736
4737      /* If we're going to emit a shift sequence that clobbers the T_REG,
4738	 try to find the previous insn that sets the T_REG and emit the 
4739	 shift insn before that insn, to remove the T_REG dependency.
4740	 If the insn that sets the T_REG cannot be found, store the T_REG
4741	 in a temporary reg and restore it after the shift.  */
4742      if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4743	  && ! sh_dynamicalize_shift_p (shift_count))
4744	{
4745	  prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4746
4747	  /* Skip the nott insn, which was probably inserted by the splitter
4748	     of *rotcl_neg_t.  Don't use one of the recog functions
4749	     here during insn splitting, since that causes problems in later
4750	     passes.  */
4751	  if (prev_set_t_insn != NULL_RTX)
4752	    {
4753	      rtx pat = PATTERN (prev_set_t_insn);
4754	      if (GET_CODE (pat) == SET
4755		  && t_reg_operand (XEXP (pat, 0), SImode)
4756		  && negt_reg_operand (XEXP (pat, 1), SImode))
4757	      prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4758	    }
4759
4760	  if (! (prev_set_t_insn != NULL_RTX
4761		 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4762		 && ! reg_referenced_p (get_t_reg_rtx (),
4763					PATTERN (prev_set_t_insn))))
4764	    {
4765	      prev_set_t_insn = NULL_RTX;
4766	      tmp_t_reg = gen_reg_rtx (SImode);
4767	      emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4768	    } 
4769	}
4770
4771      rtx shift_result = gen_reg_rtx (SImode);
4772      rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4773      operands[1] = shift_result;
4774
4775      /* Emit the shift insn before the insn that sets T_REG, if possible.  */
4776      if (prev_set_t_insn != NULL_RTX)
4777	emit_insn_before (shift_insn, prev_set_t_insn);
4778      else
4779	emit_insn (shift_insn);
4780
4781      /* Restore T_REG if it has been saved before.  */
4782      if (tmp_t_reg != NULL_RTX)
4783	emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4784    }
4785
4786  /* For the rotcl insn to work, operands[3] must be in T_REG.
4787     If it is not we can get it there by shifting it right one bit.
4788     In this case T_REG is not an input for this insn, thus we don't have to
4789     pay attention as of where to insert the shlr insn.  */
4790  if (! t_reg_operand (operands[3], SImode))
4791    {
4792      /* We don't care about the shifted result here, only the T_REG.  */
4793      emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4794      operands[3] = get_t_reg_rtx ();
4795    }
4796
4797  emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4798  DONE;
4799})
4800
4801;; rotcl combine pattern variations
4802(define_insn_and_split "*rotcl"
4803  [(set (match_operand:SI 0 "arith_reg_dest")
4804	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4805			   (match_operand:SI 2 "const_int_operand"))
4806		(match_operand 3 "treg_set_expr")))
4807   (clobber (reg:SI T_REG))]
4808  "TARGET_SH1"
4809  "#"
4810  "&& can_create_pseudo_p ()"
4811  [(parallel [(set (match_dup 0)
4812		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4813			   (and:SI (match_dup 3) (const_int 1))))
4814	      (clobber (reg:SI T_REG))])]
4815{
4816  sh_split_treg_set_expr (operands[3], curr_insn);
4817  operands[3] = get_t_reg_rtx ();
4818})
4819
4820(define_insn_and_split "*rotcl"
4821  [(set (match_operand:SI 0 "arith_reg_dest")
4822	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4823			(const_int 1))
4824		(ashift:SI (match_operand:SI 2 "arith_reg_operand")
4825			   (match_operand:SI 3 "const_int_operand"))))
4826   (clobber (reg:SI T_REG))]
4827  "TARGET_SH1"
4828  "#"
4829  "&& can_create_pseudo_p ()"
4830  [(parallel [(set (match_dup 0)
4831		   (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4832			   (and:SI (match_dup 1) (const_int 1))))
4833	      (clobber (reg:SI T_REG))])])
4834
4835(define_insn_and_split "*rotcl"
4836  [(set (match_operand:SI 0 "arith_reg_dest")
4837	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4838			   (match_operand:SI 2 "const_int_operand"))
4839		(lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4840			     (const_int 31))))
4841   (clobber (reg:SI T_REG))]
4842  "TARGET_SH1"
4843  "#"
4844  "&& can_create_pseudo_p ()"
4845  [(parallel [(set (match_dup 0)
4846		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4847			   (and:SI (reg:SI T_REG) (const_int 1))))
4848	      (clobber (reg:SI T_REG))])]
4849{
4850  /* We don't care about the result of the left shift, only the T_REG.  */
4851  emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4852})
4853
4854(define_insn_and_split "*rotcl"
4855  [(set (match_operand:SI 0 "arith_reg_dest")
4856	(ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4857			     (const_int 31))
4858		(ashift:SI (match_operand:SI 1 "arith_reg_operand")
4859			   (match_operand:SI 2 "const_int_operand"))))
4860   (clobber (reg:SI T_REG))]
4861  "TARGET_SH1"
4862  "#"
4863  "&& can_create_pseudo_p ()"
4864  [(parallel [(set (match_dup 0)
4865		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4866			   (and:SI (reg:SI T_REG) (const_int 1))))
4867	      (clobber (reg:SI T_REG))])]
4868{
4869  /* We don't care about the result of the left shift, only the T_REG.  */
4870  emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4871})
4872
4873(define_insn_and_split "*rotcl"
4874  [(set (match_operand:SI 0 "arith_reg_dest")
4875	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4876			   (match_operand 2 "const_int_operand"))
4877		(zero_extract:SI (match_operand:SI 3 "arith_reg_operand")
4878				 (const_int 1)
4879				 (match_operand 4 "const_int_operand"))))
4880   (clobber (reg:SI T_REG))]
4881  "TARGET_SH1"
4882  "#"
4883  "&& can_create_pseudo_p ()"
4884  [(parallel [(set (match_dup 0)
4885		   (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4886			   (and:SI (match_dup 5) (const_int 1))))
4887	      (clobber (reg:SI T_REG))])]
4888{
4889  if (TARGET_SH2A && satisfies_constraint_K03 (operands[4]))
4890    {
4891      /* On SH2A we can use the bld insn to zero extract a single bit
4892	 into the T bit.  */
4893      operands[5] = get_t_reg_rtx ();
4894      emit_insn (gen_bldsi_reg (operands[3], operands[4]));
4895    }
4896  else
4897    {
4898      /* If we can't use the bld insn we have to emit a tst + nott sequence
4899	 to get the extracted bit into the T bit.
4900	 This will probably be worse than pre-shifting the operand.  */
4901      operands[5] = gen_reg_rtx (SImode);
4902      emit_insn (gen_lshrsi3 (operands[5], operands[3], operands[4]));
4903    }
4904})
4905
4906;; rotcr combine bridge pattern which will make combine try out more
4907;; complex patterns.
4908(define_insn_and_split "*rotcr"
4909  [(set (match_operand:SI 0 "arith_reg_dest")
4910	(ashift:SI (match_operand 1 "treg_set_expr") (const_int 31)))]
4911  "TARGET_SH1 && can_create_pseudo_p ()"
4912  "#"
4913  "&& 1"
4914  [(parallel [(set (match_dup 0)
4915		   (ior:SI (lshiftrt:SI (const_int 0) (const_int 1))
4916			   (ashift:SI (match_dup 1) (const_int 31))))
4917	      (clobber (reg:SI T_REG))])])
4918
4919(define_insn_and_split "*rotcr"
4920  [(set (match_operand:SI 0 "arith_reg_dest")
4921	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4922			(const_int -2147483648)) ;; 0xffffffff80000000
4923		(lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4924			     (const_int 1))))
4925   (clobber (reg:SI T_REG))]
4926  "TARGET_SH1"
4927  "#"
4928  "&& can_create_pseudo_p ()"
4929  [(const_int 0)]
4930{
4931  rtx tmp = gen_reg_rtx (SImode);
4932  emit_insn (gen_shll (tmp, operands[1]));
4933  emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4934  DONE;
4935})
4936
4937;; rotcr combine patterns for rotating in the negated T_REG value.
4938(define_insn_and_split "*rotcr_neg_t"
4939  [(set (match_operand:SI 0 "arith_reg_dest")
4940	(ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4941		(lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4942			     (match_operand:SI 3 "const_int_operand"))))
4943   (clobber (reg:SI T_REG))]
4944  "TARGET_SH1"
4945  "#"
4946  "&& can_create_pseudo_p ()"
4947  [(parallel [(set (match_dup 0)
4948		   (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4949			   (ashift:SI (reg:SI T_REG) (const_int 31))))
4950	      (clobber (reg:SI T_REG))])]
4951{
4952  emit_insn (gen_nott (get_t_reg_rtx ()));
4953})
4954
4955(define_insn_and_split "*rotcr_neg_t"
4956  [(set (match_operand:SI 0 "arith_reg_dest")
4957	(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4958			     (match_operand:SI 2 "const_int_operand"))
4959		(match_operand:SI 3 "negt_reg_shl31_operand")))
4960   (clobber (reg:SI T_REG))]
4961  "TARGET_SH1"
4962  "#"
4963  "&& can_create_pseudo_p ()"
4964  [(parallel [(set (match_dup 0)
4965		   (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4966			   (ashift:SI (reg:SI T_REG) (const_int 31))))
4967	      (clobber (reg:SI T_REG))])]
4968{
4969  emit_insn (gen_nott (get_t_reg_rtx ()));
4970})
4971
4972;; rotcl combine patterns for rotating in the negated T_REG value.
4973;; For some strange reason these have to be specified as splits which combine
4974;; will pick up.  If they are specified as insn_and_split like the
4975;; *rotcr_neg_t patterns above, combine would recognize them successfully
4976;; but not emit them on non-SH2A targets.
4977(define_split
4978  [(set (match_operand:SI 0 "arith_reg_dest")
4979	(ior:SI (match_operand:SI 1 "negt_reg_operand")
4980		(ashift:SI (match_operand:SI 2 "arith_reg_operand")
4981			   (match_operand:SI 3 "const_int_operand"))))]
4982  "TARGET_SH1"
4983  [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4984   (parallel [(set (match_dup 0)
4985		   (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4986			   (and:SI (reg:SI T_REG) (const_int 1))))
4987	      (clobber (reg:SI T_REG))])])
4988
4989(define_split
4990  [(set (match_operand:SI 0 "arith_reg_dest")
4991	(ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4992			   (match_operand:SI 3 "const_int_operand"))
4993		(match_operand:SI 1 "negt_reg_operand")))]
4994  "TARGET_SH1"
4995  [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4996   (parallel [(set (match_dup 0)
4997		   (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4998			   (and:SI (reg:SI T_REG) (const_int 1))))
4999	      (clobber (reg:SI T_REG))])])
5000
5001;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5002;; SImode shift left
5003
5004(define_expand "ashlsi3"
5005  [(set (match_operand:SI 0 "arith_reg_operand" "")
5006	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
5007		   (match_operand:SI 2 "shift_count_operand" "")))]
5008  ""
5009{
5010  if (TARGET_SHMEDIA)
5011    {
5012       if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5013	{
5014	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5015	  emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
5016	  DONE;
5017	}
5018      emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
5019      DONE;
5020    }
5021  if (TARGET_DYNSHIFT
5022      && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
5023    {
5024      /* Don't force the constant into a reg yet.  Some other optimizations
5025	 might not see through the reg that holds the shift count.  */
5026    }
5027
5028  /*  If the ashlsi3_* insn is going to clobber the T_REG it must be
5029      expanded here.  */
5030  if (CONST_INT_P (operands[2])
5031      && sh_ashlsi_clobbers_t_reg_p (operands[2])
5032      && ! sh_dynamicalize_shift_p (operands[2]))
5033    {
5034      emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
5035					   operands[2]));
5036      DONE;
5037    }
5038
5039  /* Expand a library call for the dynamic shift.  */
5040  if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
5041    {
5042      emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
5043      rtx funcaddr = gen_reg_rtx (Pmode);
5044      rtx lab = function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC).lab;
5045      emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr, lab));
5046
5047      DONE;
5048    }
5049})
5050
5051(define_insn "ashlsi3_k"
5052  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5053	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
5054		   (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
5055  "TARGET_SH1"
5056  "@
5057	add	%0,%0
5058	shll%O2	%0"
5059  [(set_attr "type" "arith")])
5060
5061(define_insn_and_split "ashlsi3_d"
5062  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5063	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5064		   (match_operand:SI 2 "shift_count_operand" "r")))]
5065  "TARGET_DYNSHIFT"
5066  "shld	%2,%0"
5067  "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
5068   && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
5069  [(const_int 0)]
5070{
5071  if (satisfies_constraint_P27 (operands[2]))
5072    {
5073      emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
5074      DONE;
5075    }
5076  else if (! satisfies_constraint_P27 (operands[2]))
5077    {
5078      /* This must happen before reload, otherwise the constant will be moved
5079	 into a register due to the "r" constraint, after which this split
5080	 cannot be done anymore.
5081	 Unfortunately the move insn will not always be eliminated.
5082	 Also, here we must not create a shift sequence that clobbers the
5083	 T_REG.  */
5084      emit_move_insn (operands[0], operands[1]);
5085      gen_shifty_op (ASHIFT, operands);
5086      DONE;
5087    }
5088
5089  FAIL;
5090}
5091  [(set_attr "type" "dyn_shift")])
5092
5093;; If dynamic shifts are not available use a library function.
5094;; By specifying the pattern we reduce the number of call clobbered regs.
5095;; In order to make combine understand the truncation of the shift amount
5096;; operand we have to allow it to use pseudo regs for the shift operands.
5097(define_insn "ashlsi3_d_call"
5098  [(set (match_operand:SI 0 "arith_reg_dest" "=z,z")
5099	(ashift:SI (reg:SI R4_REG)
5100		   (and:SI (match_operand:SI 1 "arith_reg_operand" "z,z")
5101			   (const_int 31))))
5102   (use (match_operand:SI 2 "arith_reg_operand" "r,r"))
5103   (use (match_operand 3 "" "Z,Ccl"))
5104   (clobber (reg:SI T_REG))
5105   (clobber (reg:SI PR_REG))]
5106  "TARGET_SH1 && !TARGET_DYNSHIFT"
5107  "@
5108	jsr	@%2%#
5109	bsrf	%2\n%O3:%#"
5110  [(set_attr "type" "sfunc")
5111   (set_attr "needs_delay_slot" "yes")])
5112
5113(define_insn_and_split "ashlsi3_n"
5114  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5115	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5116		   (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
5117  "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
5118  "#"
5119  "&& (reload_completed
5120       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5121  [(const_int 0)]
5122{
5123  if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5124    {
5125      /* If this pattern was picked and dynamic shifts are supported, switch
5126	 to dynamic shift pattern before reload.  */
5127      operands[2] = force_reg (SImode, operands[2]);
5128      emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
5129    }
5130  else
5131    gen_shifty_op (ASHIFT, operands);
5132
5133  DONE;
5134})
5135
5136(define_insn_and_split "ashlsi3_n_clobbers_t"
5137  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5138	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5139		   (match_operand:SI 2 "not_p27_shift_count_operand" "")))
5140   (clobber (reg:SI T_REG))]
5141  "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
5142  "#"
5143  "&& (reload_completed || INTVAL (operands[2]) == 31
5144       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5145  [(const_int 0)]
5146{
5147  if (INTVAL (operands[2]) == 31)
5148    {
5149      /* If the shift amount is 31 we split into a different sequence before
5150	 reload so that it gets a chance to allocate R0 for the sequence.
5151	 If it fails to do so (due to pressure on R0), it will take one insn
5152	 more for the and.  */
5153      emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
5154      emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
5155    }
5156  else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5157    {
5158      /* If this pattern was picked and dynamic shifts are supported, switch
5159	 to dynamic shift pattern before reload.  */
5160      operands[2] = force_reg (SImode, operands[2]);
5161      emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
5162    }
5163  else
5164    gen_shifty_op (ASHIFT, operands);
5165
5166  DONE;
5167})
5168
5169(define_insn "shll"
5170  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5171	(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
5172   (set (reg:SI T_REG)
5173	(lt:SI (match_dup 1) (const_int 0)))]
5174  "TARGET_SH1"
5175  "shll	%0"
5176  [(set_attr "type" "arith")])
5177
5178(define_insn "*ashlsi_c_void"
5179  [(set (reg:SI T_REG)
5180	(lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
5181   (clobber (match_scratch:SI 1 "=0"))]
5182  "TARGET_SH1 && cse_not_expected"
5183  "shll	%0"
5184  [(set_attr "type" "arith")])
5185
5186(define_peephole2
5187  [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
5188   (set (reg:SI T_REG)
5189	(gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
5190  "TARGET_SH1
5191   && peep2_reg_dead_p (2, operands[0])
5192   && peep2_reg_dead_p (2, operands[1])"
5193  [(const_int 0)]
5194{
5195  emit_insn (gen_shll (operands[1], operands[1]));
5196  DONE;
5197})
5198
5199(define_insn "ashlsi3_media"
5200  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5201	(ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5202		   (match_operand:SI 2 "shift_count_operand" "r,n")))]
5203  "TARGET_SHMEDIA"
5204  "@
5205	shlld.l	%1, %2, %0
5206	shlli.l	%1, %2, %0"
5207  [(set_attr "type" "arith_media")
5208   (set_attr "highpart" "ignore")])
5209
5210;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5211;; HImode shift left
5212
5213(define_expand "ashlhi3"
5214  [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
5215		   (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
5216			      (match_operand:SI 2 "nonmemory_operand" "")))
5217	      (clobber (reg:SI T_REG))])]
5218  "TARGET_SH1"
5219{
5220  if (!CONST_INT_P (operands[2]))
5221    FAIL;
5222  /* It may be possible to call gen_ashlhi3 directly with more generic
5223     operands.  Make sure operands[1] is a HImode register here.  */
5224  if (!arith_reg_operand (operands[1], HImode))
5225    operands[1] = copy_to_mode_reg (HImode, operands[1]);
5226})
5227
5228(define_insn "ashlhi3_k"
5229  [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
5230	(ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
5231		   (match_operand:HI 2 "const_int_operand" "M,P27")))]
5232  "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
5233  "@
5234	add	%0,%0
5235	shll%O2	%0"
5236  [(set_attr "type" "arith")])
5237
5238(define_insn_and_split "*ashlhi3_n"
5239  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
5240	(ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
5241		   (match_operand:HI 2 "const_int_operand" "n")))
5242   (clobber (reg:SI T_REG))]
5243  "TARGET_SH1"
5244  "#"
5245  "&& reload_completed"
5246  [(use (reg:SI R0_REG))]
5247{
5248  gen_shifty_hi_op (ASHIFT, operands);
5249  DONE;
5250})
5251
5252;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5253;; DImode shift left
5254
5255(define_expand "ashldi3"
5256  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5257		   (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
5258			      (match_operand:DI 2 "immediate_operand" "")))
5259	      (clobber (reg:SI T_REG))])]
5260  ""
5261{
5262  if (TARGET_SHMEDIA)
5263    {
5264       if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5265	{
5266	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5267	  emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
5268	  DONE;
5269	}
5270      emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5271      DONE;
5272    }
5273  if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
5274    {
5275      emit_insn (gen_ashldi3_k (operands[0], operands[1]));
5276      DONE;
5277    }
5278  else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
5279    {
5280      emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
5281      DONE;
5282    }
5283  else
5284    FAIL;
5285})
5286
5287;; Expander for DImode shift left with SImode operations.
5288(define_expand "ashldi3_std"
5289  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5290	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
5291                   (match_operand:DI 2 "const_int_operand" "n")))]
5292  "TARGET_SH1 && INTVAL (operands[2]) < 32"
5293{
5294  rtx low_src = gen_lowpart (SImode, operands[1]);
5295  rtx high_src = gen_highpart (SImode, operands[1]);
5296  rtx dst = gen_reg_rtx (DImode);
5297  rtx low_dst = gen_lowpart (SImode, dst);
5298  rtx high_dst = gen_highpart (SImode, dst);
5299  rtx tmp0 = gen_reg_rtx (SImode);
5300  rtx tmp1 = gen_reg_rtx (SImode);
5301
5302  emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
5303  emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));  
5304  emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));  
5305  emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
5306  emit_move_insn (operands[0], dst);
5307  DONE;
5308})
5309
5310(define_insn_and_split "ashldi3_k"
5311  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5312	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
5313		   (const_int 1)))
5314   (clobber (reg:SI T_REG))]
5315  "TARGET_SH1"
5316  "#"
5317  "&& reload_completed"
5318  [(const_int 0)]
5319{
5320  rtx high = gen_highpart (SImode, operands[0]);
5321  rtx low = gen_lowpart (SImode, operands[0]);
5322  emit_insn (gen_shll (low, low));
5323  emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
5324  DONE;
5325})
5326
5327(define_insn "ashldi3_media"
5328  [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
5329	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5330		   (match_operand:DI 2 "shift_count_operand" "r,n")))]
5331  "TARGET_SHMEDIA"
5332  "@
5333	shlld	%1, %2, %0
5334	shlli	%1, %2, %0"
5335  [(set_attr "type" "arith_media")])
5336
5337(define_insn "*ashldisi3_media"
5338  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5339	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
5340		   (match_operand:DI 2 "const_int_operand" "n")))]
5341  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5342  "shlli.l	%1, %2, %0"
5343  [(set_attr "type" "arith_media")
5344   (set_attr "highpart" "ignore")])
5345
5346;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5347;; SImode arithmetic shift right
5348;;
5349;; We can't do HImode right shifts correctly unless we start out with an
5350;; explicit zero / sign extension; doing that would result in worse overall
5351;; code, so just let the machine independent code widen the mode.
5352;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
5353
5354(define_expand "ashrsi3"
5355  [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
5356		   (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
5357				(match_operand:SI 2 "nonmemory_operand" "")))
5358	      (clobber (reg:SI T_REG))])]
5359  ""
5360{
5361  if (TARGET_SHMEDIA)
5362    {
5363      if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5364	{
5365	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5366	  emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
5367	  DONE;
5368	}
5369      emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
5370      DONE;
5371    }
5372  if (expand_ashiftrt (operands))
5373    DONE;
5374  else
5375    FAIL;
5376})
5377
5378(define_insn "shar"
5379  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5380	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5381		     (const_int 1)))
5382   (set (reg:SI T_REG)
5383	(and:SI (match_dup 1) (const_int 1)))]
5384  "TARGET_SH1"
5385  "shar	%0"
5386  [(set_attr "type" "arith")])
5387
5388(define_insn "ashrsi3_k"
5389  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5390	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5391		     (match_operand:SI 2 "const_int_operand" "M")))
5392   (clobber (reg:SI T_REG))]
5393  "TARGET_SH1 && INTVAL (operands[2]) == 1"
5394  "shar	%0"
5395  [(set_attr "type" "arith")])
5396
5397(define_insn_and_split "ashrsi2_16"
5398  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5399        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
5400                     (const_int 16)))]
5401  "TARGET_SH1"
5402  "#"
5403  "&& 1"
5404  [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
5405   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
5406{
5407  operands[2] = gen_lowpart (HImode, operands[0]);
5408})
5409
5410(define_insn_and_split "ashrsi2_31"
5411  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5412	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5413		     (const_int 31)))
5414   (clobber (reg:SI T_REG))]
5415  "TARGET_SH1"
5416  "#"
5417  "&& 1"
5418  [(const_int 0)]
5419{
5420  emit_insn (gen_shll (operands[0], operands[1]));
5421  emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
5422  DONE;
5423})
5424
5425;; If the shift amount is changed by combine it will try to plug the
5426;; use on the symbol of the library function and the PR clobber.
5427(define_insn_and_split "*ashrsi2_31"
5428  [(set (match_operand:SI 0 "arith_reg_dest")
5429	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand")
5430		     (const_int 31)))
5431   (clobber (reg:SI T_REG))
5432   (clobber (reg:SI PR_REG))
5433   (use (match_operand:SI 2 "symbol_ref_operand"))]
5434  "TARGET_SH1"
5435  "#"
5436  "&& 1"
5437  [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))
5438	      (clobber (reg:SI T_REG))])])
5439
5440(define_insn "ashrsi3_d"
5441  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5442	(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5443		     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
5444  "TARGET_DYNSHIFT"
5445  "shad	%2,%0"
5446  [(set_attr "type" "dyn_shift")])
5447
5448(define_insn "ashrsi3_n"
5449  [(set (reg:SI R4_REG)
5450	(ashiftrt:SI (reg:SI R4_REG)
5451		     (match_operand:SI 0 "const_int_operand" "i,i")))
5452   (clobber (reg:SI T_REG))
5453   (clobber (reg:SI PR_REG))
5454   (use (match_operand:SI 1 "arith_reg_operand" "r,r"))
5455   (use (match_operand 2 "" "Z,Ccl"))]
5456  "TARGET_SH1"
5457  "@
5458	jsr	@%1%#
5459	bsrf	%1\n%O2:%#"
5460  [(set_attr "type" "sfunc")
5461   (set_attr "needs_delay_slot" "yes")])
5462
5463(define_insn "ashrsi3_media"
5464  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5465	(ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5466		     (match_operand:SI 2 "shift_count_operand" "r,n")))]
5467  "TARGET_SHMEDIA"
5468  "@
5469	shard.l	%1, %2, %0
5470	shari.l	%1, %2, %0"
5471  [(set_attr "type" "arith_media")
5472   (set_attr "highpart" "ignore")])
5473
5474;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5475;; DImode arithmetic shift right
5476
5477(define_expand "ashrdi3"
5478  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5479		   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5480				(match_operand:DI 2 "immediate_operand" "")))
5481	      (clobber (reg:SI T_REG))])]
5482  ""
5483{
5484  if (TARGET_SHMEDIA)
5485    {
5486      if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5487	{
5488	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5489	  emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5490	  DONE;
5491	}
5492      emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
5493      DONE;
5494    }
5495  if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5496    FAIL;
5497})
5498
5499(define_insn_and_split "ashrdi3_k"
5500  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5501	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5502		     (const_int 1)))
5503   (clobber (reg:SI T_REG))]
5504  "TARGET_SH1"
5505  "#"
5506  "&& reload_completed"
5507  [(const_int 0)]
5508{
5509  rtx high = gen_highpart (SImode, operands[0]);
5510  rtx low = gen_lowpart (SImode, operands[0]);
5511  emit_insn (gen_shar (high, high));
5512  emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5513  DONE;
5514})
5515
5516(define_insn "ashrdi3_media"
5517  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5518	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5519		     (match_operand:DI 2 "shift_count_operand" "r,n")))]
5520  "TARGET_SHMEDIA
5521   && (arith_reg_dest (operands[0], DImode)
5522       || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
5523  "@
5524	shard	%1, %2, %0
5525	shari	%1, %2, %0"
5526  [(set_attr "type" "arith_media")])
5527
5528(define_insn "*ashrdisi3_media"
5529  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5530	(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5531		     (match_operand:DI 2 "const_int_operand" "n")))]
5532  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5533  "shari.l	%1, %2, %0"
5534  [(set_attr "type" "arith_media")
5535   (set_attr "highpart" "ignore")])
5536
5537(define_insn "ashrdisi3_media_high"
5538  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5539	(truncate:SI
5540	   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5541			(match_operand:DI 2 "const_int_operand" "n"))))]
5542  "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
5543  "shari	%1, %2, %0"
5544  [(set_attr "type" "arith_media")])
5545
5546(define_insn "ashrdisi3_media_opaque"
5547  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5548	(unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
5549		    (match_operand:DI 2 "const_int_operand" "n")]
5550	 UNSPEC_ASHIFTRT))]
5551  "TARGET_SHMEDIA"
5552  "shari	%1, %2, %0"
5553  [(set_attr "type" "arith_media")])
5554
5555;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5556;; SImode logical shift right
5557
5558(define_expand "lshrsi3"
5559  [(set (match_operand:SI 0 "arith_reg_dest" "")
5560	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
5561		     (match_operand:SI 2 "shift_count_operand" "")))]
5562  ""
5563{
5564  if (TARGET_SHMEDIA)
5565    {
5566      if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5567	{
5568	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5569	  emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
5570	  DONE;
5571	}
5572      emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
5573      DONE;
5574    }
5575
5576  /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
5577     here, otherwise the pattern will never match due to the shift amount reg
5578     negation.  */
5579  if (TARGET_DYNSHIFT
5580      && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
5581    {
5582      /* Don't force the constant into a reg yet.  Some other optimizations
5583	 might not see through the reg that holds the shift count.  */
5584      if (sh_lshrsi_clobbers_t_reg_p (operands[2]))
5585        emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1], operands[2]));
5586      else
5587        emit_insn (gen_lshrsi3_n (operands[0], operands[1], operands[2]));
5588      DONE;
5589    }
5590
5591  if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
5592    {
5593      rtx neg_count = gen_reg_rtx (SImode);
5594      emit_insn (gen_negsi2 (neg_count, operands[2]));
5595      emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5596      DONE;
5597    }
5598
5599  /* If the lshrsi3_* insn is going to clobber the T_REG it must be
5600     expanded here.  */
5601  if (CONST_INT_P (operands[2])
5602      && sh_lshrsi_clobbers_t_reg_p (operands[2])
5603      && ! sh_dynamicalize_shift_p (operands[2]))
5604    {
5605      emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
5606		 operands[2]));
5607      DONE;
5608    }
5609
5610  /* Expand a library call for the dynamic shift.  */
5611  if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
5612    {
5613      emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
5614      rtx funcaddr = gen_reg_rtx (Pmode);
5615      rtx lab = function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC).lab;
5616      emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr, lab));
5617      DONE;
5618    }
5619})
5620
5621(define_insn "lshrsi3_k"
5622  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5623	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5624		     (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
5625  "TARGET_SH1"
5626  "shlr%O2	%0"
5627  [(set_attr "type" "arith")])
5628
5629(define_insn_and_split "lshrsi3_d"
5630  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5631	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5632		     (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
5633  "TARGET_DYNSHIFT"
5634  "shld	%2,%0"
5635  "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
5636   && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5637  [(const_int 0)]
5638{
5639  /* The shift count const_int is a negative value for all dynamic
5640     right shift insns.  */
5641  operands[2] = GEN_INT (- INTVAL (operands[2]));
5642
5643  if (satisfies_constraint_P27 (operands[2]))
5644    {
5645      /* This will not be done for a shift amount of 1, because it would
5646	 clobber the T_REG.  */
5647      emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
5648      DONE;
5649    }
5650  else if (! satisfies_constraint_P27 (operands[2]))
5651    {
5652      /* This must happen before reload, otherwise the constant will be moved
5653	 into a register due to the "r" constraint, after which this split
5654	 cannot be done anymore.
5655	 Unfortunately the move insn will not always be eliminated.
5656	 Also, here we must not create a shift sequence that clobbers the
5657	 T_REG.  */
5658      emit_move_insn (operands[0], operands[1]);
5659      gen_shifty_op (LSHIFTRT, operands);
5660      DONE;
5661    }
5662
5663  FAIL;
5664}
5665  [(set_attr "type" "dyn_shift")])
5666
5667;; If dynamic shifts are not available use a library function.
5668;; By specifying the pattern we reduce the number of call clobbered regs.
5669;; In order to make combine understand the truncation of the shift amount
5670;; operand we have to allow it to use pseudo regs for the shift operands.
5671(define_insn "lshrsi3_d_call"
5672  [(set (match_operand:SI 0 "arith_reg_dest" "=z,z")
5673	(lshiftrt:SI (reg:SI R4_REG)
5674		     (and:SI (match_operand:SI 1 "arith_reg_operand" "z,z")
5675			     (const_int 31))))
5676   (use (match_operand:SI 2 "arith_reg_operand" "r,r"))
5677   (use (match_operand 3 "" "Z,Ccl"))
5678   (clobber (reg:SI T_REG))
5679   (clobber (reg:SI PR_REG))]
5680  "TARGET_SH1 && !TARGET_DYNSHIFT"
5681  "@
5682	jsr	@%2%#
5683	bsrf	%2\n%O3:%#"
5684  [(set_attr "type" "sfunc")
5685   (set_attr "needs_delay_slot" "yes")])
5686
5687(define_insn_and_split "lshrsi3_n"
5688  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5689	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5690		     (match_operand:SI 2 "not_p27_rshift_count_operand")))]
5691  "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5692  "#"
5693  "&& (reload_completed
5694       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5695  [(const_int 0)]
5696{
5697  if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5698    {
5699      /* If this pattern was picked and dynamic shifts are supported, switch
5700	 to dynamic shift pattern before reload.  */
5701      operands[2] = GEN_INT (- INTVAL (operands[2]));
5702      emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5703    }
5704  else
5705    gen_shifty_op (LSHIFTRT, operands);
5706
5707  DONE;
5708})
5709
5710;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5711;; the shlr pattern.
5712(define_insn_and_split "lshrsi3_n_clobbers_t"
5713  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5714	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5715		     (match_operand:SI 2 "not_p27_rshift_count_operand")))
5716   (clobber (reg:SI T_REG))]
5717  "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
5718  "#"
5719  "&& (reload_completed || INTVAL (operands[2]) == 31
5720       || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5721  [(const_int 0)]
5722{
5723  if (INTVAL (operands[2]) == 31)
5724    {
5725      emit_insn (gen_shll (operands[0], operands[1]));
5726      emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5727    }
5728  else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5729    {
5730      /* If this pattern was picked and dynamic shifts are supported, switch
5731	 to dynamic shift pattern before reload.  */
5732      operands[2] = GEN_INT (- INTVAL (operands[2]));
5733      emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5734    }
5735  else
5736    gen_shifty_op (LSHIFTRT, operands);
5737
5738  DONE;
5739})
5740
5741(define_insn "shlr"
5742  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5743	(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5744		     (const_int 1)))
5745   (set (reg:SI T_REG)
5746	(and:SI (match_dup 1) (const_int 1)))]
5747  "TARGET_SH1"
5748  "shlr	%0"
5749  [(set_attr "type" "arith")])
5750
5751(define_insn "lshrsi3_media"
5752  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5753	(lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5754		     (match_operand:SI 2 "shift_count_operand" "r,n")))]
5755  "TARGET_SHMEDIA"
5756  "@
5757	shlrd.l	%1, %2, %0
5758	shlri.l	%1, %2, %0"
5759  [(set_attr "type" "arith_media")
5760   (set_attr "highpart" "ignore")])
5761
5762;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5763;; DImode logical shift right
5764
5765(define_expand "lshrdi3"
5766  [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5767		   (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5768			       (match_operand:DI 2 "immediate_operand" "")))
5769	     (clobber (reg:SI T_REG))])]
5770  ""
5771{
5772  if (TARGET_SHMEDIA)
5773    {
5774      if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5775	{
5776	  operands[2] = GEN_INT (-INTVAL (operands[2]));
5777	  emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5778	  DONE;
5779	}
5780      emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
5781      DONE;
5782    }
5783  if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5784    FAIL;
5785})
5786
5787(define_insn_and_split "lshrdi3_k"
5788  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5789	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5790		     (const_int 1)))
5791   (clobber (reg:SI T_REG))]
5792  "TARGET_SH1"
5793  "#"
5794  "&& reload_completed"
5795  [(const_int 0)]
5796{
5797  rtx high = gen_highpart (SImode, operands[0]);
5798  rtx low = gen_lowpart (SImode, operands[0]);
5799  emit_insn (gen_shlr (high, high));
5800  emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5801  DONE;
5802})
5803
5804(define_insn "lshrdi3_media"
5805  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5806	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5807		     (match_operand:DI 2 "shift_count_operand" "r,n")))]
5808  "TARGET_SHMEDIA
5809   && (arith_reg_dest (operands[0], DImode)
5810       || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
5811  "@
5812	shlrd	%1, %2, %0
5813	shlri	%1, %2, %0"
5814  [(set_attr "type" "arith_media")])
5815
5816(define_insn "*lshrdisi3_media"
5817  [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5818	(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5819		     (match_operand:DI 2 "const_int_operand" "n")))]
5820  "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5821  "shlri.l	%1, %2, %0"
5822  [(set_attr "type" "arith_media")
5823   (set_attr "highpart" "ignore")])
5824
5825;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5826;; Combined left/right shifts
5827
5828(define_split
5829  [(set (match_operand:SI 0 "register_operand" "")
5830	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5831			   (match_operand:SI 2 "const_int_operand" ""))
5832		(match_operand:SI 3 "const_int_operand" "")))]
5833  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5834  [(use (reg:SI R0_REG))]
5835{
5836  if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5837    FAIL;
5838  DONE;
5839})
5840
5841(define_split
5842  [(set (match_operand:SI 0 "register_operand" "")
5843	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5844			   (match_operand:SI 2 "const_int_operand" ""))
5845		(match_operand:SI 3 "const_int_operand" "")))
5846   (clobber (reg:SI T_REG))]
5847  "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5848  [(use (reg:SI R0_REG))]
5849{
5850  if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5851    FAIL;
5852  DONE;
5853})
5854
5855(define_insn ""
5856  [(set (match_operand:SI 0 "register_operand" "=r")
5857	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5858			   (match_operand:SI 2 "const_int_operand" "n"))
5859		(match_operand:SI 3 "const_int_operand" "n")))
5860   (clobber (reg:SI T_REG))]
5861  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
5862  "#"
5863  [(set (attr "length")
5864	(cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5865	       (const_string "4")
5866	       (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5867	       (const_string "6")
5868	       (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5869	       (const_string "8")
5870	       (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5871	       (const_string "10")
5872	       (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5873	       (const_string "12")
5874	       (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5875	       (const_string "14")
5876	       (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5877	       (const_string "16")]
5878	      (const_string "18")))
5879   (set_attr "type" "arith")])
5880
5881(define_insn ""
5882  [(set (match_operand:SI 0 "register_operand" "=z")
5883	(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5884			   (match_operand:SI 2 "const_int_operand" "n"))
5885		(match_operand:SI 3 "const_int_operand" "n")))
5886   (clobber (reg:SI T_REG))]
5887  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
5888  "#"
5889  [(set (attr "length")
5890	(cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5891	       (const_string "4")
5892	       (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5893	       (const_string "6")
5894	       (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5895	       (const_string "8")]
5896	      (const_string "10")))
5897   (set_attr "type" "arith")])
5898
5899;; shift left / and combination with a scratch register: The combine pass
5900;; does not accept the individual instructions, even though they are
5901;; cheap.  But it needs a precise description so that it is usable after
5902;; reload.
5903(define_insn "and_shl_scratch"
5904  [(set (match_operand:SI 0 "register_operand" "=r,&r")
5905	(lshiftrt:SI
5906	 (ashift:SI
5907	  (and:SI
5908	   (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5909			(match_operand:SI 2 "const_int_operand" "N,n"))
5910	   (match_operand:SI 3 "" "0,r"))
5911	  (match_operand:SI 4 "const_int_operand" "n,n"))
5912	 (match_operand:SI 5 "const_int_operand" "n,n")))
5913   (clobber (reg:SI T_REG))]
5914  "TARGET_SH1"
5915  "#"
5916  [(set (attr "length")
5917	(cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5918	       (const_string "4")
5919	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5920	       (const_string "6")
5921	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5922	       (const_string "8")
5923	       (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5924	       (const_string "10")]
5925	      (const_string "12")))
5926   (set_attr "type" "arith")])
5927
5928(define_split
5929  [(set (match_operand:SI 0 "register_operand" "")
5930	(lshiftrt:SI
5931	 (ashift:SI
5932	  (and:SI
5933	   (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5934			(match_operand:SI 2 "const_int_operand" ""))
5935	   (match_operand:SI 3 "register_operand" ""))
5936	  (match_operand:SI 4 "const_int_operand" ""))
5937	 (match_operand:SI 5 "const_int_operand" "")))
5938   (clobber (reg:SI T_REG))]
5939  "TARGET_SH1"
5940  [(use (reg:SI R0_REG))]
5941{
5942  rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5943
5944  if (INTVAL (operands[2]))
5945    {
5946      gen_shifty_op (LSHIFTRT, operands);
5947    }
5948  emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5949  operands[2] = operands[4];
5950  gen_shifty_op (ASHIFT, operands);
5951  if (INTVAL (operands[5]))
5952    {
5953      operands[2] = operands[5];
5954      gen_shifty_op (LSHIFTRT, operands);
5955    }
5956  DONE;
5957})
5958
5959;; signed left/right shift combination.
5960(define_split
5961  [(set (match_operand:SI 0 "register_operand" "")
5962        (sign_extract:SI
5963	 (ashift:SI (match_operand:SI 1 "register_operand" "")
5964		    (match_operand:SI 2 "const_int_operand" ""))
5965	 (match_operand:SI 3 "const_int_operand" "")
5966	 (const_int 0)))
5967   (clobber (reg:SI T_REG))]
5968  "TARGET_SH1"
5969  [(use (reg:SI R0_REG))]
5970{
5971  if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5972    FAIL;
5973  DONE;
5974})
5975
5976(define_insn "shl_sext_ext"
5977  [(set (match_operand:SI 0 "register_operand" "=r")
5978        (sign_extract:SI
5979	 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5980		    (match_operand:SI 2 "const_int_operand" "n"))
5981	 (match_operand:SI 3 "const_int_operand" "n")
5982	 (const_int 0)))
5983   (clobber (reg:SI T_REG))]
5984  "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5985  "#"
5986  [(set (attr "length")
5987	(cond [(match_test "shl_sext_length (insn)")
5988	       (const_string "2")
5989	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5990	       (const_string "4")
5991	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5992	       (const_string "6")
5993	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5994	       (const_string "8")
5995	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5996	       (const_string "10")
5997	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5998	       (const_string "12")
5999	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
6000	       (const_string "14")
6001	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
6002	       (const_string "16")]
6003	      (const_string "18")))
6004    (set_attr "type" "arith")])
6005
6006(define_insn "shl_sext_sub"
6007  [(set (match_operand:SI 0 "register_operand" "=z")
6008        (sign_extract:SI
6009	 (ashift:SI (match_operand:SI 1 "register_operand" "0")
6010		    (match_operand:SI 2 "const_int_operand" "n"))
6011	 (match_operand:SI 3 "const_int_operand" "n")
6012	 (const_int 0)))
6013   (clobber (reg:SI T_REG))]
6014  "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
6015  "#"
6016  [(set (attr "length")
6017	(cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
6018	       (const_string "6")
6019	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
6020	       (const_string "8")
6021	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
6022	       (const_string "10")
6023	       (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
6024	       (const_string "12")]
6025	      (const_string "14")))
6026    (set_attr "type" "arith")])
6027
6028;; The xtrct_left and xtrct_right patterns are used in expansions of DImode
6029;; shifts by 16, and allow the xtrct instruction to be generated from C
6030;; source.
6031(define_insn "xtrct_left"
6032  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6033        (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
6034			   (const_int 16))
6035 	        (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
6036			     (const_int 16))))]
6037  "TARGET_SH1"
6038  "xtrct	%1,%0"
6039  [(set_attr "type" "arith")])
6040
6041(define_insn "xtrct_right"
6042  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6043        (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
6044			     (const_int 16))
6045 	        (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
6046			   (const_int 16))))]
6047  "TARGET_SH1"
6048  "xtrct	%2,%0"
6049  [(set_attr "type" "arith")])
6050
6051;; -------------------------------------------------------------------------
6052;; Unary arithmetic
6053;; -------------------------------------------------------------------------
6054
6055(define_insn "negc"
6056  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6057	(neg:SI (plus:SI (reg:SI T_REG)
6058			 (match_operand:SI 1 "arith_reg_operand" "r"))))
6059   (set (reg:SI T_REG)
6060	(ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
6061	       (const_int 0)))]
6062  "TARGET_SH1"
6063  "negc	%1,%0"
6064  [(set_attr "type" "arith")])
6065
6066;; A simplified version of the negc insn, where the exact value of the
6067;; T bit doesn't matter.  This is easier for combine to pick up.
6068;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
6069;; extra patterns for this case.
6070(define_insn_and_split "*negc"
6071  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6072	(minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
6073		  (match_operand 2 "treg_set_expr")))
6074   (clobber (reg:SI T_REG))]
6075  "TARGET_SH1 && can_create_pseudo_p ()"
6076  "#"
6077  "&& 1"
6078  [(const_int 0)]
6079{
6080  sh_split_treg_set_expr (operands[2], curr_insn);
6081  emit_insn (gen_negc (operands[0], operands[1]));
6082  DONE;
6083});
6084
6085(define_insn "*negdi_media"
6086  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
6087	(neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
6088  "TARGET_SHMEDIA"
6089  "sub	r63, %1, %0"
6090  [(set_attr "type" "arith_media")])
6091
6092;; Don't split into individual negc insns immediately so that neg:DI (abs:DI)
6093;; can be combined.
6094(define_expand "negdi2"
6095  [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
6096		   (neg:DI (match_operand:DI 1 "arith_reg_operand")))
6097	      (clobber (reg:SI T_REG))])]
6098  "TARGET_SH1")
6099
6100(define_insn_and_split "*negdi2"
6101  [(set (match_operand:DI 0 "arith_reg_dest")
6102	(neg:DI (match_operand:DI 1 "arith_reg_operand")))
6103   (clobber (reg:SI T_REG))]
6104  "TARGET_SH1"
6105  "#"
6106  "&& can_create_pseudo_p ()"
6107  [(const_int 0)]
6108{
6109  emit_insn (gen_clrt ());
6110  emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
6111		       gen_lowpart (SImode, operands[1])));
6112  emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
6113		       gen_highpart (SImode, operands[1])));
6114  DONE;
6115})
6116
6117(define_insn "negsi2"
6118  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6119	(neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
6120  "TARGET_SH1"
6121  "neg	%1,%0"
6122  [(set_attr "type" "arith")])
6123
6124(define_insn_and_split "one_cmplsi2"
6125  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6126	(not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
6127  "TARGET_SH1"
6128  "not	%1,%0"
6129  "&& can_create_pseudo_p ()"
6130  [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
6131   (set (match_dup 0) (reg:SI T_REG))]
6132{
6133/* PR 54685
6134   If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
6135   sequence:
6136
6137     (set (reg0) (not:SI (reg0) (reg1)))
6138     (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
6139		(clobber (reg:SI T_REG))])
6140
6141   ... match and combine the sequence manually in the split pass after the
6142   combine pass.  Notice that combine does try the target pattern of this
6143   split, but if the pattern is added it interferes with other patterns, in
6144   particular with the div0s comparisons.
6145   This could also be done with a peephole but doing it here before register
6146   allocation can save one temporary.
6147   When we're here, the not:SI pattern obviously has been matched already
6148   and we only have to see whether the following insn is the left shift.  */
6149
6150  rtx_insn *i = next_nonnote_insn_bb (curr_insn);
6151  if (i == NULL_RTX || !NONJUMP_INSN_P (i))
6152    FAIL;
6153
6154  rtx p = PATTERN (i);
6155  if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
6156    FAIL;
6157
6158  rtx p0 = XVECEXP (p, 0, 0);
6159  rtx p1 = XVECEXP (p, 0, 1);
6160
6161  if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31)))  */
6162      GET_CODE (p0) == SET
6163      && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
6164      && REG_P (XEXP (XEXP (p0, 1), 0))
6165      && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
6166      && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
6167      && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
6168
6169      /* (clobber (reg:SI T_REG))  */
6170      && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
6171      && REGNO (XEXP (p1, 0)) == T_REG)
6172    {
6173      operands[0] = XEXP (p0, 0);
6174      set_insn_deleted (i);
6175    }
6176  else
6177    FAIL;
6178}
6179  [(set_attr "type" "arith")])
6180
6181(define_expand "one_cmpldi2"
6182  [(set (match_operand:DI 0 "arith_reg_dest" "")
6183	(xor:DI (match_operand:DI 1 "arith_reg_operand" "")
6184		(const_int -1)))]
6185  "TARGET_SHMEDIA" "")
6186
6187(define_expand "abs<mode>2"
6188  [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
6189		   (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
6190	      (clobber (reg:SI T_REG))])]
6191  "TARGET_SH1")
6192
6193(define_insn_and_split "*abs<mode>2"
6194  [(set (match_operand:SIDI 0 "arith_reg_dest")
6195  	(abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
6196   (clobber (reg:SI T_REG))]
6197  "TARGET_SH1"
6198  "#"
6199  "&& can_create_pseudo_p ()"
6200  [(const_int 0)]
6201{
6202  if (<MODE>mode == SImode)
6203    emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
6204  else
6205    {
6206      rtx high_src = gen_highpart (SImode, operands[1]);
6207      emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
6208    }
6209
6210  emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
6211				 const1_rtx));
6212  DONE;
6213})
6214
6215(define_insn_and_split "*negabs<mode>2"
6216  [(set (match_operand:SIDI 0 "arith_reg_dest")
6217	(neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
6218   (clobber (reg:SI T_REG))]
6219  "TARGET_SH1"
6220  "#"
6221  "&& can_create_pseudo_p ()"
6222  [(const_int 0)]
6223{
6224  if (<MODE>mode == SImode)
6225    emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
6226  else
6227    {
6228      rtx high_src = gen_highpart (SImode, operands[1]);
6229      emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
6230    }
6231
6232  emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
6233				 const0_rtx));
6234  DONE;
6235})
6236
6237;; The SH4 202 can do zero-offset branches without pipeline stalls.
6238;; This can be used as some kind of conditional execution, which is useful
6239;; for abs.
6240;; Actually the instruction scheduling should decide whether to use a
6241;; zero-offset branch or not for any generic case involving a single
6242;; instruction on SH4 202.
6243(define_insn_and_split "negsi_cond"
6244  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
6245	(if_then_else
6246	  (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
6247	  (match_operand:SI 1 "arith_reg_operand" "0,0")
6248	  (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
6249  "TARGET_SH1 && TARGET_ZDCBRANCH"
6250{
6251  static const char* alt[] =
6252  {
6253       "bt	0f"	"\n"
6254    "	neg	%2,%0"	"\n"
6255    "0:",
6256
6257       "bf	0f"	"\n"
6258    "	neg	%2,%0"	"\n"
6259    "0:"
6260  };
6261  return alt[which_alternative];
6262}
6263  "TARGET_SH1 && ! TARGET_ZDCBRANCH"
6264  [(const_int 0)]
6265{
6266  rtx skip_neg_label = gen_label_rtx ();
6267
6268  emit_move_insn (operands[0], operands[1]);
6269
6270  emit_jump_insn (INTVAL (operands[3])
6271		  ? gen_branch_true (skip_neg_label)
6272		  : gen_branch_false (skip_neg_label));
6273
6274  emit_label_after (skip_neg_label,
6275		    emit_insn (gen_negsi2 (operands[0], operands[1])));
6276  DONE;
6277}
6278  [(set_attr "type" "arith") ;; poor approximation
6279   (set_attr "length" "4")])
6280
6281(define_insn_and_split "negdi_cond"
6282  [(set (match_operand:DI 0 "arith_reg_dest")
6283	(if_then_else
6284	  (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
6285	  (match_operand:DI 1 "arith_reg_operand")
6286	  (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
6287   (clobber (reg:SI T_REG))]
6288  "TARGET_SH1"
6289  "#"
6290  "&& can_create_pseudo_p ()"
6291  [(const_int 0)]
6292{
6293  rtx skip_neg_label = gen_label_rtx ();
6294
6295  emit_move_insn (operands[0], operands[1]);
6296
6297  emit_jump_insn (INTVAL (operands[3]) 
6298		  ? gen_branch_true (skip_neg_label)
6299		  : gen_branch_false (skip_neg_label));
6300
6301  if (!INTVAL (operands[3]))
6302    emit_insn (gen_clrt ());
6303
6304  emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
6305		       gen_lowpart (SImode, operands[1])));
6306  emit_label_after (skip_neg_label,
6307		    emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
6308					 gen_highpart (SImode, operands[1]))));
6309  DONE;
6310})
6311
6312(define_expand "bswapsi2"
6313  [(set (match_operand:SI 0 "arith_reg_dest" "")
6314	(bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
6315  "TARGET_SH1"
6316{
6317  if (! can_create_pseudo_p ())
6318    FAIL;
6319  else
6320    {
6321      rtx tmp0 = gen_reg_rtx (SImode);
6322      rtx tmp1 = gen_reg_rtx (SImode);
6323
6324      emit_insn (gen_swapbsi2 (tmp0, operands[1]));
6325      emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
6326      emit_insn (gen_swapbsi2 (operands[0], tmp1));
6327      DONE;
6328    }
6329})
6330
6331(define_insn "swapbsi2"
6332  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6333	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
6334			(const_int -65536)) ;; 0xFFFF0000
6335		(ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
6336				(const_int 65280))
6337			(and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
6338				(const_int 255)))))]
6339  "TARGET_SH1"
6340  "swap.b	%1,%0"
6341  [(set_attr "type" "arith")])
6342
6343;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
6344;; partial byte swap expressions such as...
6345;;   ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
6346;; ...which are currently not handled by the tree optimizers.
6347;; The combine pass will not initially try to combine the full expression,
6348;; but only some sub-expressions.  In such a case the *swapbisi2_and_shl8
6349;; pattern acts as an intermediate pattern that will eventually lead combine
6350;; to the swapbsi2 pattern above.
6351;; As a side effect this also improves code that does (x & 0xFF) << 8
6352;; or (x << 8) & 0xFF00.
6353(define_insn_and_split "*swapbisi2_and_shl8"
6354  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6355	(ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
6356				   (const_int 8))
6357			(const_int 65280))
6358		(match_operand:SI 2 "arith_reg_operand" "r")))]
6359  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
6360  "#"
6361  "&& can_create_pseudo_p ()"
6362  [(const_int 0)]
6363{
6364  rtx tmp0 = gen_reg_rtx (SImode);
6365  rtx tmp1 = gen_reg_rtx (SImode);
6366
6367  emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
6368  emit_insn (gen_swapbsi2 (tmp1, tmp0));
6369  emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
6370  DONE;
6371})
6372
6373;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
6374;; intermediate pattern that will help the combine pass arriving at swapbsi2.
6375(define_insn_and_split "*swapbhisi2"
6376  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6377	(ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
6378				   (const_int 8))
6379			(const_int 65280))
6380		(zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
6381  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
6382  "#"
6383  "&& can_create_pseudo_p ()"
6384  [(const_int 0)]
6385{
6386  rtx tmp = gen_reg_rtx (SImode);
6387
6388  emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
6389  emit_insn (gen_swapbsi2 (operands[0], tmp));
6390  DONE;
6391})
6392
6393;; In some cases the swapbsi2 pattern might leave a sequence such as...
6394;;   swap.b  r4,r4
6395;;   mov     r4,r0
6396;;
6397;; which can be simplified to...
6398;;   swap.b  r4,r0
6399(define_peephole2
6400  [(set (match_operand:SI 0 "arith_reg_dest" "")
6401	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
6402			(const_int -65536)) ;; 0xFFFF0000
6403		(ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
6404				(const_int 65280))
6405			(and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
6406				(const_int 255)))))
6407   (set (match_operand:SI 2 "arith_reg_dest" "")
6408	(match_dup 0))]
6409  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
6410  [(set (match_dup 2)
6411	(ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
6412			(const_int -65536)) ;; 0xFFFF0000
6413		(ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
6414				(const_int 65280))
6415			(and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
6416				(const_int 255)))))])
6417
6418;; -------------------------------------------------------------------------
6419;; Zero extension instructions
6420;; -------------------------------------------------------------------------
6421
6422(define_insn "zero_extendsidi2"
6423  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
6424	(zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
6425  "TARGET_SHMEDIA"
6426  "addz.l	%1, r63, %0"
6427  [(set_attr "type" "arith_media")
6428   (set_attr "highpart" "extend")])
6429
6430(define_insn "zero_extendhidi2"
6431  [(set (match_operand:DI 0 "register_operand" "=r,r")
6432	(zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6433  "TARGET_SHMEDIA"
6434  "@
6435	#
6436	ld%M1.uw	%m1, %0"
6437  [(set_attr "type" "*,load_media")
6438   (set (attr "highpart")
6439	(cond [(match_test "sh_contains_memref_p (insn)")
6440	       (const_string "user")]
6441	      (const_string "ignore")))])
6442
6443(define_split
6444  [(set (match_operand:DI 0 "register_operand" "")
6445	(zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6446  "TARGET_SHMEDIA && reload_completed"
6447  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6448   (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
6449{
6450  if (GET_CODE (operands[1]) == TRUNCATE)
6451    operands[1] = XEXP (operands[1], 0);
6452})
6453
6454;; ??? when a truncated input to a zero_extend is reloaded, reload will
6455;; reload the entire truncate expression.
6456(define_insn_and_split "*loaddi_trunc"
6457  [(set (match_operand 0 "any_register_operand" "=r")
6458	(truncate (match_operand:DI 1 "memory_operand" "m")))]
6459  "TARGET_SHMEDIA && reload_completed"
6460  "#"
6461  "TARGET_SHMEDIA && reload_completed"
6462  [(set (match_dup 0) (match_dup 1))]
6463{
6464  operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6465})
6466
6467(define_insn "zero_extendqidi2"
6468  [(set (match_operand:DI 0 "register_operand" "=r,r")
6469	(zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6470  "TARGET_SHMEDIA"
6471  "@
6472	andi	%1, 255, %0
6473	ld%M1.ub	%m1, %0"
6474  [(set_attr "type" "arith_media,load_media")
6475   (set (attr "highpart")
6476	(cond [(match_test "sh_contains_memref_p (insn)")
6477	       (const_string "user")]
6478	      (const_string "ignore")))])
6479
6480(define_expand "zero_extend<mode>si2"
6481  [(set (match_operand:SI 0 "arith_reg_dest")
6482	(zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
6483
6484(define_insn_and_split "*zero_extend<mode>si2_compact"
6485  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6486	(zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6487  "TARGET_SH1"
6488  "extu.<bw>	%1,%0"
6489  "&& can_create_pseudo_p ()"
6490  [(set (match_dup 0) (match_dup 2))]
6491{
6492  /* Sometimes combine fails to combine a T bit or negated T bit store to a
6493     reg with a following zero extension.  In the split pass after combine,
6494     try to figure out how the extended reg was set.  If it originated from
6495     the T bit we can replace the zero extension with a reg move, which will
6496     be eliminated.  Notice that this also helps the *cbranch_t splitter when
6497     it tries to post-combine tests and conditional branches, as it does not
6498     check for zero extensions.  */
6499  operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6500  if (operands[2] == NULL_RTX)
6501    FAIL;
6502}
6503  [(set_attr "type" "arith")])
6504
6505(define_insn "*zero_extendhisi2_media"
6506  [(set (match_operand:SI 0 "register_operand" "=r,r")
6507	(zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6508  "TARGET_SHMEDIA"
6509  "@
6510	#
6511	ld%M1.uw	%m1, %0"
6512  [(set_attr "type" "arith_media,load_media")
6513   (set (attr "highpart")
6514	(cond [(match_test "sh_contains_memref_p (insn)")
6515	       (const_string "user")]
6516	      (const_string "ignore")))])
6517
6518(define_split
6519  [(set (match_operand:SI 0 "register_operand" "")
6520	(zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6521  "TARGET_SHMEDIA && reload_completed"
6522  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6523   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
6524{
6525  rtx op1 = operands[1];
6526
6527  if (GET_CODE (op1) == TRUNCATE)
6528    op1 = XEXP (op1, 0);
6529  operands[2]
6530    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6531			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
6532})
6533
6534(define_insn "*zero_extendqisi2_media"
6535  [(set (match_operand:SI 0 "register_operand" "=r,r")
6536	(zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6537  "TARGET_SHMEDIA"
6538  "@
6539	andi	%1, 255, %0
6540	ld%M1.ub	%m1, %0"
6541  [(set_attr "type" "arith_media,load_media")
6542   (set (attr "highpart")
6543	(cond [(match_test "sh_contains_memref_p (insn)")
6544	       (const_string "user")]
6545	      (const_string "ignore")))])
6546
6547(define_insn "zero_extendqihi2"
6548  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6549	(zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6550  "TARGET_SH1"
6551  "extu.b	%1,%0"
6552  [(set_attr "type" "arith")])
6553
6554;; SH2A supports two zero extending load instructions: movu.b and movu.w.
6555;; They could also be used for simple memory addresses like @Rn by setting
6556;; the displacement value to zero.  However, doing so too early results in
6557;; missed opportunities for other optimizations such as post-inc or index
6558;; addressing loads.
6559;; We don't allow the zero extending loads to match during RTL expansion
6560;; (see zero_extend_operand predicate), as this would pessimize other
6561;; optimization opportunities such as bit extractions of unsigned mems,
6562;; where the zero extraction is irrelevant.  If the zero extracting mem
6563;; loads are emitted early it will be more difficult to change them back
6564;; to sign extending loads (which are preferred).
6565;; The combine pass will also try to combine mem loads and zero extends,
6566;; which is prevented by 'sh_legitimate_combined_insn'.
6567(define_insn "*zero_extend<mode>si2_disp_mem"
6568  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
6569	(zero_extend:SI
6570	  (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
6571  "TARGET_SH2A"
6572  "@
6573	movu.<bw>	%1,%0
6574	movu.<bw>	@(0,%t1),%0"
6575  [(set_attr "type" "load")
6576   (set_attr "length" "4")])
6577
6578;; Convert the zero extending loads in sequences such as:
6579;;	movu.b	@(1,r5),r0	movu.w	@(2,r5),r0
6580;;	mov.b	r0,@(1,r4)	mov.b	r0,@(1,r4)
6581;;
6582;; back to sign extending loads like:
6583;;	mov.b	@(1,r5),r0	mov.w	@(2,r5),r0
6584;;	mov.b	r0,@(1,r4)	mov.b	r0,@(1,r4)
6585;;
6586;; if the extension type is irrelevant.  The sign extending mov.{b|w} insn
6587;; is only 2 bytes in size if the displacement is {K04|K05}.
6588;; If the displacement is greater it doesn't matter, so we convert anyways.
6589(define_peephole2
6590  [(set (match_operand:SI 0 "arith_reg_dest" "")
6591	(zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
6592   (set (match_operand 2 "nonimmediate_operand" "")
6593	(match_operand 3 "arith_reg_operand" ""))]
6594  "TARGET_SH2A
6595   && REGNO (operands[0]) == REGNO (operands[3])
6596   && peep2_reg_dead_p (2, operands[0])
6597   && GET_MODE_SIZE (GET_MODE (operands[2]))
6598      <= GET_MODE_SIZE (GET_MODE (operands[1]))"
6599  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
6600   (set (match_dup 2) (match_dup 3))])
6601
6602;; Fold sequences such as
6603;;	mov.b	@r3,r7
6604;;	extu.b	r7,r7
6605;; into
6606;;	movu.b	@(0,r3),r7
6607;; This does not reduce the code size but the number of instructions is
6608;; halved, which results in faster code.
6609(define_peephole2
6610  [(set (match_operand:SI 0 "arith_reg_dest" "")
6611	(sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
6612   (set (match_operand:SI 2 "arith_reg_dest" "")
6613	(zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
6614  "TARGET_SH2A
6615   && GET_MODE (operands[1]) == GET_MODE (operands[3])
6616   && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
6617   && REGNO (operands[0]) == REGNO (operands[3])
6618   && (REGNO (operands[2]) == REGNO (operands[0])
6619       || peep2_reg_dead_p (2, operands[0]))"
6620  [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
6621{
6622  operands[4]
6623    = replace_equiv_address (operands[1],
6624			     gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
6625					   const0_rtx));
6626})
6627
6628;; -------------------------------------------------------------------------
6629;; Sign extension instructions
6630;; -------------------------------------------------------------------------
6631
6632;; ??? This should be a define expand.
6633;; ??? Or perhaps it should be dropped?
6634
6635;; convert_move generates good code for SH[1-4].
6636(define_insn "extendsidi2"
6637  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6638	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
6639  "TARGET_SHMEDIA"
6640  "@
6641	add.l	%1, r63, %0
6642	ld%M1.l	%m1, %0
6643	fmov.sl	%1, %0"
6644  [(set_attr "type" "arith_media,load_media,fpconv_media")
6645   (set (attr "highpart")
6646	(cond [(match_test "sh_contains_memref_p (insn)")
6647	       (const_string "user")]
6648	      (const_string "extend")))])
6649
6650(define_insn "extendhidi2"
6651  [(set (match_operand:DI 0 "register_operand" "=r,r")
6652	(sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6653  "TARGET_SHMEDIA"
6654  "@
6655	#
6656	ld%M1.w	%m1, %0"
6657  [(set_attr "type" "*,load_media")
6658   (set (attr "highpart")
6659	(cond [(match_test "sh_contains_memref_p (insn)")
6660	       (const_string "user")]
6661	      (const_string "ignore")))])
6662
6663(define_split
6664  [(set (match_operand:DI 0 "register_operand" "")
6665	(sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6666  "TARGET_SHMEDIA && reload_completed"
6667  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6668   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
6669{
6670  if (GET_CODE (operands[1]) == TRUNCATE)
6671    operands[1] = XEXP (operands[1], 0);
6672})
6673
6674(define_insn "extendqidi2"
6675  [(set (match_operand:DI 0 "register_operand" "=r,r")
6676	(sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6677  "TARGET_SHMEDIA"
6678  "@
6679	#
6680	ld%M1.b	%m1, %0"
6681  [(set_attr "type" "*,load_media")
6682   (set (attr "highpart")
6683	(cond [(match_test "sh_contains_memref_p (insn)")
6684	       (const_string "user")]
6685	      (const_string "ignore")))])
6686
6687(define_split
6688  [(set (match_operand:DI 0 "register_operand" "")
6689	(sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
6690  "TARGET_SHMEDIA && reload_completed"
6691  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
6692   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
6693{
6694  if (GET_CODE (operands[1]) == TRUNCATE)
6695    operands[1] = XEXP (operands[1], 0);
6696})
6697
6698(define_expand "extend<mode>si2"
6699  [(set (match_operand:SI 0 "arith_reg_dest")
6700	(sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
6701
6702(define_insn "*extendhisi2_media"
6703  [(set (match_operand:SI 0 "register_operand" "=r,r")
6704	(sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6705  "TARGET_SHMEDIA"
6706  "@
6707	#
6708	ld%M1.w	%m1, %0"
6709  [(set_attr "type" "arith_media,load_media")
6710   (set (attr "highpart")
6711	(cond [(match_test "sh_contains_memref_p (insn)")
6712	       (const_string "user")]
6713	      (const_string "ignore")))])
6714
6715(define_split
6716  [(set (match_operand:SI 0 "register_operand" "")
6717	(sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6718  "TARGET_SHMEDIA && reload_completed"
6719  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6720   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
6721{
6722  rtx op1 = operands[1];
6723  if (GET_CODE (op1) == TRUNCATE)
6724    op1 = XEXP (op1, 0);
6725  operands[2]
6726    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6727			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
6728})
6729
6730(define_insn_and_split "*extend<mode>si2_compact_reg"
6731  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6732	(sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6733  "TARGET_SH1"
6734  "exts.<bw>	%1,%0"
6735  "&& can_create_pseudo_p ()"
6736  [(set (match_dup 0) (match_dup 2))]
6737{
6738  /* Sometimes combine fails to combine a T bit or negated T bit store to a
6739     reg with a following sign extension.  In the split pass after combine,
6740     try to figure the extended reg was set.  If it originated from the T
6741     bit we can replace the sign extension with a reg move, which will be
6742     eliminated.  */
6743  operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6744  if (operands[2] == NULL_RTX)
6745    FAIL;
6746}
6747  [(set_attr "type" "arith")])
6748
6749;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6750;; See movqi insns.
6751(define_insn "*extend<mode>si2_compact_mem_disp"
6752  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6753	(sign_extend:SI
6754	  (mem:QIHI
6755	    (plus:SI
6756	      (match_operand:SI 1 "arith_reg_operand" "%r,r")
6757	      (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
6758  "TARGET_SH1 && ! TARGET_SH2A
6759   && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6760  "@
6761	mov.<bw>	@(%O2,%1),%0
6762	mov.<bw>	@%1,%0"
6763  [(set_attr "type" "load")])
6764
6765(define_insn "*extend<mode>si2_compact_mem_disp"
6766  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6767	(sign_extend:SI
6768	  (mem:QIHI
6769	    (plus:SI
6770	      (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6771	      (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
6772  "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6773  "@
6774	mov.<bw>	@(%O2,%1),%0
6775	mov.<bw>	@%1,%0
6776	mov.<bw>	@(%O2,%1),%0"
6777  [(set_attr "type" "load")
6778   (set_attr "length" "2,2,4")])
6779
6780;; The *_snd patterns will take care of other QImode/HImode addressing
6781;; modes than displacement addressing.  They must be defined _after_ the
6782;; displacement addressing patterns.  Otherwise the displacement addressing
6783;; patterns will not be picked.
6784(define_insn "*extend<mode>si2_compact_snd"
6785  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6786	(sign_extend:SI
6787	  (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
6788  "TARGET_SH1"
6789  "mov.<bw>	%1,%0"
6790  [(set_attr "type" "load")])
6791
6792(define_insn "*extendqisi2_media"
6793  [(set (match_operand:SI 0 "register_operand" "=r,r")
6794	(sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6795  "TARGET_SHMEDIA"
6796  "@
6797	#
6798	ld%M1.b	%m1, %0"
6799  [(set_attr "type" "arith_media,load_media")
6800   (set (attr "highpart")
6801	(cond [(match_test "sh_contains_memref_p (insn)")
6802	       (const_string "user")]
6803	      (const_string "ignore")))])
6804
6805(define_split
6806  [(set (match_operand:SI 0 "register_operand" "")
6807	(sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
6808  "TARGET_SHMEDIA && reload_completed"
6809  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6810   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6811{
6812  rtx op1 = operands[1];
6813  if (GET_CODE (op1) == TRUNCATE)
6814    op1 = XEXP (op1, 0);
6815  operands[2]
6816    = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6817			   subreg_lowpart_offset (SImode, GET_MODE (op1)));
6818})
6819
6820(define_expand "extendqihi2"
6821  [(set (match_operand:HI 0 "arith_reg_dest")
6822	(sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))]
6823  "TARGET_SH1")
6824
6825(define_insn "*extendqihi2_compact_reg"
6826  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6827	(sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6828  "TARGET_SH1"
6829  "exts.b	%1,%0"
6830  [(set_attr "type" "arith")])
6831
6832;; It would seem useful to combine the truncXi patterns into the movXi
6833;; patterns, but unary operators are ignored when matching constraints,
6834;; so we need separate patterns.
6835(define_insn "truncdisi2"
6836  [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
6837	(truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6838  "TARGET_SHMEDIA"
6839  "@
6840	add.l	%1, r63, %0
6841	st%M0.l	%m0, %1
6842	fst%M0.s	%m0, %T1
6843	fmov.ls	%1, %0
6844	fmov.sl	%T1, %0
6845	fmov.s	%T1, %0"
6846  [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,
6847		     fpconv_media,fmove_media")
6848   (set (attr "highpart")
6849	(cond [(match_test "sh_contains_memref_p (insn)")
6850	       (const_string "user")]
6851	      (const_string "extend")))])
6852
6853(define_insn "truncdihi2"
6854  [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
6855	(truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6856  "TARGET_SHMEDIA"
6857{
6858  static const char* alt[] =
6859  {
6860       "shlli	%1,48,%0"	"\n"
6861    "	shlri	%0,48,%0",
6862
6863       "st%M0.w	%m0, %1"
6864  };
6865  return alt[which_alternative];
6866}
6867  [(set_attr "type"   "arith_media,store_media")
6868   (set_attr "length" "8,4")
6869   (set (attr "highpart")
6870	(cond [(match_test "sh_contains_memref_p (insn)")
6871	       (const_string "user")]
6872	      (const_string "extend")))])
6873
6874; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6875; Because we use zero extension, we can't provide signed QImode compares
6876; using a simple compare or conditional branch insn.
6877(define_insn "truncdiqi2"
6878  [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6879	(truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6880  "TARGET_SHMEDIA"
6881  "@
6882	andi	%1, 255, %0
6883	st%M0.b	%m0, %1"
6884  [(set_attr "type"   "arith_media,store")
6885   (set (attr "highpart")
6886	(cond [(match_test "sh_contains_memref_p (insn)")
6887	       (const_string "user")]
6888	      (const_string "extend")))])
6889
6890;; -------------------------------------------------------------------------
6891;; Move instructions
6892;; -------------------------------------------------------------------------
6893
6894;; define push and pop so it is easy for sh.c
6895;; We can't use push and pop on SHcompact because the stack must always
6896;; be 8-byte aligned.
6897(define_expand "push"
6898  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6899	(match_operand:SI 0 "register_operand" "r,l,x"))]
6900  "TARGET_SH1 && ! TARGET_SH5"
6901  "")
6902
6903(define_expand "pop"
6904  [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6905	(mem:SI (post_inc:SI (reg:SI SP_REG))))]
6906  "TARGET_SH1 && ! TARGET_SH5"
6907  "")
6908
6909(define_expand "push_e"
6910  [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6911		   (match_operand:SF 0 "" ""))
6912	      (use (reg:SI FPSCR_MODES_REG))
6913	      (clobber (scratch:SI))])]
6914  "TARGET_SH1 && ! TARGET_SH5"
6915  "")
6916
6917(define_insn "push_fpul"
6918  [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6919  "TARGET_SH2E && ! TARGET_SH5"
6920  "sts.l	fpul,@-r15"
6921  [(set_attr "type" "fstore")
6922   (set_attr "late_fp_use" "yes")
6923   (set_attr "hit_stack" "yes")])
6924
6925;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6926;; so use that.
6927(define_expand "push_4"
6928  [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6929		   (match_operand:DF 0 "" ""))
6930	      (use (reg:SI FPSCR_MODES_REG))
6931	      (clobber (scratch:SI))])]
6932  "TARGET_SH1 && ! TARGET_SH5"
6933  "")
6934
6935(define_expand "pop_e"
6936  [(parallel [(set (match_operand:SF 0 "" "")
6937	      (mem:SF (post_inc:SI (reg:SI SP_REG))))
6938	      (use (reg:SI FPSCR_MODES_REG))
6939	      (clobber (scratch:SI))])]
6940  "TARGET_SH1 && ! TARGET_SH5"
6941  "")
6942
6943(define_insn "pop_fpul"
6944  [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6945  "TARGET_SH2E && ! TARGET_SH5"
6946  "lds.l	@r15+,fpul"
6947  [(set_attr "type" "load")
6948   (set_attr "hit_stack" "yes")])
6949
6950(define_expand "pop_4"
6951  [(parallel [(set (match_operand:DF 0 "" "")
6952		   (mem:DF (post_inc:SI (reg:SI SP_REG))))
6953	      (use (reg:SI FPSCR_MODES_REG))
6954	      (clobber (scratch:SI))])]
6955  "TARGET_SH1 && ! TARGET_SH5"
6956  "")
6957
6958(define_expand "push_fpscr"
6959  [(const_int 0)]
6960  "TARGET_SH2E"
6961{
6962  add_reg_note (
6963    emit_insn (
6964      gen_sts_fpscr (
6965	gen_frame_mem (SImode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx)))),
6966    REG_INC, stack_pointer_rtx);
6967  DONE;
6968})
6969
6970(define_expand "pop_fpscr"
6971  [(const_int 0)]
6972  "TARGET_SH2E"
6973{
6974  add_reg_note (
6975    emit_insn (
6976      gen_lds_fpscr (
6977	gen_frame_mem (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)))),
6978    REG_INC, stack_pointer_rtx);
6979  DONE;
6980})
6981
6982;; The clrt and sett patterns can happen as the result of optimization and
6983;; insn expansion.
6984;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6985;; In this case they might not disappear completely, because the T reg is
6986;; a fixed hard reg.
6987;; When DImode operations that use the T reg as carry/borrow are split into
6988;; individual SImode operations, the T reg is usually cleared before the
6989;; first SImode insn.
6990(define_insn "clrt"
6991  [(set (reg:SI T_REG) (const_int 0))]
6992  "TARGET_SH1"
6993  "clrt"
6994  [(set_attr "type" "mt_group")])
6995
6996(define_insn "sett"
6997  [(set (reg:SI T_REG) (const_int 1))]
6998  "TARGET_SH1"
6999  "sett"
7000  [(set_attr "type" "mt_group")])
7001
7002;; Use the combine pass to transform sequences such as
7003;;	mov	r5,r0
7004;;	add	#1,r0
7005;;	shll2	r0
7006;;	mov.l	@(r0,r4),r0
7007;; into
7008;;	shll2	r5
7009;;	add	r4,r5
7010;;	mov.l	@(4,r5),r0
7011;;
7012;; See also PR 39423.
7013;; Notice that these patterns have a T_REG clobber, because the shift
7014;; sequence that will be split out might clobber the T_REG.  Ideally, the
7015;; clobber would be added conditionally, depending on the result of
7016;; sh_ashlsi_clobbers_t_reg_p.  When splitting out the shifts we must go
7017;; through the ashlsi3 expander in order to get the right shift insn --
7018;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
7019;; FIXME: Combine never tries this kind of patterns for DImode.
7020(define_insn_and_split "*movsi_index_disp_load"
7021  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7022	(match_operand:SI 1 "mem_index_disp_operand" "m"))
7023   (clobber (reg:SI T_REG))]
7024  "TARGET_SH1"
7025  "#"
7026  "&& can_create_pseudo_p ()"
7027  [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
7028   (set (match_dup 0) (match_dup 7))]
7029{
7030  rtx mem = operands[1];
7031  rtx plus0_rtx = XEXP (mem, 0);
7032  rtx plus1_rtx = XEXP (plus0_rtx, 0);
7033  rtx mult_rtx = XEXP (plus1_rtx, 0);
7034
7035  operands[1] = XEXP (mult_rtx, 0);
7036  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
7037  operands[3] = XEXP (plus1_rtx, 1);
7038  operands[4] = XEXP (plus0_rtx, 1);
7039  operands[5] = gen_reg_rtx (SImode);
7040  operands[6] = gen_reg_rtx (SImode);
7041  operands[7] =
7042    replace_equiv_address (mem,
7043			   gen_rtx_PLUS (SImode, operands[6], operands[4]));
7044
7045  emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
7046})
7047
7048(define_insn_and_split "*movhi_index_disp_load"
7049  [(set (match_operand:SI 0 "arith_reg_dest")
7050	(SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
7051   (clobber (reg:SI T_REG))]
7052  "TARGET_SH1"
7053  "#"
7054  "&& can_create_pseudo_p ()"
7055  [(const_int 0)]
7056{
7057  rtx mem = operands[1];
7058  rtx plus0_rtx = XEXP (mem, 0);
7059  rtx plus1_rtx = XEXP (plus0_rtx, 0);
7060  rtx mult_rtx = XEXP (plus1_rtx, 0);
7061
7062  rtx op_1 = XEXP (mult_rtx, 0);
7063  rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
7064  rtx op_3 = XEXP (plus1_rtx, 1);
7065  rtx op_4 = XEXP (plus0_rtx, 1);
7066  rtx op_5 = gen_reg_rtx (SImode);
7067  rtx op_6 = gen_reg_rtx (SImode);
7068  rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
7069
7070  emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
7071  emit_insn (gen_addsi3 (op_6, op_5, op_3));
7072
7073  if (<CODE> == SIGN_EXTEND)
7074    {
7075      emit_insn (gen_extendhisi2 (operands[0], op_7));
7076      DONE;
7077    }
7078  else if (<CODE> == ZERO_EXTEND)
7079    {
7080      /* On SH2A the movu.w insn can be used for zero extending loads.  */
7081      if (TARGET_SH2A)
7082	emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
7083      else
7084	{
7085	  emit_insn (gen_extendhisi2 (operands[0], op_7));
7086	  emit_insn (gen_zero_extendhisi2 (operands[0],
7087				           gen_lowpart (HImode, operands[0])));
7088	}
7089      DONE;
7090    }
7091  else
7092    FAIL;
7093})
7094
7095(define_insn_and_split "*mov<mode>_index_disp_store"
7096  [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
7097	(match_operand:HISI 1 "arith_reg_operand" "r"))
7098   (clobber (reg:SI T_REG))]
7099  "TARGET_SH1"
7100  "#"
7101  "&& can_create_pseudo_p ()"
7102  [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
7103   (set (match_dup 7) (match_dup 1))]
7104{
7105  rtx mem = operands[0];
7106  rtx plus0_rtx = XEXP (mem, 0);
7107  rtx plus1_rtx = XEXP (plus0_rtx, 0);
7108  rtx mult_rtx = XEXP (plus1_rtx, 0);
7109
7110  operands[0] = XEXP (mult_rtx, 0);
7111  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
7112  operands[3] = XEXP (plus1_rtx, 1);
7113  operands[4] = XEXP (plus0_rtx, 1);
7114  operands[5] = gen_reg_rtx (SImode);
7115  operands[6] = gen_reg_rtx (SImode);
7116  operands[7] =
7117    replace_equiv_address (mem,
7118			   gen_rtx_PLUS (SImode, operands[6], operands[4]));
7119
7120  emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
7121})
7122
7123;; t/r must come after r/r, lest reload will try to reload stuff like
7124;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
7125;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
7126(define_insn "movsi_i"
7127  [(set (match_operand:SI 0 "general_movdst_operand"
7128	    "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
7129	(match_operand:SI 1 "general_movsrc_operand"
7130	 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
7131  "TARGET_SH1
7132   && ! TARGET_SH2E
7133   && ! TARGET_SH2A
7134   && (register_operand (operands[0], SImode)
7135       || register_operand (operands[1], SImode))"
7136  "@
7137	mov.l	%1,%0
7138	mov	%1,%0
7139	mov	%1,%0
7140	mov.l	%1,%0
7141	sts	%1,%0
7142	sts	%1,%0
7143	mov.l	%1,%0
7144	sts.l	%1,%0
7145	sts.l	%1,%0
7146	lds	%1,%0
7147	lds	%1,%0
7148	lds.l	%1,%0
7149	lds.l	%1,%0
7150	fake	%1,%0"
7151  [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,
7152		     pstore,gp_mac,prset,mem_mac,pload,pcload_si")
7153   (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
7154
7155;; t/r must come after r/r, lest reload will try to reload stuff like
7156;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
7157;; ??? This allows moves from macl to fpul to be recognized, but these moves
7158;; will require a reload.
7159;; ??? We can't include f/f because we need the proper FPSCR setting when
7160;; TARGET_FMOVD is in effect, and mode switching is done before reload.
7161(define_insn "movsi_ie"
7162  [(set (match_operand:SI 0 "general_movdst_operand"
7163	    "=r,r,r,r,r,r,r,r,mr,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
7164	(match_operand:SI 1 "general_movsrc_operand"
7165	 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
7166  "(TARGET_SH2E || TARGET_SH2A)
7167   && ((register_operand (operands[0], SImode)
7168	&& !fpscr_operand (operands[0], SImode))
7169       || (register_operand (operands[1], SImode)
7170	   && !fpscr_operand (operands[1], SImode)))"
7171  "@
7172	mov.l	%1,%0
7173	mov	%1,%0
7174	mov	%1,%0
7175	movi20	%1,%0
7176	movi20s	%1,%0
7177	mov.l	%1,%0
7178	sts	%1,%0
7179	sts	%1,%0
7180	mov.l	%1,%0
7181	sts.l	%1,%0
7182	sts.l	%1,%0
7183	lds	%1,%0
7184	lds	%1,%0
7185	lds.l	%1,%0
7186	lds.l	%1,%0
7187	lds.l	%1,%0
7188	sts.l	%1,%0
7189	fake	%1,%0
7190	lds	%1,%0
7191	sts	%1,%0
7192	fsts	fpul,%0
7193	flds	%1,fpul
7194	fmov	%1,%0
7195	! move optimized away"
7196  [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,
7197		     mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,
7198		     pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
7199   (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
7200   (set_attr_alternative "length"
7201     [(const_int 2)
7202      (const_int 2)
7203      (const_int 2)
7204      (const_int 4)
7205      (const_int 4)
7206      (if_then_else
7207	(match_test "TARGET_SH2A")
7208	(const_int 4) (const_int 2))
7209      (const_int 2)
7210      (const_int 2)
7211      (if_then_else
7212	(match_test "TARGET_SH2A")
7213	(const_int 4) (const_int 2))
7214      (const_int 2)
7215      (const_int 2)
7216      (const_int 2)
7217      (const_int 2)
7218      (const_int 2)
7219      (const_int 2)
7220      (const_int 2)
7221      (const_int 2)
7222      (const_int 2)
7223      (const_int 2)
7224      (const_int 2)
7225      (const_int 2)
7226      (const_int 2)
7227      (const_int 2)
7228      (const_int 0)])])
7229
7230(define_insn "movsi_i_lowpart"
7231  [(set (strict_low_part
7232	  (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
7233	(match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
7234   "TARGET_SH1
7235    && (register_operand (operands[0], SImode)
7236        || register_operand (operands[1], SImode))"
7237  "@
7238	mov.l	%1,%0
7239	mov	%1,%0
7240	mov	%1,%0
7241	mov.l	%1,%0
7242	sts	%1,%0
7243	sts	%1,%0
7244	mov.l	%1,%0
7245	fake	%1,%0"
7246  [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
7247
7248(define_insn_and_split "load_ra"
7249  [(set (match_operand:SI 0 "general_movdst_operand" "")
7250	(unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
7251  "TARGET_SH1"
7252  "#"
7253  "&& ! currently_expanding_to_rtl"
7254  [(set (match_dup 0) (match_dup 1))]
7255{
7256  if (TARGET_SHCOMPACT && crtl->saves_all_registers)
7257    operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
7258})
7259
7260;; The '?'s in the following constraints may not reflect the time taken
7261;; to perform the move. They are there to discourage the use of floating-
7262;; point registers for storing integer values.
7263(define_insn "*movsi_media"
7264  [(set (match_operand:SI 0 "general_movdst_operand"
7265	        "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
7266	(match_operand:SI 1 "general_movsrc_operand"
7267	 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7268  "TARGET_SHMEDIA_FPU
7269   && (register_operand (operands[0], SImode)
7270       || sh_register_operand (operands[1], SImode)
7271       || GET_CODE (operands[1]) == TRUNCATE)"
7272  "@
7273	add.l	%1, r63, %0
7274	movi	%1, %0
7275	#
7276	ld%M1.l	%m1, %0
7277	st%M0.l	%m0, %N1
7278	fld%M1.s	%m1, %0
7279	fst%M0.s	%m0, %1
7280	fmov.ls	%N1, %0
7281	fmov.sl	%1, %0
7282	fmov.s	%1, %0
7283	ptabs	%1, %0
7284	gettr	%1, %0
7285	pt	%1, %0"
7286  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,
7287		       fload_media,fstore_media,fload_media,fpconv_media,
7288		       fmove_media,ptabs_media,gettr_media,pt_media")
7289   (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
7290   (set (attr "highpart")
7291	(cond [(match_test "sh_contains_memref_p (insn)")
7292	       (const_string "user")]
7293	      (const_string "ignore")))])
7294
7295(define_insn "*movsi_media_nofpu"
7296  [(set (match_operand:SI 0 "general_movdst_operand"
7297	        "=r,r,r,r,m,*b,r,*b")
7298	(match_operand:SI 1 "general_movsrc_operand"
7299	 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
7300  "TARGET_SHMEDIA
7301   && (register_operand (operands[0], SImode)
7302       || sh_register_operand (operands[1], SImode)
7303       || GET_CODE (operands[1]) == TRUNCATE)"
7304  "@
7305	add.l	%1, r63, %0
7306	movi	%1, %0
7307	#
7308	ld%M1.l	%m1, %0
7309	st%M0.l	%m0, %N1
7310	ptabs	%1, %0
7311	gettr	%1, %0
7312	pt	%1, %0"
7313  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7314		     ptabs_media,gettr_media,pt_media")
7315   (set_attr "length" "4,4,8,4,4,4,4,12")
7316   (set (attr "highpart")
7317	(cond [(match_test "sh_contains_memref_p (insn)")
7318	       (const_string "user")]
7319	      (const_string "ignore")))])
7320
7321(define_expand "movsi_const"
7322  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7323	(const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
7324			      (const_int 16)] UNSPEC_EXTRACT_S16)))
7325   (set (match_dup 0)
7326	(ior:SI (ashift:SI (match_dup 0) (const_int 16))
7327		(const:SI (unspec:SI [(match_dup 1)
7328				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
7329  "TARGET_SHMEDIA && reload_completed
7330   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7331{
7332  if (GET_CODE (operands[1]) == LABEL_REF
7333      && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
7334    LABEL_NUSES (XEXP (operands[1], 0)) += 2;
7335  else if (GOTOFF_P (operands[1]))
7336    {
7337      rtx unspec = XEXP (operands[1], 0);
7338
7339      if (! UNSPEC_GOTOFF_P (unspec))
7340	{
7341	  unspec = XEXP (unspec, 0);
7342	  if (! UNSPEC_GOTOFF_P (unspec))
7343	    abort ();
7344	}
7345      if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
7346	  && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
7347	LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
7348    }
7349})
7350
7351(define_expand "movsi_const_16bit"
7352  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7353	(const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
7354			      (const_int 0)] UNSPEC_EXTRACT_S16)))]
7355  "TARGET_SHMEDIA && flag_pic && reload_completed
7356   && GET_CODE (operands[1]) == SYMBOL_REF"
7357  "")
7358
7359(define_split
7360  [(set (match_operand:SI 0 "arith_reg_dest" "")
7361	(match_operand:SI 1 "immediate_operand" ""))]
7362  "TARGET_SHMEDIA && reload_completed
7363   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7364  [(const_int 0)]
7365{
7366  rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
7367
7368  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7369
7370  DONE;
7371})
7372
7373(define_split
7374  [(set (match_operand:SI 0 "register_operand" "")
7375	(match_operand:SI 1 "immediate_operand" ""))]
7376  "TARGET_SHMEDIA && reload_completed
7377   && ((CONST_INT_P (operands[1])
7378	&& ! satisfies_constraint_I16 (operands[1]))
7379       || GET_CODE (operands[1]) == CONST_DOUBLE)"
7380  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7381
7382(define_expand "movsi"
7383  [(set (match_operand:SI 0 "general_movdst_operand" "")
7384	(match_operand:SI 1 "general_movsrc_operand" ""))]
7385  ""
7386{
7387  prepare_move_operands (operands, SImode);
7388})
7389
7390(define_expand "ic_invalidate_line"
7391  [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
7392				(match_dup 1)] UNSPEC_ICACHE)
7393	      (clobber (scratch:SI))])]
7394  "TARGET_HARD_SH4 || TARGET_SH5"
7395{
7396  if (TARGET_SHMEDIA)
7397    {
7398      emit_insn (gen_ic_invalidate_line_media (operands[0]));
7399      DONE;
7400    }
7401  else if (TARGET_SHCOMPACT)
7402    {
7403      operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC).sym;
7404      operands[1] = force_reg (Pmode, operands[1]);
7405      emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
7406      DONE;
7407    }
7408  else if (TARGET_SH4A || TARGET_SH4_300)
7409    {
7410      emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
7411      DONE;
7412    }
7413  operands[0] = force_reg (Pmode, operands[0]);
7414  operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
7415							       Pmode)));
7416})
7417
7418;; The address %0 is assumed to be 4-aligned at least.  Thus, by ORing
7419;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
7420;; the requirement *1*00 for associative address writes.  The alignment of
7421;; %0 implies that its least significant bit is cleared,
7422;; thus we clear the V bit of a matching entry if there is one.
7423(define_insn "ic_invalidate_line_i"
7424  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
7425		     (match_operand:SI 1 "register_operand" "r")]
7426		     UNSPEC_ICACHE)
7427   (clobber (match_scratch:SI 2 "=&r"))]
7428  "TARGET_HARD_SH4"
7429{
7430  return       "ocbwb	@%0"	"\n"
7431	 "	extu.w	%0,%2"	"\n"
7432	 "	or	%1,%2"	"\n"
7433	 "	mov.l	%0,@%2";
7434}
7435  [(set_attr "length" "8")
7436   (set_attr "type" "cwb")])
7437
7438(define_insn "ic_invalidate_line_sh4a"
7439  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
7440		    UNSPEC_ICACHE)]
7441  "TARGET_SH4A || TARGET_SH4_300"
7442{
7443  return       "ocbwb	@%0"	"\n"
7444	 "	synco"		"\n"
7445	 "	icbi	@%0";
7446}
7447  [(set_attr "length" "16")	;; FIXME: Why 16 and not 6?  Looks like typo.
7448   (set_attr "type" "cwb")])
7449
7450;; ??? could make arg 0 an offsettable memory operand to allow to save
7451;; an add in the code that calculates the address.
7452(define_insn "ic_invalidate_line_media"
7453  [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
7454		    UNSPEC_ICACHE)]
7455  "TARGET_SHMEDIA"
7456{
7457  return       "ocbwb	%0,0"	"\n"
7458	 "	synco"		"\n"
7459	 "	icbi	%0,0"	"\n"
7460	 "	synci";
7461}
7462  [(set_attr "length" "16")
7463   (set_attr "type" "invalidate_line_media")])
7464
7465(define_insn "ic_invalidate_line_compact"
7466  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
7467		     (match_operand:SI 1 "register_operand" "r")]
7468		    UNSPEC_ICACHE)
7469   (clobber (reg:SI PR_REG))]
7470  "TARGET_SHCOMPACT"
7471  "jsr @%1%#"
7472  [(set_attr "type" "sfunc")
7473   (set_attr "needs_delay_slot" "yes")])
7474
7475(define_expand "initialize_trampoline"
7476  [(match_operand:SI 0 "" "")
7477   (match_operand:SI 1 "" "")
7478   (match_operand:SI 2 "" "")]
7479  "TARGET_SHCOMPACT"
7480{
7481  rtx sfun, tramp;
7482
7483  tramp = force_reg (Pmode, operands[0]);
7484  sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
7485					    SFUNC_STATIC).sym);
7486  emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
7487  emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
7488
7489  emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
7490  DONE;
7491})
7492
7493(define_insn "initialize_trampoline_compact"
7494  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
7495		     (match_operand:SI 1 "register_operand" "r")
7496		     (reg:SI R2_REG) (reg:SI R3_REG)]
7497		    UNSPEC_INIT_TRAMP)
7498
7499   (clobber (reg:SI PR_REG))]
7500  "TARGET_SHCOMPACT"
7501  "jsr @%1%#"
7502  [(set_attr "type" "sfunc")
7503   (set_attr "needs_delay_slot" "yes")])
7504
7505(define_expand "mov<mode>"
7506  [(set (match_operand:QIHI 0 "general_movdst_operand")
7507	(match_operand:QIHI 1 "general_movsrc_operand"))]
7508  ""
7509{
7510 if (can_create_pseudo_p () && CONST_INT_P (operands[1])
7511    && REG_P (operands[0]) && REGNO (operands[0]) != R0_REG)
7512    {
7513        rtx reg = gen_reg_rtx(SImode);
7514        emit_move_insn (reg, operands[1]);
7515        operands[1] = gen_lowpart (<MODE>mode, reg);
7516    }
7517
7518  prepare_move_operands (operands, <MODE>mode);
7519})
7520
7521;; Specifying the displacement addressing load / store patterns separately
7522;; before the generic movqi / movhi pattern allows controlling the order
7523;; in which load / store insns are selected in a more fine grained way.
7524;; FIXME: The non-SH2A and SH2A variants should be combined by adding
7525;; "enabled" attribute as it is done in other targets.
7526(define_insn "*mov<mode>_store_mem_disp04"
7527  [(set (mem:QIHI
7528	  (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
7529		   (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
7530	(match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
7531  "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
7532  "@
7533	mov.<bw>	%2,@(%O1,%0)
7534	mov.<bw>	%2,@%0"
7535  [(set_attr "type" "store")])
7536
7537(define_insn "*mov<mode>_store_mem_disp12"
7538  [(set (mem:QIHI
7539	  (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
7540		   (match_operand:SI 1 "const_int_operand" "<disp12>")))
7541	(match_operand:QIHI 2 "arith_reg_operand" "r"))]
7542  "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
7543  "mov.<bw>	%2,@(%O1,%0)"
7544  [(set_attr "type" "store")
7545   (set_attr "length" "4")])
7546
7547(define_insn "*mov<mode>_load_mem_disp04"
7548  [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
7549	(mem:QIHI
7550	  (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
7551		   (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
7552  "TARGET_SH1 && ! TARGET_SH2A
7553   && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
7554  "@
7555	mov.<bw>	@(%O2,%1),%0
7556	mov.<bw>	@%1,%0"
7557  [(set_attr "type" "load")])
7558
7559(define_insn "*mov<mode>_load_mem_disp12"
7560  [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
7561	(mem:QIHI
7562	  (plus:SI
7563	    (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
7564	    (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
7565  "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
7566  "@
7567	mov.<bw>	@(%O2,%1),%0
7568	mov.<bw>	@%1,%0
7569	mov.<bw>	@(%O2,%1),%0"
7570  [(set_attr "type" "load")
7571   (set_attr "length" "2,2,4")])
7572
7573;; The order of the constraint alternatives is important here.
7574;; Q/r has to come first, otherwise PC relative loads might wrongly get
7575;; placed into delay slots.  Since there is no QImode PC relative load, the
7576;; Q constraint and general_movsrc_operand will reject it for QImode.
7577;; The Sid/Ssd alternatives should come before Sdd in order to avoid
7578;; a preference of using r0 als the register operand for addressing modes
7579;; other than displacement addressing.
7580;; The Sdd alternatives allow only r0 as register operand, even though on
7581;; SH2A any register could be allowed by switching to a 32 bit insn.
7582;; Generally sticking to the r0 is preferrable, since it generates smaller
7583;; code.  Obvious r0 reloads can then be eliminated with a peephole on SH2A.
7584(define_insn "*mov<mode>"
7585  [(set (match_operand:QIHI 0 "general_movdst_operand"
7586			      "=r,r,r,Sid,^zr,Ssd,r,  Sdd,z,  r,l")
7587	(match_operand:QIHI 1 "general_movsrc_operand"
7588			       "Q,r,i,^zr,Sid,r,  Ssd,z,  Sdd,l,r"))]
7589  "TARGET_SH1
7590   && (arith_reg_operand (operands[0], <MODE>mode)
7591       || arith_reg_operand (operands[1], <MODE>mode))"
7592  "@
7593	mov.<bw>	%1,%0
7594	mov	%1,%0
7595	mov	%1,%0
7596	mov.<bw>	%1,%0
7597	mov.<bw>	%1,%0
7598	mov.<bw>	%1,%0
7599	mov.<bw>	%1,%0
7600	mov.<bw>	%1,%0
7601	mov.<bw>	%1,%0
7602	sts	%1,%0
7603	lds	%1,%0"
7604  [(set_attr "type" "pcload,move,movi8,store,load,store,load,store,load,prget,prset")
7605   (set (attr "length")
7606	(cond [(and (match_operand 0 "displacement_mem_operand")
7607		    (not (match_operand 0 "short_displacement_mem_operand")))
7608	       (const_int 4)
7609	       (and (match_operand 1 "displacement_mem_operand")
7610		    (not (match_operand 1 "short_displacement_mem_operand")))
7611	       (const_int 4)]
7612	      (const_int 2)))])
7613
7614(define_insn "*movqi_media"
7615  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
7616	(match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
7617  "TARGET_SHMEDIA
7618   && (arith_reg_operand (operands[0], QImode)
7619       || extend_reg_or_0_operand (operands[1], QImode))"
7620  "@
7621	add.l	%1, r63, %0
7622	movi	%1, %0
7623	ld%M1.ub	%m1, %0
7624	st%M0.b	%m0, %N1"
7625  [(set_attr "type" "arith_media,arith_media,load_media,store_media")
7626   (set (attr "highpart")
7627	(cond [(match_test "sh_contains_memref_p (insn)")
7628	       (const_string "user")]
7629	      (const_string "ignore")))])
7630
7631(define_expand "reload_inqi"
7632  [(set (match_operand:SI 2 "" "=&r")
7633	(match_operand:QI 1 "inqhi_operand" ""))
7634   (set (match_operand:QI 0 "arith_reg_operand" "=r")
7635	(truncate:QI (match_dup 3)))]
7636  "TARGET_SHMEDIA"
7637{
7638  rtx inner = XEXP (operands[1], 0);
7639  int regno = REGNO (inner);
7640
7641  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7642  operands[1] = gen_rtx_REG (SImode, regno);
7643  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7644})
7645
7646(define_insn "*movhi_media"
7647  [(set (match_operand:HI 0 "general_movdst_operand"     "=r,r,r,r,m")
7648	(match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
7649  "TARGET_SHMEDIA
7650   && (arith_reg_operand (operands[0], HImode)
7651       || arith_reg_or_0_operand (operands[1], HImode))"
7652  "@
7653	add.l	%1, r63, %0
7654	movi	%1, %0
7655	#
7656	ld%M1.w	%m1, %0
7657	st%M0.w	%m0, %N1"
7658  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
7659   (set (attr "highpart")
7660	(cond [(match_test "sh_contains_memref_p (insn)")
7661	       (const_string "user")]
7662	      (const_string "ignore")))])
7663
7664(define_split
7665  [(set (match_operand:HI 0 "register_operand" "")
7666	(match_operand:HI 1 "immediate_operand" ""))]
7667  "TARGET_SHMEDIA && reload_completed
7668   && ! satisfies_constraint_I16 (operands[1])"
7669  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7670
7671(define_expand "reload_inhi"
7672  [(set (match_operand:SI 2 "" "=&r")
7673	(match_operand:HI 1 "inqhi_operand" ""))
7674   (set (match_operand:HI 0 "arith_reg_operand" "=r")
7675	(truncate:HI (match_dup 3)))]
7676  "TARGET_SHMEDIA"
7677{
7678  rtx inner = XEXP (operands[1], 0);
7679  int regno = REGNO (inner);
7680
7681  regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7682  operands[1] = gen_rtx_REG (SImode, regno);
7683  operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7684})
7685
7686;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
7687;; compiled with -m2 -ml -O3 -funroll-loops
7688(define_insn "*movdi_i"
7689  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
7690	(match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
7691  "TARGET_SH1
7692   && (arith_reg_operand (operands[0], DImode)
7693       || arith_reg_operand (operands[1], DImode))"
7694{
7695  return output_movedouble (insn, operands, DImode);
7696}
7697  [(set_attr "length" "4")
7698   (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
7699
7700;; If the output is a register and the input is memory or a register, we have
7701;; to be careful and see which word needs to be loaded first.
7702(define_split
7703  [(set (match_operand:DI 0 "general_movdst_operand" "")
7704	(match_operand:DI 1 "general_movsrc_operand" ""))]
7705  "TARGET_SH1 && reload_completed"
7706  [(set (match_dup 2) (match_dup 3))
7707   (set (match_dup 4) (match_dup 5))]
7708{
7709  int regno;
7710
7711  if ((MEM_P (operands[0])
7712       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7713      || (MEM_P (operands[1])
7714	  && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7715    FAIL;
7716
7717  switch (GET_CODE (operands[0]))
7718    {
7719    case REG:
7720      regno = REGNO (operands[0]);
7721      break;
7722    case SUBREG:
7723      regno = subreg_regno (operands[0]);
7724      break;
7725    case MEM:
7726      regno = -1;
7727      break;
7728    default:
7729      gcc_unreachable ();
7730    }
7731
7732  if (regno == -1 || ! refers_to_regno_p (regno, operands[1]))
7733    {
7734      operands[2] = operand_subword (operands[0], 0, 0, DImode);
7735      operands[3] = operand_subword (operands[1], 0, 0, DImode);
7736      operands[4] = operand_subword (operands[0], 1, 0, DImode);
7737      operands[5] = operand_subword (operands[1], 1, 0, DImode);
7738    }
7739  else
7740    {
7741      operands[2] = operand_subword (operands[0], 1, 0, DImode);
7742      operands[3] = operand_subword (operands[1], 1, 0, DImode);
7743      operands[4] = operand_subword (operands[0], 0, 0, DImode);
7744      operands[5] = operand_subword (operands[1], 0, 0, DImode);
7745    }
7746
7747  if (operands[2] == 0 || operands[3] == 0
7748      || operands[4] == 0 || operands[5] == 0)
7749    FAIL;
7750})
7751
7752;; The '?'s in the following constraints may not reflect the time taken
7753;; to perform the move. They are there to discourage the use of floating-
7754;; point registers for storing integer values.
7755(define_insn "*movdi_media"
7756  [(set (match_operand:DI 0 "general_movdst_operand"
7757	         "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
7758	(match_operand:DI 1 "general_movsrc_operand"
7759	 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7760  "TARGET_SHMEDIA_FPU
7761   && (register_operand (operands[0], DImode)
7762       || sh_register_operand (operands[1], DImode))"
7763  "@
7764	add	%1, r63, %0
7765	movi	%1, %0
7766	#
7767	ld%M1.q	%m1, %0
7768	st%M0.q	%m0, %N1
7769	fld%M1.d	%m1, %0
7770	fst%M0.d	%m0, %1
7771	fmov.qd	%N1, %0
7772	fmov.dq	%1, %0
7773	fmov.d	%1, %0
7774	ptabs	%1, %0
7775	gettr	%1, %0
7776	pt	%1, %0"
7777  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7778		     fload_media,fstore_media,fload_media,dfpconv_media,
7779		     fmove_media,ptabs_media,gettr_media,pt_media")
7780   (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7781
7782(define_insn "*movdi_media_nofpu"
7783  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
7784	(match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
7785  "TARGET_SHMEDIA
7786   && (register_operand (operands[0], DImode)
7787       || sh_register_operand (operands[1], DImode))"
7788  "@
7789	add	%1, r63, %0
7790	movi	%1, %0
7791	#
7792	ld%M1.q	%m1, %0
7793	st%M0.q	%m0, %N1
7794	ptabs	%1, %0
7795	gettr	%1, %0
7796	pt	%1, %0"
7797  [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7798		     ptabs_media,gettr_media,pt_media")
7799   (set_attr "length" "4,4,16,4,4,4,4,*")])
7800
7801(define_insn "*movdi_media_I16"
7802  [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7803	(match_operand:DI 1 "const_int_operand" "I16"))]
7804  "TARGET_SHMEDIA && reload_completed"
7805  "movi	%1, %0"
7806  [(set_attr "type" "arith_media")
7807   (set_attr "length" "4")])
7808
7809(define_split
7810  [(set (match_operand:DI 0 "arith_reg_dest" "")
7811	(match_operand:DI 1 "immediate_operand" ""))]
7812  "TARGET_SHMEDIA && reload_completed
7813   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7814  [(set (match_dup 0) (match_dup 1))]
7815{
7816  rtx insn;
7817
7818  if (TARGET_SHMEDIA64)
7819    insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7820  else
7821    insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7822
7823  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7824
7825  DONE;
7826})
7827
7828(define_expand "movdi_const"
7829  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7830	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7831		  	      (const_int 48)] UNSPEC_EXTRACT_S16)))
7832   (set (match_dup 0)
7833	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7834		(const:DI (unspec:DI [(match_dup 1)
7835				      (const_int 32)] UNSPEC_EXTRACT_U16))))
7836   (set (match_dup 0)
7837	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7838		(const:DI (unspec:DI [(match_dup 1)
7839				      (const_int 16)] UNSPEC_EXTRACT_U16))))
7840   (set (match_dup 0)
7841	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7842		(const:DI (unspec:DI [(match_dup 1)
7843				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
7844  "TARGET_SHMEDIA64 && reload_completed
7845   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7846{
7847  sh_mark_label (operands[1], 4);
7848})
7849
7850(define_expand "movdi_const_32bit"
7851  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7852	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7853			      (const_int 16)] UNSPEC_EXTRACT_S16)))
7854   (set (match_dup 0)
7855	(ior:DI (ashift:DI (match_dup 0) (const_int 16))
7856		(const:DI (unspec:DI [(match_dup 1)
7857				      (const_int 0)] UNSPEC_EXTRACT_U16))))]
7858  "TARGET_SHMEDIA32 && reload_completed
7859   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7860{
7861  sh_mark_label (operands[1], 2);
7862})
7863
7864(define_expand "movdi_const_16bit"
7865  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7866	(const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7867			      (const_int 0)] UNSPEC_EXTRACT_S16)))]
7868  "TARGET_SHMEDIA && flag_pic && reload_completed
7869   && GET_CODE (operands[1]) == SYMBOL_REF"
7870  "")
7871
7872(define_split
7873  [(set (match_operand:DI 0 "ext_dest_operand" "")
7874	(match_operand:DI 1 "immediate_operand" ""))]
7875  "TARGET_SHMEDIA && reload_completed
7876   && CONST_INT_P (operands[1])
7877   && ! satisfies_constraint_I16 (operands[1])"
7878  [(set (match_dup 0) (match_dup 2))
7879   (match_dup 1)]
7880{
7881  unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7882  unsigned HOST_WIDE_INT low = val;
7883  unsigned HOST_WIDE_INT high = val;
7884  unsigned HOST_WIDE_INT sign;
7885  unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7886
7887  /* Zero-extend the 16 least-significant bits.  */
7888  low &= 0xffff;
7889
7890  /* Arithmetic shift right the word by 16 bits.  */
7891  high >>= 16;
7892  if (GET_CODE (operands[0]) == SUBREG
7893      && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7894    {
7895      high &= 0xffff;
7896      high ^= 0x8000;
7897      high -= 0x8000;
7898    }
7899  else
7900    {
7901      sign = 1;
7902      sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7903      high ^= sign;
7904      high -= sign;
7905    }
7906  do
7907    {
7908      /* If we can't generate the constant with a two-insn movi / shori
7909	 sequence, try some other strategies.  */
7910      if (! CONST_OK_FOR_I16 (high))
7911	{
7912	  /* Try constant load / left shift.  We know VAL != 0.  */
7913	  val2 = val ^ (val-1);
7914	  if (val2 > 0x1ffff)
7915	    {
7916	      int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7917
7918	      if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7919		  || (! CONST_OK_FOR_I16 (high >> 16)
7920		      && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7921		{
7922		  val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7923		  operands[1] = gen_ashldi3_media (operands[0], operands[0],
7924						   GEN_INT (trailing_zeroes));
7925		  break;
7926		}
7927	    }
7928	  /* Try constant load / right shift.  */
7929	  val2 = (val >> 15) + 1;
7930	  if (val2 == (val2 & -val2))
7931	    {
7932	      int shift = 49 - exact_log2 (val2);
7933
7934	      val2 = trunc_int_for_mode (val << shift, DImode);
7935	      if (CONST_OK_FOR_I16 (val2))
7936		{
7937		  operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7938						   GEN_INT (shift));
7939		  break;
7940		}
7941	    }
7942	  /* Try mperm.w .  */
7943	  val2 = val & 0xffff;
7944	  if ((val >> 16 & 0xffff) == val2
7945	      && (val >> 32 & 0xffff) == val2
7946	      && (val >> 48 & 0xffff) == val2)
7947	    {
7948	      val2 = (HOST_WIDE_INT) val >> 48;
7949	      operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7950	      operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7951	      break;
7952	    }
7953	  /* Try movi / mshflo.l  */
7954	  val2 = (HOST_WIDE_INT) val >> 32;
7955	  if (val2 == ((unsigned HOST_WIDE_INT)
7956			trunc_int_for_mode (val, SImode)))
7957	    {
7958	      operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7959					     operands[0]);
7960	      break;
7961	    }
7962	  /* Try movi / mshflo.l w/ r63.  */
7963	  val2 = val + ((HOST_WIDE_INT) (HOST_WIDE_INT_M1U << 32));
7964	  if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7965	    {
7966	      operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7967					     const0_rtx);
7968	      break;
7969	    }
7970	}
7971      val2 = high;
7972      operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7973    }
7974  while (0);
7975  operands[2] = GEN_INT (val2);
7976})
7977
7978(define_split
7979  [(set (match_operand:DI 0 "ext_dest_operand" "")
7980	(match_operand:DI 1 "immediate_operand" ""))]
7981  "TARGET_SHMEDIA && reload_completed
7982   && GET_CODE (operands[1]) == CONST_DOUBLE"
7983  [(set (match_dup 0) (match_dup 2))
7984  (set (match_dup 0)
7985       (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7986{
7987  unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7988  unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7989  unsigned HOST_WIDE_INT val = low;
7990  unsigned HOST_WIDE_INT sign;
7991
7992  /* Zero-extend the 16 least-significant bits.  */
7993  val &= 0xffff;
7994  operands[1] = GEN_INT (val);
7995
7996  /* Arithmetic shift right the double-word by 16 bits.  */
7997  low >>= 16;
7998  low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7999  high >>= 16;
8000  sign = 1;
8001  sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
8002  high ^= sign;
8003  high -= sign;
8004
8005  /* This will only be true if high is a sign-extension of low, i.e.,
8006     it must be either 0 or (unsigned)-1, and be zero iff the
8007     most-significant bit of low is set.  */
8008  if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
8009    operands[2] = GEN_INT (low);
8010  else
8011    operands[2] = immed_double_const (low, high, DImode);
8012})
8013
8014(define_insn "shori_media"
8015  [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
8016	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
8017			   (const_int 16))
8018		(match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
8019  "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
8020  "@
8021	shori	%u2, %0
8022	#"
8023  [(set_attr "type" "arith_media,*")])
8024
8025(define_insn "*shori_media_si"
8026  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
8027	(ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
8028			   (const_int 16))
8029		(match_operand:SI 2 "immediate_operand" "K16Csu")))]
8030  "TARGET_SHMEDIA"
8031  "shori	%u2, %0")
8032
8033(define_expand "movdi"
8034  [(set (match_operand:DI 0 "general_movdst_operand" "")
8035	(match_operand:DI 1 "general_movsrc_operand" ""))]
8036  ""
8037{
8038  prepare_move_operands (operands, DImode);
8039  if (TARGET_SH1)
8040    {
8041      /* When the dest operand is (R0, R1) register pair, split it to
8042	 two movsi of which dest is R1 and R0 so as to lower R0-register
8043	 pressure on the first movsi.  Apply only for simple source not
8044	 to make complex rtl here.  */
8045      if (REG_P (operands[0])
8046	  && REGNO (operands[0]) == R0_REG
8047	  && REG_P (operands[1])
8048	  && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
8049	{
8050	  emit_insn (gen_movsi (gen_rtx_REG (SImode, R1_REG),
8051			        gen_rtx_SUBREG (SImode, operands[1], 4)));
8052	  emit_insn (gen_movsi (gen_rtx_REG (SImode, R0_REG),
8053			        gen_rtx_SUBREG (SImode, operands[1], 0)));
8054	  DONE;
8055	}
8056    }
8057})
8058
8059(define_insn "movdf_media"
8060  [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8061	(match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8062  "TARGET_SHMEDIA_FPU
8063   && (register_operand (operands[0], DFmode)
8064       || sh_register_operand (operands[1], DFmode))"
8065  "@
8066	fmov.d	%1, %0
8067	fmov.qd	%N1, %0
8068	fmov.dq	%1, %0
8069	add	%1, r63, %0
8070	#
8071	fld%M1.d	%m1, %0
8072	fst%M0.d	%m0, %1
8073	ld%M1.q	%m1, %0
8074	st%M0.q	%m0, %N1"
8075  [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,
8076		     fload_media,fstore_media,load_media,store_media")])
8077
8078(define_insn "movdf_media_nofpu"
8079  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
8080	(match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8081  "TARGET_SHMEDIA
8082   && (register_operand (operands[0], DFmode)
8083       || sh_register_operand (operands[1], DFmode))"
8084  "@
8085	add	%1, r63, %0
8086	#
8087	ld%M1.q	%m1, %0
8088	st%M0.q	%m0, %N1"
8089  [(set_attr "type" "arith_media,*,load_media,store_media")])
8090
8091(define_split
8092  [(set (match_operand:DF 0 "arith_reg_dest" "")
8093	(match_operand:DF 1 "immediate_operand" ""))]
8094  "TARGET_SHMEDIA && reload_completed"
8095  [(set (match_dup 3) (match_dup 2))]
8096{
8097  int endian = WORDS_BIG_ENDIAN ? 1 : 0;
8098  long values[2];
8099
8100  REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), values);
8101
8102  if (HOST_BITS_PER_WIDE_INT >= 64)
8103    operands[2] = immed_double_const ((unsigned long) values[endian]
8104				      | ((HOST_WIDE_INT) values[1 - endian]
8105					 << 32), 0, DImode);
8106  else
8107    {
8108      gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
8109      operands[2] = immed_double_const (values[endian], values[1 - endian],
8110	  			        DImode);
8111    }
8112
8113  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8114})
8115
8116;; FIXME: This should be a define_insn_and_split.
8117(define_insn "movdf_k"
8118  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
8119	(match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
8120  "TARGET_SH1
8121   && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
8122       /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
8123       || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8124       || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8125   && (arith_reg_operand (operands[0], DFmode)
8126       || arith_reg_operand (operands[1], DFmode))"
8127{
8128  return output_movedouble (insn, operands, DFmode);
8129}
8130  [(set_attr "length" "4")
8131   (set_attr "type" "move,pcload,load,store")])
8132
8133;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
8134;; However, the d/F/c/z alternative cannot be split directly; it is converted
8135;; with special code in machine_dependent_reorg into a load of the R0_REG and
8136;; the d/m/c/X alternative, which is split later into single-precision
8137;; instructions.  And when not optimizing, no splits are done before fixing
8138;; up pcloads, so we need usable length information for that.
8139(define_insn "movdf_i4"
8140  [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
8141	(match_operand:DF 1 "general_movsrc_operand"  "d,r,F,m,d,FQ,m,r,d,r"))
8142   (use (reg:SI FPSCR_MODES_REG))
8143   (clobber (match_scratch:SI 2                      "=X,X,&z,X,X,X,X,X,X,X"))]
8144  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
8145   && (arith_reg_operand (operands[0], DFmode)
8146       || arith_reg_operand (operands[1], DFmode))"
8147  {
8148    switch (which_alternative)
8149    {
8150    case 0:
8151      if (TARGET_FMOVD)
8152	return "fmov	%1,%0";
8153      else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
8154	return         "fmov	%R1,%R0"	"\n"
8155	       "	fmov	%S1,%S0";
8156      else
8157	return         "fmov	%S1,%S0"	"\n"
8158	       "	fmov	%R1,%R0";
8159    case 3:
8160    case 4:
8161      return "fmov.d	%1,%0";
8162    default:
8163      return "#";
8164    }
8165  }
8166  [(set_attr_alternative "length"
8167     [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
8168      (const_int 4)
8169      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
8170      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
8171      (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
8172      (const_int 4)
8173      (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
8174      ;; We can't use 4-byte push/pop on SHcompact, so we have to
8175      ;; increment or decrement r15 explicitly.
8176      (if_then_else
8177       (match_test "TARGET_SHCOMPACT")
8178       (const_int 10) (const_int 8))
8179      (if_then_else
8180       (match_test "TARGET_SHCOMPACT")
8181       (const_int 10) (const_int 8))])
8182   (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
8183   (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
8184   (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8185					   (const_string "double")
8186					   (const_string "none")))])
8187
8188;; Moving DFmode between fp/general registers through memory
8189;; (the top of the stack) is faster than moving through fpul even for
8190;; little endian.  Because the type of an instruction is important for its
8191;; scheduling,  it is beneficial to split these operations, rather than
8192;; emitting them in one single chunk, even if this will expose a stack
8193;; use that will prevent scheduling of other stack accesses beyond this
8194;; instruction.
8195(define_split
8196  [(set (match_operand:DF 0 "register_operand")
8197	(match_operand:DF 1 "register_operand"))
8198   (use (reg:SI FPSCR_MODES_REG))
8199   (clobber (match_scratch:SI 2))]
8200  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
8201   && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
8202  [(const_int 0)]
8203{
8204  rtx insn, tos;
8205
8206  if (TARGET_SH5 && true_regnum (operands[1]) < 16)
8207    {
8208      emit_move_insn (stack_pointer_rtx,
8209		      plus_constant (Pmode, stack_pointer_rtx, -8));
8210      tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
8211    }
8212  else
8213    tos = gen_tmp_stack_mem (DFmode,
8214			     gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
8215  insn = emit_insn (gen_movdf_i4 (tos, operands[1]));
8216  if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
8217    add_reg_note (insn, REG_INC, stack_pointer_rtx);
8218  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
8219    tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
8220  else
8221    tos = gen_tmp_stack_mem (DFmode,
8222			     gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
8223  insn = emit_insn (gen_movdf_i4 (operands[0], tos));
8224  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
8225    emit_move_insn (stack_pointer_rtx,
8226		    plus_constant (Pmode, stack_pointer_rtx, 8));
8227  else
8228    add_reg_note (insn, REG_INC, stack_pointer_rtx);
8229  DONE;
8230})
8231
8232;; local-alloc sometimes allocates scratch registers even when not required,
8233;; so we must be prepared to handle these.
8234
8235;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
8236(define_split
8237  [(set (match_operand:DF 0 "general_movdst_operand" "")
8238	(match_operand:DF 1 "general_movsrc_operand"  ""))
8239   (use (reg:SI FPSCR_MODES_REG))
8240   (clobber (match_scratch:SI 2))]
8241  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
8242   && reload_completed
8243   && true_regnum (operands[0]) < 16
8244   && true_regnum (operands[1]) < 16"
8245  [(set (match_dup 0) (match_dup 1))]
8246{
8247  /* If this was a reg <-> mem operation with base + index reg addressing,
8248     we have to handle this in a special way.  */
8249  rtx mem = operands[0];
8250  int store_p = 1;
8251  if (! memory_operand (mem, DFmode))
8252    {
8253      mem = operands[1];
8254      store_p = 0;
8255    }
8256  if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
8257    mem = SUBREG_REG (mem);
8258  if (MEM_P (mem))
8259    {
8260      rtx addr = XEXP (mem, 0);
8261      if (GET_CODE (addr) == PLUS
8262	  && REG_P (XEXP (addr, 0))
8263	  && REG_P (XEXP (addr, 1)))
8264	{
8265	  int offset;
8266	  rtx reg0 = gen_rtx_REG (Pmode, 0);
8267	  rtx regop = operands[store_p], word0 ,word1;
8268
8269	  if (GET_CODE (regop) == SUBREG)
8270	    alter_subreg (&regop, true);
8271	  if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
8272	    offset = 2;
8273	  else
8274	    offset = 4;
8275	  mem = copy_rtx (mem);
8276	  PUT_MODE (mem, SImode);
8277	  word0 = gen_rtx_SUBREG (SImode, regop, 0);
8278	  alter_subreg (&word0, true);
8279	  word1 = gen_rtx_SUBREG (SImode, regop, 4);
8280	  alter_subreg (&word1, true);
8281	  if (store_p || ! refers_to_regno_p (REGNO (word0), addr))
8282	    {
8283	      emit_insn (store_p
8284			 ? gen_movsi_ie (mem, word0)
8285			 : gen_movsi_ie (word0, mem));
8286	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
8287	      mem = copy_rtx (mem);
8288	      emit_insn (store_p
8289			 ? gen_movsi_ie (mem, word1)
8290			 : gen_movsi_ie (word1, mem));
8291	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
8292	    }
8293	  else
8294	    {
8295	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
8296	      emit_insn (gen_movsi_ie (word1, mem));
8297	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
8298	      mem = copy_rtx (mem);
8299	      emit_insn (gen_movsi_ie (word0, mem));
8300	    }
8301	  DONE;
8302	}
8303    }
8304})
8305
8306;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
8307(define_split
8308  [(set (match_operand:DF 0 "register_operand" "")
8309	(match_operand:DF 1 "memory_operand"  ""))
8310   (use (reg:SI FPSCR_MODES_REG))
8311   (clobber (reg:SI R0_REG))]
8312  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
8313  [(parallel [(set (match_dup 0) (match_dup 1))
8314	      (use (reg:SI FPSCR_MODES_REG))
8315	      (clobber (scratch:SI))])]
8316  "")
8317
8318(define_expand "reload_indf__frn"
8319  [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
8320		   (match_operand:DF 1 "immediate_operand" "FQ"))
8321	      (use (reg:SI FPSCR_MODES_REG))
8322	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8323  "TARGET_SH1"
8324  "")
8325
8326(define_expand "reload_outdf__RnFRm"
8327  [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
8328		   (match_operand:DF 1 "register_operand" "af,r"))
8329	      (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
8330  "TARGET_SH1"
8331  "")
8332
8333;; Simplify no-op moves.
8334(define_split
8335  [(set (match_operand:SF 0 "register_operand" "")
8336	(match_operand:SF 1 "register_operand" ""))
8337   (use (reg:SI FPSCR_MODES_REG))
8338   (clobber (match_scratch:SI 2))]
8339  "TARGET_SH2E && reload_completed
8340   && true_regnum (operands[0]) == true_regnum (operands[1])"
8341  [(set (match_dup 0) (match_dup 0))]
8342  "")
8343
8344;; fmovd substitute post-reload splits
8345(define_split
8346  [(set (match_operand:DF 0 "register_operand" "")
8347	(match_operand:DF 1 "register_operand" ""))
8348   (use (reg:SI FPSCR_MODES_REG))
8349   (clobber (match_scratch:SI 2))]
8350  "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
8351   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
8352   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
8353  [(const_int 0)]
8354{
8355  int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
8356  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
8357			   gen_rtx_REG (SFmode, src)));
8358  emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
8359			   gen_rtx_REG (SFmode, src + 1)));
8360  DONE;
8361})
8362
8363(define_split
8364  [(set (match_operand:DF 0 "register_operand" "")
8365	(mem:DF (match_operand:SI 1 "register_operand" "")))
8366   (use (reg:SI FPSCR_MODES_REG))
8367   (clobber (match_scratch:SI 2))]
8368  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
8369   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
8370   && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
8371  [(const_int 0)]
8372{
8373  int regno = true_regnum (operands[0]);
8374  rtx insn;
8375  rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
8376  rtx mem2
8377    = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
8378  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
8379					       regno + SH_REG_MSW_OFFSET),
8380				  mem2));
8381  add_reg_note (insn, REG_INC, operands[1]);
8382  insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
8383					       regno + SH_REG_LSW_OFFSET),
8384				  change_address (mem, SFmode, NULL_RTX)));
8385  DONE;
8386})
8387
8388(define_split
8389  [(set (match_operand:DF 0 "register_operand" "")
8390	(match_operand:DF 1 "memory_operand" ""))
8391   (use (reg:SI FPSCR_MODES_REG))
8392   (clobber (match_scratch:SI 2))]
8393  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
8394   && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
8395  [(const_int 0)]
8396{
8397  int regno = true_regnum (operands[0]);
8398  rtx addr, insn;
8399  rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
8400  rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
8401  rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
8402
8403  operands[1] = copy_rtx (mem2);
8404  addr = XEXP (mem2, 0);
8405
8406  switch (GET_CODE (addr))
8407    {
8408    case REG:
8409      /* This is complicated.  If the register is an arithmetic register
8410	 we can just fall through to the REG+DISP case below.  Otherwise
8411	 we have to use a combination of POST_INC and REG addressing...  */
8412      if (! arith_reg_operand (operands[1], SFmode))
8413	{
8414	  XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
8415	  insn = emit_insn (gen_movsf_ie (reg0, mem2));
8416	  add_reg_note (insn, REG_INC, XEXP (addr, 0));
8417	  
8418	  emit_insn (gen_movsf_ie (reg1, operands[1]));
8419
8420	  /* If we have modified the stack pointer, the value that we have
8421	     read with post-increment might be modified by an interrupt,
8422	     so write it back.  */
8423	  if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
8424	    emit_insn (gen_push_e (reg0));
8425	  else
8426	    emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0),
8427				   GEN_INT (-4)));
8428	  break;
8429	}
8430      /* Fall through.  */
8431
8432    case PLUS:
8433      emit_insn (gen_movsf_ie (reg0, operands[1]));
8434      operands[1] = copy_rtx (operands[1]);
8435      XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
8436      emit_insn (gen_movsf_ie (reg1, operands[1]));
8437      break;
8438
8439    case POST_INC:
8440      insn = emit_insn (gen_movsf_ie (reg0, operands[1]));
8441      add_reg_note (insn, REG_INC, XEXP (addr, 0));
8442
8443      insn = emit_insn (gen_movsf_ie (reg1, operands[1]));
8444      add_reg_note (insn, REG_INC, XEXP (addr, 0));
8445      break;
8446
8447    default:
8448      debug_rtx (addr);
8449      gcc_unreachable ();
8450    }
8451
8452  DONE;
8453})
8454
8455(define_split
8456  [(set (match_operand:DF 0 "memory_operand" "")
8457	(match_operand:DF 1 "register_operand" ""))
8458   (use (reg:SI FPSCR_MODES_REG))
8459   (clobber (match_scratch:SI 2))]
8460  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
8461   && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
8462  [(const_int 0)]
8463{
8464  int regno = true_regnum (operands[1]);
8465  rtx insn, addr;
8466  rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
8467  rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
8468
8469  operands[0] = copy_rtx (operands[0]);
8470  PUT_MODE (operands[0], SFmode);
8471  addr = XEXP (operands[0], 0);
8472
8473  switch (GET_CODE (addr))
8474    {
8475    case REG:
8476      /* This is complicated.  If the register is an arithmetic register
8477	 we can just fall through to the REG+DISP case below.  Otherwise
8478	 we have to use a combination of REG and PRE_DEC addressing...  */
8479      if (! arith_reg_operand (operands[0], SFmode))
8480	{
8481	  emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
8482	  emit_insn (gen_movsf_ie (operands[0], reg1));
8483
8484	  operands[0] = copy_rtx (operands[0]);
8485	  XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
8486	  
8487	  insn = emit_insn (gen_movsf_ie (operands[0], reg0));
8488	  add_reg_note (insn, REG_INC, XEXP (addr, 0));
8489	  break;
8490	}
8491      /* Fall through.  */
8492
8493    case PLUS:
8494      /* Since REG+DISP addressing has already been decided upon by gcc
8495	 we can rely upon it having chosen an arithmetic register as the
8496	 register component of the address.  Just emit the lower numbered
8497	 register first, to the lower address, then the higher numbered
8498	 register to the higher address.  */
8499      emit_insn (gen_movsf_ie (operands[0], reg0));
8500
8501      operands[0] = copy_rtx (operands[0]);
8502      XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
8503
8504      emit_insn (gen_movsf_ie (operands[0], reg1));
8505      break;
8506
8507    case PRE_DEC:
8508      /* This is easy.  Output the word to go to the higher address
8509         first (ie the word in the higher numbered register) then the
8510	 word to go to the lower address.  */
8511
8512      insn = emit_insn (gen_movsf_ie (operands[0], reg1));
8513      add_reg_note (insn, REG_INC, XEXP (addr, 0));
8514
8515      insn = emit_insn (gen_movsf_ie (operands[0], reg0));
8516      add_reg_note (insn, REG_INC, XEXP (addr, 0));
8517      break;
8518
8519    default:
8520      /* FAIL; */
8521      debug_rtx (addr);
8522      gcc_unreachable ();
8523    }
8524
8525  DONE;
8526})
8527
8528;; If the output is a register and the input is memory or a register, we have
8529;; to be careful and see which word needs to be loaded first.
8530(define_split
8531  [(set (match_operand:DF 0 "general_movdst_operand" "")
8532	(match_operand:DF 1 "general_movsrc_operand" ""))]
8533  "TARGET_SH1 && reload_completed"
8534  [(set (match_dup 2) (match_dup 3))
8535   (set (match_dup 4) (match_dup 5))]
8536{
8537  int regno;
8538
8539  if ((MEM_P (operands[0])
8540       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
8541      || (MEM_P (operands[1])
8542	  && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
8543    FAIL;
8544
8545  switch (GET_CODE (operands[0]))
8546    {
8547    case REG:
8548      regno = REGNO (operands[0]);
8549      break;
8550    case SUBREG:
8551      regno = subreg_regno (operands[0]);
8552      break;
8553    case MEM:
8554      regno = -1;
8555      break;
8556    default:
8557      gcc_unreachable ();
8558    }
8559
8560  if (regno == -1 || ! refers_to_regno_p (regno, operands[1]))
8561    {
8562      operands[2] = operand_subword (operands[0], 0, 0, DFmode);
8563      operands[3] = operand_subword (operands[1], 0, 0, DFmode);
8564      operands[4] = operand_subword (operands[0], 1, 0, DFmode);
8565      operands[5] = operand_subword (operands[1], 1, 0, DFmode);
8566    }
8567  else
8568    {
8569      operands[2] = operand_subword (operands[0], 1, 0, DFmode);
8570      operands[3] = operand_subword (operands[1], 1, 0, DFmode);
8571      operands[4] = operand_subword (operands[0], 0, 0, DFmode);
8572      operands[5] = operand_subword (operands[1], 0, 0, DFmode);
8573    }
8574
8575  if (operands[2] == 0 || operands[3] == 0
8576      || operands[4] == 0 || operands[5] == 0)
8577    FAIL;
8578})
8579
8580(define_expand "movdf"
8581  [(set (match_operand:DF 0 "general_movdst_operand" "")
8582	(match_operand:DF 1 "general_movsrc_operand" ""))]
8583  ""
8584{
8585  prepare_move_operands (operands, DFmode);
8586  if (TARGET_SHMEDIA)
8587    {
8588      if (TARGET_SHMEDIA_FPU)
8589	emit_insn (gen_movdf_media (operands[0], operands[1]));
8590      else
8591	emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
8592      DONE;
8593    }
8594  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8595    {
8596      emit_insn (gen_movdf_i4 (operands[0], operands[1]));
8597      DONE;
8598    }
8599})
8600
8601;;This is incompatible with the way gcc uses subregs.
8602;;(define_insn "movv2sf_i"
8603;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
8604;;	(match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
8605;;  "TARGET_SHMEDIA_FPU
8606;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
8607;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
8608;;  "@
8609;;	#
8610;;	fld%M1.p	%m1, %0
8611;;	fst%M0.p	%m0, %1"
8612;;  [(set_attr "type" "*,fload_media,fstore_media")])
8613(define_insn_and_split "movv2sf_i"
8614  [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8615	(match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8616  "TARGET_SHMEDIA_FPU"
8617  "#"
8618  "TARGET_SHMEDIA_FPU && reload_completed"
8619  [(set (match_dup 0) (match_dup 1))]
8620{
8621  operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
8622  operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
8623})
8624
8625(define_expand "movv2sf"
8626  [(set (match_operand:V2SF 0 "general_movdst_operand" "")
8627	(match_operand:V2SF 1 "nonimmediate_operand" ""))]
8628  "TARGET_SHMEDIA_FPU"
8629{
8630  prepare_move_operands (operands, V2SFmode);
8631})
8632
8633(define_expand "addv2sf3"
8634  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8635   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8636   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8637  "TARGET_SHMEDIA_FPU"
8638{
8639  sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
8640  DONE;
8641})
8642
8643(define_expand "subv2sf3"
8644  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8645   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8646   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8647  "TARGET_SHMEDIA_FPU"
8648{
8649  sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
8650  DONE;
8651})
8652
8653(define_expand "mulv2sf3"
8654  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8655   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8656   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8657  "TARGET_SHMEDIA_FPU"
8658{
8659  sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
8660  DONE;
8661})
8662
8663(define_expand "divv2sf3"
8664  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8665   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8666   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8667  "TARGET_SHMEDIA_FPU"
8668{
8669  sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
8670  DONE;
8671})
8672
8673(define_insn_and_split "*movv4sf_i"
8674  [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8675	(match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8676  "TARGET_SHMEDIA_FPU"
8677  "#"
8678  "&& reload_completed"
8679  [(const_int 0)]
8680{
8681  for (int i = 0; i < 4/2; i++)
8682    {
8683      rtx x, y;
8684
8685      if (MEM_P (operands[0]))
8686	x = adjust_address (operands[0], V2SFmode,
8687			    i * GET_MODE_SIZE (V2SFmode));
8688      else
8689	x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
8690
8691      if (MEM_P (operands[1]))
8692	y = adjust_address (operands[1], V2SFmode,
8693			    i * GET_MODE_SIZE (V2SFmode));
8694      else
8695	y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
8696
8697      emit_insn (gen_movv2sf_i (x, y));
8698    }
8699
8700  DONE;
8701}
8702  [(set_attr "length" "8")])
8703
8704(define_expand "movv4sf"
8705  [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
8706	(match_operand:V4SF 1 "general_operand" ""))]
8707  "TARGET_SHMEDIA_FPU"
8708{
8709  prepare_move_operands (operands, V4SFmode);
8710})
8711
8712(define_insn_and_split "*movv16sf_i"
8713  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8714	(match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8715  "TARGET_SHMEDIA_FPU"
8716  "#"
8717  "&& reload_completed"
8718  [(const_int 0)]
8719{
8720  for (int i = 0; i < 16/2; i++)
8721    {
8722      rtx x, y;
8723
8724      if (MEM_P (operands[0]))
8725	x = adjust_address (operands[0], V2SFmode,
8726			    i * GET_MODE_SIZE (V2SFmode));
8727      else
8728	{
8729	  x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
8730	  alter_subreg (&x, true);
8731	}
8732
8733      if (MEM_P (operands[1]))
8734	y = adjust_address (operands[1], V2SFmode,
8735			    i * GET_MODE_SIZE (V2SFmode));
8736      else
8737	{
8738	  y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
8739	  alter_subreg (&y, true);
8740	}
8741
8742      emit_insn (gen_movv2sf_i (x, y));
8743    }
8744
8745  DONE;
8746}
8747  [(set_attr "length" "32")])
8748
8749(define_expand "movv16sf"
8750  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8751	(match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8752  "TARGET_SHMEDIA_FPU"
8753{
8754  prepare_move_operands (operands, V16SFmode);
8755})
8756
8757(define_insn "movsf_media"
8758  [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8759	(match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8760  "TARGET_SHMEDIA_FPU
8761   && (register_operand (operands[0], SFmode)
8762       || sh_register_operand (operands[1], SFmode))"
8763  "@
8764	fmov.s	%1, %0
8765	fmov.ls	%N1, %0
8766	fmov.sl	%1, %0
8767	add.l	%1, r63, %0
8768	#
8769	fld%M1.s	%m1, %0
8770	fst%M0.s	%m0, %1
8771	ld%M1.l	%m1, %0
8772	st%M0.l	%m0, %N1"
8773  [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8774   (set (attr "highpart")
8775	(cond [(match_test "sh_contains_memref_p (insn)")
8776	       (const_string "user")]
8777	      (const_string "ignore")))])
8778
8779(define_insn "movsf_media_nofpu"
8780  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
8781	(match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8782  "TARGET_SHMEDIA
8783   && (register_operand (operands[0], SFmode)
8784       || sh_register_operand (operands[1], SFmode))"
8785  "@
8786	add.l	%1, r63, %0
8787	#
8788	ld%M1.l	%m1, %0
8789	st%M0.l	%m0, %N1"
8790  [(set_attr "type" "arith_media,*,load_media,store_media")
8791   (set (attr "highpart")
8792	(cond [(match_test "sh_contains_memref_p (insn)")
8793	       (const_string "user")]
8794	      (const_string "ignore")))])
8795
8796(define_split
8797  [(set (match_operand:SF 0 "arith_reg_dest" "")
8798	(match_operand:SF 1 "immediate_operand" ""))]
8799  "TARGET_SHMEDIA && reload_completed
8800   && ! FP_REGISTER_P (true_regnum (operands[0]))"
8801  [(set (match_dup 3) (match_dup 2))]
8802{
8803  long values;
8804
8805  REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), values);
8806  operands[2] = GEN_INT (values);
8807
8808  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8809})
8810
8811(define_insn "movsf_i"
8812  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
8813	(match_operand:SF 1 "general_movsrc_operand"  "r,G,FQ,mr,r,r,l"))]
8814  "TARGET_SH1
8815   && (! TARGET_SH2E
8816       /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
8817       || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8818       || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8819   && (arith_reg_operand (operands[0], SFmode)
8820       || arith_reg_operand (operands[1], SFmode))"
8821  "@
8822	mov	%1,%0
8823	mov	#0,%0
8824	mov.l	%1,%0
8825	mov.l	%1,%0
8826	mov.l	%1,%0
8827	lds	%1,%0
8828	sts	%1,%0"
8829  [(set_attr "type" "move,move,pcload,load,store,move,move")])
8830
8831;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8832;; update_flow_info would not know where to put REG_EQUAL notes
8833;; when the destination changes mode.
8834(define_insn "movsf_ie"
8835  [(set (match_operand:SF 0 "general_movdst_operand"
8836	 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8837	(match_operand:SF 1 "general_movsrc_operand"
8838	  "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8839   (use (reg:SI FPSCR_MODES_REG))
8840   (clobber (match_scratch:SI 2 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
8841  "TARGET_SH2E
8842   && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode)
8843       || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode)
8844       || arith_reg_operand (operands[2], SImode))"
8845  "@
8846	fmov	%1,%0
8847	mov	%1,%0
8848	fldi0	%0
8849	fldi1	%0
8850	#
8851	fmov.s	%1,%0
8852	fmov.s	%1,%0
8853	mov.l	%1,%0
8854	mov.l	%1,%0
8855	mov.l	%1,%0
8856	fsts	fpul,%0
8857	flds	%1,fpul
8858	lds.l	%1,%0
8859	#
8860	sts	%1,%0
8861	lds	%1,%0
8862	sts.l	%1,%0
8863	lds.l	%1,%0
8864	! move optimized away"
8865  [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8866		     store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8867   (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8868   (set_attr_alternative "length"
8869     [(const_int 2)
8870      (const_int 2)
8871      (const_int 2)
8872      (const_int 2)
8873      (const_int 4)
8874      (if_then_else
8875	(match_test "TARGET_SH2A")
8876	(const_int 4) (const_int 2))
8877      (if_then_else
8878	(match_test "TARGET_SH2A")
8879	(const_int 4) (const_int 2))
8880      (const_int 2)
8881      (if_then_else
8882	(match_test "TARGET_SH2A")
8883	(const_int 4) (const_int 2))
8884      (if_then_else
8885	(match_test "TARGET_SH2A")
8886	(const_int 4) (const_int 2))
8887      (const_int 2)
8888      (const_int 2)
8889      (const_int 2)
8890      (const_int 4)
8891      (const_int 2)
8892      (const_int 2)
8893      (const_int 2)
8894      (const_int 2)
8895      (const_int 0)])
8896  (set_attr_alternative "fp_mode"
8897     [(if_then_else (eq_attr "fmovd" "yes")
8898		    (const_string "single") (const_string "none"))
8899      (const_string "none")
8900      (const_string "single")
8901      (const_string "single")
8902      (const_string "none")
8903      (if_then_else (eq_attr "fmovd" "yes")
8904		    (const_string "single") (const_string "none"))
8905      (if_then_else (eq_attr "fmovd" "yes")
8906		    (const_string "single") (const_string "none"))
8907      (const_string "none")
8908      (const_string "none")
8909      (const_string "none")
8910      (const_string "none")
8911      (const_string "none")
8912      (const_string "none")
8913      (const_string "none")
8914      (const_string "none")
8915      (const_string "none")
8916      (const_string "none")
8917      (const_string "none")
8918      (const_string "none")])])
8919
8920(define_insn_and_split "movsf_ie_ra"
8921  [(set (match_operand:SF 0 "general_movdst_operand"
8922	 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8923	(match_operand:SF 1 "general_movsrc_operand"
8924	  "f,r,G,H,FQ,m,f,FQ,m,r,y,f,>,fr,y,r,y,>,y"))
8925   (use (reg:SI FPSCR_MODES_REG))
8926   (clobber (match_scratch:SF 2 "=r,r,X,X,&z,r,r,X,r,r,r,r,r,y,r,r,r,r,r"))
8927   (const_int 0)]
8928  "TARGET_SH2E
8929   && (arith_reg_operand (operands[0], SFmode)
8930       || fpul_operand (operands[0], SFmode)
8931       || arith_reg_operand (operands[1], SFmode)
8932       || fpul_operand (operands[1], SFmode))"
8933  "@
8934	fmov	%1,%0
8935	mov	%1,%0
8936	fldi0	%0
8937	fldi1	%0
8938	#
8939	fmov.s	%1,%0
8940	fmov.s	%1,%0
8941	mov.l	%1,%0
8942	mov.l	%1,%0
8943	mov.l	%1,%0
8944	fsts	fpul,%0
8945	flds	%1,fpul
8946	lds.l	%1,%0
8947	#
8948	sts	%1,%0
8949	lds	%1,%0
8950	sts.l	%1,%0
8951	lds.l	%1,%0
8952	! move optimized away"
8953  "reload_completed
8954   && sh_movsf_ie_ra_split_p (operands[0], operands[1], operands[2])"
8955  [(const_int 0)]
8956{
8957  if (! rtx_equal_p (operands[0], operands[1]))
8958    {
8959      emit_insn (gen_movsf_ie (operands[2], operands[1]));
8960      emit_insn (gen_movsf_ie (operands[0], operands[2]));
8961    }
8962}
8963  [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8964		     store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8965   (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8966   (set_attr_alternative "length"
8967     [(const_int 2)
8968      (const_int 2)
8969      (const_int 2)
8970      (const_int 2)
8971      (const_int 4)
8972      (if_then_else
8973	(match_test "TARGET_SH2A")
8974	(const_int 4) (const_int 2))
8975      (if_then_else
8976	(match_test "TARGET_SH2A")
8977	(const_int 4) (const_int 2))
8978      (const_int 2)
8979      (if_then_else
8980	(match_test "TARGET_SH2A")
8981	(const_int 4) (const_int 2))
8982      (if_then_else
8983	(match_test "TARGET_SH2A")
8984	(const_int 4) (const_int 2))
8985      (const_int 2)
8986      (const_int 2)
8987      (const_int 2)
8988      (const_int 4)
8989      (const_int 2)
8990      (const_int 2)
8991      (const_int 2)
8992      (const_int 2)
8993      (const_int 0)])
8994  (set_attr_alternative "fp_mode"
8995     [(if_then_else (eq_attr "fmovd" "yes")
8996		    (const_string "single") (const_string "none"))
8997      (const_string "none")
8998      (const_string "single")
8999      (const_string "single")
9000      (const_string "none")
9001      (if_then_else (eq_attr "fmovd" "yes")
9002		    (const_string "single") (const_string "none"))
9003      (if_then_else (eq_attr "fmovd" "yes")
9004		    (const_string "single") (const_string "none"))
9005      (const_string "none")
9006      (const_string "none")
9007      (const_string "none")
9008      (const_string "none")
9009      (const_string "none")
9010      (const_string "none")
9011      (const_string "none")
9012      (const_string "none")
9013      (const_string "none")
9014      (const_string "none")
9015      (const_string "none")
9016      (const_string "none")])])
9017
9018(define_split
9019  [(set (match_operand:SF 0 "register_operand" "")
9020	(match_operand:SF 1 "register_operand" ""))
9021   (use (reg:SI FPSCR_MODES_REG))
9022   (clobber (reg:SI FPUL_REG))]
9023  "TARGET_SH1"
9024  [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
9025	      (use (reg:SI FPSCR_MODES_REG))
9026	      (clobber (scratch:SI))])
9027   (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
9028	      (use (reg:SI FPSCR_MODES_REG))
9029	      (clobber (scratch:SI))])]
9030  "")
9031
9032(define_expand "movsf"
9033  [(set (match_operand:SF 0 "general_movdst_operand" "")
9034        (match_operand:SF 1 "general_movsrc_operand" ""))]
9035  ""
9036{
9037  prepare_move_operands (operands, SFmode);
9038  if (TARGET_SHMEDIA)
9039    {
9040      if (TARGET_SHMEDIA_FPU)
9041	emit_insn (gen_movsf_media (operands[0], operands[1]));
9042      else
9043	emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
9044      DONE;
9045    }
9046  if (TARGET_SH2E)
9047    {
9048      if (lra_in_progress)
9049	{
9050	  if (GET_CODE (operands[0]) == SCRATCH)
9051	    DONE;
9052	  emit_insn (gen_movsf_ie_ra (operands[0], operands[1]));
9053	  DONE;
9054	}
9055
9056      emit_insn (gen_movsf_ie (operands[0], operands[1]));
9057      DONE;
9058    }
9059})
9060
9061(define_insn "mov_nop"
9062  [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
9063  "TARGET_SH2E"
9064  ""
9065  [(set_attr "length" "0")
9066   (set_attr "type" "nil")])
9067
9068(define_expand "reload_insf__frn"
9069  [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
9070		   (match_operand:SF 1 "immediate_operand" "FQ"))
9071	      (use (reg:SI FPSCR_MODES_REG))
9072	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
9073  "TARGET_SH1"
9074  "")
9075
9076(define_expand "reload_insi__i_fpul"
9077  [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
9078		   (match_operand:SI 1 "immediate_operand" "i"))
9079	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
9080  "TARGET_SH1"
9081  "")
9082
9083(define_expand "ptabs"
9084  [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
9085  "TARGET_SHMEDIA"
9086{
9087  if (!TARGET_PT_FIXED)
9088    {
9089      rtx eq = operands[1];
9090
9091      /* ??? For canonical RTL we really should remove any CONST from EQ
9092	 before wrapping it in the AND, and finally wrap the EQ into a
9093	 const if is constant.  However, for reload we must expose the
9094	 input register or symbolic constant, and we can't have
9095	 different insn structures outside of the operands for different
9096	 alternatives of the same pattern.  */
9097      eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
9098		       GEN_INT (3));
9099      operands[1]
9100	= (gen_rtx_IF_THEN_ELSE
9101	    (PDImode,
9102	     eq,
9103	     gen_rtx_MEM (PDImode, operands[1]),
9104	     gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
9105			    PDImode, operands[1])));
9106    }
9107})
9108
9109;; expanded by ptabs expander.
9110(define_insn "*extendsipdi_media"
9111  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
9112	(if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
9113							  "r,Csy")
9114				      (const_int 3))
9115			      (const_int 3))
9116			  (mem:PDI (match_dup 1))
9117			  (sign_extend:PDI (match_dup 1))))]
9118  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
9119  "@
9120	ptabs	%1, %0
9121	pt	%1, %0"
9122  [(set_attr "type"   "ptabs_media,pt_media")
9123   (set_attr "length" "4,*")])
9124
9125(define_insn "*truncdipdi_media"
9126  [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
9127	(if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
9128							  "r,Csy")
9129				      (const_int 3))
9130			      (const_int 3))
9131			  (mem:PDI (match_dup 1))
9132			  (truncate:PDI (match_dup 1))))]
9133  "TARGET_SHMEDIA && !TARGET_PT_FIXED"
9134  "@
9135	ptabs	%1, %0
9136	pt	%1, %0"
9137  [(set_attr "type"   "ptabs_media,pt_media")
9138   (set_attr "length" "4,*")])
9139
9140(define_insn "*movsi_y"
9141  [(set (match_operand:SI 0 "register_operand" "=y,y")
9142	(match_operand:SI 1 "immediate_operand" "Qi,I08"))
9143   (clobber (match_scratch:SI 2 "=&z,r"))]
9144  "TARGET_SH2E
9145   && (reload_in_progress || reload_completed)"
9146  "#"
9147  [(set_attr "length" "4")
9148   (set_attr "type" "pcload,move")])
9149
9150(define_split
9151  [(set (match_operand:SI 0 "register_operand" "")
9152	(match_operand:SI 1 "immediate_operand" ""))
9153   (clobber (match_operand:SI 2 "register_operand" ""))]
9154  "TARGET_SH1"
9155  [(set (match_dup 2) (match_dup 1))
9156   (set (match_dup 0) (match_dup 2))]
9157  "")
9158
9159;; ------------------------------------------------------------------------
9160;; Define the real conditional branch instructions.
9161;; ------------------------------------------------------------------------
9162
9163(define_expand "branch_true"
9164  [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
9165			   (label_ref (match_operand 0))
9166			   (pc)))]
9167  "TARGET_SH1")
9168
9169(define_expand "branch_false"
9170  [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
9171			   (label_ref (match_operand 0))
9172			   (pc)))]
9173  "TARGET_SH1")
9174
9175(define_insn_and_split "*cbranch_t"
9176  [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
9177			   (label_ref (match_operand 0))
9178			   (pc)))]
9179  "TARGET_SH1"
9180{
9181  return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
9182}
9183  "&& 1"
9184  [(const_int 0)]
9185{
9186  /* Try to canonicalize the branch condition if it is not one of:
9187	(ne (reg:SI T_REG) (const_int 0))
9188	(eq (reg:SI T_REG) (const_int 0))
9189
9190     Instead of splitting out a new insn, we modify the current insn's
9191     operands as needed.  This preserves things such as REG_DEAD notes.  */
9192
9193  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9194      && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG
9195      && XEXP (operands[1], 1) == const0_rtx)
9196    DONE;
9197
9198  int branch_cond = sh_eval_treg_value (operands[1]);
9199  rtx new_cond_rtx = NULL_RTX;
9200
9201  if (branch_cond == 0)
9202    new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx);
9203  else if (branch_cond == 1)
9204    new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx);
9205
9206  if (new_cond_rtx != NULL_RTX)
9207    validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0),
9208		     new_cond_rtx, false);
9209  DONE;
9210}
9211  [(set_attr "type" "cbranch")])
9212
9213;; Patterns to prevent reorg from re-combining a condbranch with a branch
9214;; which destination is too far away.
9215;; The const_int_operand is distinct for each branch target; it avoids
9216;; unwanted matches with redundant_insn.
9217(define_insn "block_branch_redirect"
9218  [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
9219  "TARGET_SH1"
9220  ""
9221  [(set_attr "length" "0")])
9222
9223;; This one has the additional purpose to record a possible scratch register
9224;; for the following branch.
9225;; ??? Unfortunately, just setting the scratch register is not good enough,
9226;; because the insn then might be deemed dead and deleted.  And we can't
9227;; make the use in the jump insn explicit because that would disable
9228;; delay slot scheduling from the target.
9229(define_insn "indirect_jump_scratch"
9230  [(set (match_operand:SI 0 "register_operand" "=r")
9231	(unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
9232   (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
9233  "TARGET_SH1"
9234  ""
9235  [(set_attr "length" "0")])
9236
9237;; This one is used to preemt an insn from beyond the bra / braf / jmp
9238;; being pulled into the delay slot of a condbranch that has been made to
9239;; jump around the unconditional jump because it was out of range.
9240(define_insn "stuff_delay_slot"
9241  [(set (pc)
9242	(unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
9243		 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
9244  "TARGET_SH1"
9245  ""
9246  [(set_attr "length" "0")
9247   (set_attr "cond_delay_slot" "yes")])
9248
9249;; Conditional branch insns
9250
9251(define_expand "cbranchint4_media"
9252  [(set (pc)
9253	(if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
9254		       [(match_operand 1 "" "")
9255			(match_operand 2 "" "")])
9256		      (match_operand 3 "" "")
9257		      (pc)))]
9258  "TARGET_SHMEDIA"
9259{
9260  machine_mode mode = GET_MODE (operands[1]);
9261  if (mode == VOIDmode)
9262    mode = GET_MODE (operands[2]);
9263  if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
9264    {
9265      operands[1] = force_reg (mode, operands[1]);
9266      if (CONSTANT_P (operands[2])
9267          && (! satisfies_constraint_I06 (operands[2])))
9268        operands[2] = force_reg (mode, operands[2]);
9269    }
9270  else
9271    {
9272      if (operands[1] != const0_rtx)
9273        operands[1] = force_reg (mode, operands[1]);
9274      if (operands[2] != const0_rtx)
9275        operands[2] = force_reg (mode, operands[2]);
9276    }
9277  switch (GET_CODE (operands[0]))
9278    {
9279    case LEU:
9280    case LE:
9281    case LTU:
9282    case LT:
9283      operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
9284				    VOIDmode, operands[2], operands[1]);
9285      operands[1] = XEXP (operands[0], 0);
9286      operands[2] = XEXP (operands[0], 1);
9287      break;
9288    default:
9289      operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
9290				    VOIDmode, operands[1], operands[2]);
9291      break;
9292    }
9293  operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
9294})
9295
9296(define_expand "cbranchfp4_media"
9297  [(set (pc)
9298	(if_then_else (match_operator 0 "sh_float_comparison_operator"
9299		       [(match_operand 1 "" "")
9300			(match_operand 2 "" "")])
9301		      (match_operand 3 "" "")
9302		      (pc)))]
9303  "TARGET_SHMEDIA"
9304{
9305  rtx tmp = gen_reg_rtx (SImode);
9306  rtx cmp;
9307  if (GET_CODE (operands[0]) == NE)
9308    cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
9309  else
9310    cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
9311			  operands[1], operands[2]);
9312
9313  emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
9314
9315  if (GET_CODE (cmp) == GET_CODE (operands[0]))
9316    operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
9317  else
9318    operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
9319  operands[1] = tmp;
9320  operands[2] = const0_rtx;
9321  operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
9322})
9323
9324(define_insn "*beq_media_i"
9325  [(set (pc)
9326	(if_then_else (match_operator 3 "equality_comparison_operator"
9327			[(match_operand:DI 1 "arith_reg_operand" "r,r")
9328			 (match_operand:DI 2 "arith_operand" "r,I06")])
9329		      (match_operand 0 "target_operand" "b,b")
9330		      (pc)))]
9331  "TARGET_SHMEDIA"
9332  "@
9333	b%o3%'	%1, %2, %0%>
9334	b%o3i%'	%1, %2, %0%>"
9335  [(set_attr "type" "cbranch_media")])
9336
9337(define_insn "*beq_media_i32"
9338  [(set (pc)
9339	(if_then_else (match_operator 3 "equality_comparison_operator"
9340			[(match_operand:SI 1 "arith_reg_operand" "r,r")
9341			 (match_operand:SI 2 "arith_operand" "r,I06")])
9342		      (match_operand 0 "target_operand" "b,b")
9343		      (pc)))]
9344  "TARGET_SHMEDIA"
9345  "@
9346	b%o3%'	%1, %2, %0%>
9347	b%o3i%'	%1, %2, %0%>"
9348  [(set_attr "type" "cbranch_media")])
9349
9350(define_insn "*bgt_media_i"
9351  [(set (pc)
9352	(if_then_else (match_operator 3 "greater_comparison_operator"
9353			[(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
9354			 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
9355		      (match_operand 0 "target_operand" "b")
9356		      (pc)))]
9357  "TARGET_SHMEDIA"
9358  "b%o3%'	%N1, %N2, %0%>"
9359  [(set_attr "type" "cbranch_media")])
9360
9361(define_insn "*bgt_media_i32"
9362  [(set (pc)
9363	(if_then_else (match_operator 3 "greater_comparison_operator"
9364			[(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
9365			 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
9366		      (match_operand 0 "target_operand" "b")
9367		      (pc)))]
9368  "TARGET_SHMEDIA"
9369  "b%o3%'	%N1, %N2, %0%>"
9370  [(set_attr "type" "cbranch_media")])
9371
9372;; These are only needed to make invert_jump() happy - otherwise, jump
9373;; optimization will be silently disabled.
9374(define_insn "*blt_media_i"
9375  [(set (pc)
9376	(if_then_else (match_operator 3 "less_comparison_operator"
9377			[(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
9378			 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
9379		      (match_operand 0 "target_operand" "b")
9380		      (pc)))]
9381  "TARGET_SHMEDIA"
9382  "b%o3%'	%N2, %N1, %0%>"
9383  [(set_attr "type" "cbranch_media")])
9384
9385(define_insn "*blt_media_i32"
9386  [(set (pc)
9387	(if_then_else (match_operator 3 "less_comparison_operator"
9388			[(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
9389			 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
9390		      (match_operand 0 "target_operand" "b")
9391		      (pc)))]
9392  "TARGET_SHMEDIA"
9393  "b%o3%'	%N2, %N1, %0%>"
9394  [(set_attr "type" "cbranch_media")])
9395
9396;; combiner splitter for test-and-branch on single bit in register.  This
9397;; is endian dependent because the non-paradoxical subreg looks different
9398;; on big endian.
9399(define_split
9400  [(set (pc)
9401	(if_then_else
9402	  (match_operator 3 "equality_comparison_operator"
9403	    [(subreg:SI
9404	       (zero_extract:DI
9405		 (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0)
9406		 (const_int 1)
9407		 (match_operand 2 "const_int_operand" "")) 0)
9408	     (const_int 0)])
9409	  (match_operand 0 "target_operand" "")
9410	  (pc)))
9411   (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
9412  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
9413  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
9414   (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
9415{
9416  operands[5] = GEN_INT (31 - INTVAL (operands[2]));
9417  operands[6] = (GET_CODE (operands[3]) == EQ
9418		 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
9419		 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
9420})
9421
9422; operand 0 is the loop count pseudo register
9423; operand 1 is the label to jump to at the top of the loop
9424(define_expand "doloop_end"
9425  [(parallel [(set (pc)
9426		   (if_then_else (ne:SI (match_operand:SI 0 "" "")
9427				        (const_int 1))
9428				 (label_ref (match_operand 1 "" ""))
9429				 (pc)))
9430	      (set (match_dup 0)
9431		   (plus:SI (match_dup 0) (const_int -1)))
9432	      (clobber (reg:SI T_REG))])]
9433  "TARGET_SH2"
9434{
9435  if (GET_MODE (operands[0]) != SImode)
9436    FAIL;
9437  emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0]));
9438  DONE;
9439})
9440
9441(define_insn_and_split "doloop_end_split"
9442  [(set (pc)
9443	(if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
9444			     (const_int 1))
9445		      (label_ref (match_operand 1 "" ""))
9446		      (pc)))
9447   (set (match_operand:SI 0 "arith_reg_dest" "=r")
9448	(plus:SI (match_dup 2) (const_int -1)))
9449   (clobber (reg:SI T_REG))]
9450  "TARGET_SH2"
9451  "#"
9452  ""
9453  [(parallel [(set (reg:SI T_REG)
9454		   (eq:SI (match_dup 2) (const_int 1)))
9455	      (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
9456   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
9457			   (label_ref (match_dup 1))
9458			   (pc)))]
9459  ""
9460  [(set_attr "type" "cbranch")])
9461
9462;; ------------------------------------------------------------------------
9463;; Jump and linkage insns
9464;; ------------------------------------------------------------------------
9465
9466(define_insn "jump_compact"
9467  [(set (pc)
9468	(label_ref (match_operand 0 "" "")))]
9469  "TARGET_SH1 && !CROSSING_JUMP_P (insn)"
9470{
9471  /* The length is 16 if the delay slot is unfilled.  */
9472  if (get_attr_length(insn) > 4)
9473    return output_far_jump(insn, operands[0]);
9474  else
9475    return "bra	%l0%#";
9476}
9477  [(set_attr "type" "jump")
9478   (set_attr "needs_delay_slot" "yes")])
9479
9480(define_insn "*jump_compact_crossing"
9481  [(set (pc)
9482	(label_ref (match_operand 0 "" "")))]
9483  "TARGET_SH1
9484   && flag_reorder_blocks_and_partition
9485   && CROSSING_JUMP_P (insn)"
9486{
9487  /* The length is 16 if the delay slot is unfilled.  */
9488  return output_far_jump(insn, operands[0]);
9489}
9490  [(set_attr "type" "jump")
9491   (set_attr "length" "16")])
9492
9493;; ??? It would be much saner to explicitly use the scratch register
9494;; in the jump insn, and have indirect_jump_scratch only set it,
9495;; but fill_simple_delay_slots would refuse to do delay slot filling
9496;; from the target then, as it uses simplejump_p.
9497;;(define_insn "jump_compact_far"
9498;;  [(set (pc)
9499;;	(label_ref (match_operand 0 "" "")))
9500;;   (use (match_operand 1 "register_operand" "r")]
9501;;  "TARGET_SH1"
9502;;  "* return output_far_jump(insn, operands[0], operands[1]);"
9503;;  [(set_attr "type" "jump")
9504;;   (set_attr "needs_delay_slot" "yes")])
9505
9506(define_insn "jump_media"
9507  [(set (pc)
9508	(match_operand 0 "target_operand" "b"))]
9509  "TARGET_SHMEDIA"
9510  "blink	%0, r63%>"
9511  [(set_attr "type" "jump_media")])
9512
9513(define_expand "jump"
9514  [(set (pc)
9515	(label_ref (match_operand 0 "" "")))]
9516  ""
9517{
9518  if (TARGET_SH1)
9519    emit_jump_insn (gen_jump_compact (operands[0]));
9520  else if (TARGET_SHMEDIA)
9521    {
9522      if (reload_in_progress || reload_completed)
9523	FAIL;
9524      emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0])));
9525    }
9526  DONE;
9527})
9528
9529(define_insn "force_mode_for_call"
9530  [(use (reg:SI FPSCR_MODES_REG))]
9531  "TARGET_SHCOMPACT"
9532  ""
9533  [(set_attr "length" "0")
9534   (set (attr "fp_mode")
9535	(if_then_else (eq_attr "fpu_single" "yes")
9536		      (const_string "single") (const_string "double")))])
9537
9538(define_insn "calli"
9539  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9540	 (match_operand 1 "" ""))
9541   (use (reg:SI FPSCR_MODES_REG))
9542   (clobber (reg:SI PR_REG))]
9543  "TARGET_SH1 && !TARGET_FDPIC"
9544{
9545  if (TARGET_SH2A && dbr_sequence_length () == 0)
9546    return "jsr/n	@%0";
9547  else
9548    return "jsr	@%0%#";
9549}
9550  [(set_attr "type" "call")
9551   (set (attr "fp_mode")
9552	(if_then_else (eq_attr "fpu_single" "yes")
9553		      (const_string "single") (const_string "double")))
9554   (set_attr "needs_delay_slot" "yes")
9555   (set_attr "fp_set" "unknown")])
9556
9557(define_insn "calli_fdpic"
9558  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9559	 (match_operand 1))
9560   (use (reg:SI FPSCR_MODES_REG))
9561   (use (reg:SI PIC_REG))
9562   (clobber (reg:SI PR_REG))]
9563  "TARGET_FDPIC"
9564{
9565  if (TARGET_SH2A && dbr_sequence_length () == 0)
9566    return "jsr/n	@%0";
9567  else
9568    return "jsr	@%0%#";
9569}
9570  [(set_attr "type" "call")
9571   (set (attr "fp_mode")
9572	(if_then_else (eq_attr "fpu_single" "yes")
9573		      (const_string "single") (const_string "double")))
9574   (set_attr "needs_delay_slot" "yes")
9575   (set_attr "fp_set" "unknown")])
9576
9577;; This is TBR relative jump instruction for SH2A architecture.
9578;; Its use is enabled by assigning an attribute "function_vector"
9579;; and the vector number to a function during its declaration.
9580(define_insn "calli_tbr_rel"
9581  [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
9582	 (match_operand 1 "" ""))
9583   (use (reg:SI FPSCR_MODES_REG))
9584   (clobber (reg:SI PR_REG))]
9585  "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
9586{
9587  unsigned HOST_WIDE_INT vect_num;
9588  vect_num = sh2a_get_function_vector_number (operands[0]);
9589  operands[2] = GEN_INT (vect_num * 4);
9590
9591  return "jsr/n	@@(%O2,tbr)";
9592}
9593  [(set_attr "type" "call")
9594   (set (attr "fp_mode")
9595	(if_then_else (eq_attr "fpu_single" "yes")
9596		      (const_string "single") (const_string "double")))
9597   (set_attr "needs_delay_slot" "no")
9598   (set_attr "fp_set" "unknown")])
9599
9600;; This is a pc-rel call, using bsrf, for use with PIC.
9601(define_insn "calli_pcrel"
9602  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9603	 (match_operand 1 "" ""))
9604   (use (reg:SI FPSCR_MODES_REG))
9605   (use (reg:SI PIC_REG))
9606   (use (match_operand 2 "" ""))
9607   (clobber (reg:SI PR_REG))]
9608  "TARGET_SH2"
9609{
9610  return       "bsrf	%0"	"\n"
9611	 "%O2:%#";
9612}
9613  [(set_attr "type" "call")
9614   (set (attr "fp_mode")
9615	(if_then_else (eq_attr "fpu_single" "yes")
9616		      (const_string "single") (const_string "double")))
9617   (set_attr "needs_delay_slot" "yes")
9618   (set_attr "fp_set" "unknown")])
9619
9620(define_insn_and_split "call_pcrel"
9621  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9622	 (match_operand 1 "" ""))
9623   (use (reg:SI FPSCR_MODES_REG))
9624   (use (reg:SI PIC_REG))
9625   (clobber (reg:SI PR_REG))
9626   (clobber (match_scratch:SI 2 "=&r"))]
9627  "TARGET_SH2"
9628  "#"
9629  "reload_completed"
9630  [(const_int 0)]
9631{
9632  rtx lab = PATTERN (gen_call_site ());
9633  
9634  sh_expand_sym_label2reg (operands[2], operands[0], lab, false);
9635  emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
9636  DONE;
9637}
9638  [(set_attr "type" "call")
9639   (set (attr "fp_mode")
9640	(if_then_else (eq_attr "fpu_single" "yes")
9641		      (const_string "single") (const_string "double")))
9642   (set_attr "needs_delay_slot" "yes")
9643   (set_attr "fp_set" "unknown")])
9644
9645(define_insn "call_compact"
9646  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9647	 (match_operand 1 "" ""))
9648   (match_operand 2 "immediate_operand" "n")
9649   (use (reg:SI R0_REG))
9650   (use (reg:SI R1_REG))
9651   (use (reg:SI FPSCR_MODES_REG))
9652   (clobber (reg:SI PR_REG))]
9653  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9654  "jsr	@%0%#"
9655  [(set_attr "type" "call")
9656   (set (attr "fp_mode")
9657	(if_then_else (eq_attr "fpu_single" "yes")
9658		      (const_string "single") (const_string "double")))
9659   (set_attr "needs_delay_slot" "yes")])
9660
9661(define_insn "call_compact_rettramp"
9662  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9663	 (match_operand 1 "" ""))
9664   (match_operand 2 "immediate_operand" "n")
9665   (use (reg:SI R0_REG))
9666   (use (reg:SI R1_REG))
9667   (use (reg:SI FPSCR_MODES_REG))
9668   (clobber (reg:SI R10_REG))
9669   (clobber (reg:SI PR_REG))]
9670  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9671  "jsr	@%0%#"
9672  [(set_attr "type" "call")
9673   (set (attr "fp_mode")
9674	(if_then_else (eq_attr "fpu_single" "yes")
9675		      (const_string "single") (const_string "double")))
9676   (set_attr "needs_delay_slot" "yes")])
9677
9678(define_insn "call_media"
9679  [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
9680	 (match_operand 1 "" ""))
9681   (clobber (reg:DI PR_MEDIA_REG))]
9682  "TARGET_SHMEDIA"
9683  "blink	%0, r18"
9684  [(set_attr "type" "jump_media")])
9685
9686(define_insn "call_valuei"
9687  [(set (match_operand 0 "" "=rf")
9688	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9689	      (match_operand 2 "" "")))
9690   (use (reg:SI FPSCR_MODES_REG))
9691   (clobber (reg:SI PR_REG))]
9692  "TARGET_SH1 && !TARGET_FDPIC"
9693{
9694  if (TARGET_SH2A && dbr_sequence_length () == 0)
9695    return "jsr/n	@%1";
9696  else
9697    return "jsr	@%1%#";
9698}
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   (set_attr "fp_set" "unknown")])
9705
9706(define_insn "call_valuei_fdpic"
9707  [(set (match_operand 0 "" "=rf")
9708	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9709	      (match_operand 2)))
9710   (use (reg:SI FPSCR_REG))
9711   (use (reg:SI PIC_REG))
9712   (clobber (reg:SI PR_REG))]
9713  "TARGET_FDPIC"
9714{
9715  if (TARGET_SH2A && dbr_sequence_length () == 0)
9716    return "jsr/n	@%1";
9717  else
9718    return "jsr	@%1%#";
9719}
9720  [(set_attr "type" "call")
9721   (set (attr "fp_mode")
9722	(if_then_else (eq_attr "fpu_single" "yes")
9723		      (const_string "single") (const_string "double")))
9724   (set_attr "needs_delay_slot" "yes")
9725   (set_attr "fp_set" "unknown")])
9726
9727;; This is TBR relative jump instruction for SH2A architecture.
9728;; Its use is enabled by assigning an attribute "function_vector"
9729;; and the vector number to a function during its declaration.
9730(define_insn "call_valuei_tbr_rel"
9731  [(set (match_operand 0 "" "=rf")
9732	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9733	      (match_operand 2 "" "")))
9734   (use (reg:SI FPSCR_MODES_REG))
9735   (clobber (reg:SI PR_REG))]
9736  "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
9737{
9738  unsigned HOST_WIDE_INT vect_num;
9739  vect_num = sh2a_get_function_vector_number (operands[1]);
9740  operands[3] = GEN_INT (vect_num * 4);
9741
9742  return "jsr/n	@@(%O3,tbr)";
9743}
9744  [(set_attr "type" "call")
9745   (set (attr "fp_mode")
9746	(if_then_else (eq_attr "fpu_single" "yes")
9747		      (const_string "single") (const_string "double")))
9748   (set_attr "needs_delay_slot" "no")
9749   (set_attr "fp_set" "unknown")])
9750
9751(define_insn "call_valuei_pcrel"
9752  [(set (match_operand 0 "" "=rf")
9753	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9754	      (match_operand 2 "" "")))
9755   (use (reg:SI FPSCR_MODES_REG))
9756   (use (reg:SI PIC_REG))
9757   (use (match_operand 3 "" ""))
9758   (clobber (reg:SI PR_REG))]
9759  "TARGET_SH2"
9760{
9761  return       "bsrf	%1"	"\n"
9762	 "%O3:%#";
9763}
9764  [(set_attr "type" "call")
9765   (set (attr "fp_mode")
9766	(if_then_else (eq_attr "fpu_single" "yes")
9767		      (const_string "single") (const_string "double")))
9768   (set_attr "needs_delay_slot" "yes")
9769   (set_attr "fp_set" "unknown")])
9770
9771(define_insn_and_split "call_value_pcrel"
9772  [(set (match_operand 0 "" "=rf")
9773	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9774	      (match_operand 2 "" "")))
9775   (use (reg:SI FPSCR_MODES_REG))
9776   (use (reg:SI PIC_REG))
9777   (clobber (reg:SI PR_REG))
9778   (clobber (match_scratch:SI 3 "=&r"))]
9779  "TARGET_SH2"
9780  "#"
9781  "reload_completed"
9782  [(const_int 0)]
9783{
9784  rtx lab = PATTERN (gen_call_site ());
9785
9786  sh_expand_sym_label2reg (operands[3], operands[1], lab, false);
9787  emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
9788					 operands[2], copy_rtx (lab)));
9789  DONE;
9790}
9791  [(set_attr "type" "call")
9792   (set (attr "fp_mode")
9793	(if_then_else (eq_attr "fpu_single" "yes")
9794		      (const_string "single") (const_string "double")))
9795   (set_attr "needs_delay_slot" "yes")
9796   (set_attr "fp_set" "unknown")])
9797
9798(define_insn "call_value_compact"
9799  [(set (match_operand 0 "" "=rf")
9800	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9801	      (match_operand 2 "" "")))
9802   (match_operand 3 "immediate_operand" "n")
9803   (use (reg:SI R0_REG))
9804   (use (reg:SI R1_REG))
9805   (use (reg:SI FPSCR_MODES_REG))
9806   (clobber (reg:SI PR_REG))]
9807  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9808  "jsr	@%1%#"
9809  [(set_attr "type" "call")
9810   (set (attr "fp_mode")
9811	(if_then_else (eq_attr "fpu_single" "yes")
9812		      (const_string "single") (const_string "double")))
9813   (set_attr "needs_delay_slot" "yes")])
9814
9815(define_insn "call_value_compact_rettramp"
9816  [(set (match_operand 0 "" "=rf")
9817	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9818	      (match_operand 2 "" "")))
9819   (match_operand 3 "immediate_operand" "n")
9820   (use (reg:SI R0_REG))
9821   (use (reg:SI R1_REG))
9822   (use (reg:SI FPSCR_MODES_REG))
9823   (clobber (reg:SI R10_REG))
9824   (clobber (reg:SI PR_REG))]
9825  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9826  "jsr	@%1%#"
9827  [(set_attr "type" "call")
9828   (set (attr "fp_mode")
9829	(if_then_else (eq_attr "fpu_single" "yes")
9830		      (const_string "single") (const_string "double")))
9831   (set_attr "needs_delay_slot" "yes")])
9832
9833(define_insn "call_value_media"
9834  [(set (match_operand 0 "" "=rf")
9835	(call (mem:DI (match_operand 1 "target_reg_operand" "b"))
9836	      (match_operand 2 "" "")))
9837   (clobber (reg:DI PR_MEDIA_REG))]
9838  "TARGET_SHMEDIA"
9839  "blink	%1, r18"
9840  [(set_attr "type" "jump_media")])
9841
9842(define_expand "call"
9843  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9844			    (match_operand 1 "" ""))
9845	      (match_operand 2 "" "")
9846	      (use (reg:SI FPSCR_MODES_REG))
9847	      (clobber (reg:SI PR_REG))])]
9848  ""
9849{
9850  if (TARGET_FDPIC)
9851    {
9852      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
9853      emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ());
9854    }
9855
9856  if (TARGET_SHMEDIA)
9857    {
9858      operands[0] = shmedia_prepare_call_address (operands[0], 0);
9859      emit_call_insn (gen_call_media (operands[0], operands[1]));
9860      DONE;
9861    }
9862  else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9863    {
9864      rtx cookie_rtx = operands[2];
9865      long cookie = INTVAL (cookie_rtx);
9866      rtx func = XEXP (operands[0], 0);
9867      rtx r0, r1;
9868
9869      if (flag_pic)
9870	{
9871	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9872	    {
9873	      rtx reg = gen_reg_rtx (Pmode);
9874
9875	      emit_insn (gen_symGOTPLT2reg (reg, func));
9876	      func = reg;
9877	    }
9878	  else
9879	    func = legitimize_pic_address (func, Pmode, 0);
9880	}
9881
9882      r0 = gen_rtx_REG (SImode, R0_REG);
9883      r1 = gen_rtx_REG (SImode, R1_REG);
9884
9885      /* Since such a call function may use all call-clobbered
9886	 registers, we force a mode switch earlier, so that we don't
9887	 run out of registers when adjusting fpscr for the call.  */
9888      emit_insn (gen_force_mode_for_call ());
9889
9890      operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9891				     SFUNC_GOT).sym;
9892      operands[0] = force_reg (SImode, operands[0]);
9893
9894      emit_move_insn (r0, func);
9895      emit_move_insn (r1, cookie_rtx);
9896
9897      if (cookie & CALL_COOKIE_RET_TRAMP (1))
9898	emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9899						   operands[2]));
9900      else
9901	emit_call_insn (gen_call_compact (operands[0], operands[1],
9902					  operands[2]));
9903
9904      DONE;
9905    }
9906  else if (TARGET_SHCOMPACT && flag_pic
9907	   && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9908	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9909    {
9910      rtx reg = gen_reg_rtx (Pmode);
9911
9912      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9913      XEXP (operands[0], 0) = reg;
9914    }
9915  if (!flag_pic && TARGET_SH2A
9916      && MEM_P (operands[0])
9917      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9918    {
9919      if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9920	{
9921	  emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9922					     operands[1]));
9923	  DONE;
9924	}
9925    }
9926  if (flag_pic && TARGET_SH2
9927      && MEM_P (operands[0])
9928      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9929    {
9930      emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
9931      DONE;
9932    }
9933  else
9934  {
9935    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9936    operands[1] = operands[2];
9937  }
9938
9939  if (TARGET_FDPIC)
9940    {
9941      operands[0] = sh_load_function_descriptor (operands[0]);
9942      emit_call_insn (gen_calli_fdpic (operands[0], operands[1]));
9943    }
9944  else
9945    emit_call_insn (gen_calli (operands[0], operands[1]));
9946  DONE;
9947})
9948
9949(define_insn "call_pop_compact"
9950  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9951	 (match_operand 1 "" ""))
9952   (match_operand 2 "immediate_operand" "n")
9953   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9954				 (match_operand 3 "immediate_operand" "n")))
9955   (use (reg:SI R0_REG))
9956   (use (reg:SI R1_REG))
9957   (use (reg:SI FPSCR_MODES_REG))
9958   (clobber (reg:SI PR_REG))]
9959  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9960  "jsr	@%0%#"
9961  [(set_attr "type" "call")
9962   (set (attr "fp_mode")
9963	(if_then_else (eq_attr "fpu_single" "yes")
9964		      (const_string "single") (const_string "double")))
9965   (set_attr "needs_delay_slot" "yes")])
9966
9967(define_insn "call_pop_compact_rettramp"
9968  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9969	 (match_operand 1 "" ""))
9970   (match_operand 2 "immediate_operand" "n")
9971   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9972				 (match_operand 3 "immediate_operand" "n")))
9973   (use (reg:SI R0_REG))
9974   (use (reg:SI R1_REG))
9975   (use (reg:SI FPSCR_MODES_REG))
9976   (clobber (reg:SI R10_REG))
9977   (clobber (reg:SI PR_REG))]
9978  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9979  "jsr	@%0%#"
9980  [(set_attr "type" "call")
9981   (set (attr "fp_mode")
9982	(if_then_else (eq_attr "fpu_single" "yes")
9983		      (const_string "single") (const_string "double")))
9984   (set_attr "needs_delay_slot" "yes")])
9985
9986(define_expand "call_pop"
9987  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9988		    (match_operand 1 "" ""))
9989	     (match_operand 2 "" "")
9990	     (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9991					   (match_operand 3 "" "")))])]
9992  "TARGET_SHCOMPACT"
9993{
9994  rtx cookie_rtx;
9995  long cookie;
9996  rtx func;
9997  rtx r0, r1;
9998
9999  gcc_assert (operands[2] && INTVAL (operands[2]));
10000  cookie_rtx = operands[2];
10001  cookie = INTVAL (cookie_rtx);
10002  func = XEXP (operands[0], 0);
10003
10004  if (flag_pic)
10005    {
10006      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10007	{
10008	  rtx reg = gen_reg_rtx (Pmode);
10009	  emit_insn (gen_symGOTPLT2reg (reg, func));
10010	  func = reg;
10011	}
10012      else
10013	func = legitimize_pic_address (func, Pmode, 0);
10014    }
10015
10016  r0 = gen_rtx_REG (SImode, R0_REG);
10017  r1 = gen_rtx_REG (SImode, R1_REG);
10018
10019  /* Since such a call function may use all call-clobbered
10020     registers, we force a mode switch earlier, so that we don't
10021     run out of registers when adjusting fpscr for the call.  */
10022  emit_insn (gen_force_mode_for_call ());
10023
10024  operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
10025				 SFUNC_GOT).sym;
10026  operands[0] = force_reg (SImode, operands[0]);
10027
10028  emit_move_insn (r0, func);
10029  emit_move_insn (r1, cookie_rtx);
10030
10031  if (cookie & CALL_COOKIE_RET_TRAMP (1))
10032    emit_call_insn (gen_call_pop_compact_rettramp
10033	   	     (operands[0], operands[1], operands[2], operands[3]));
10034  else
10035    emit_call_insn (gen_call_pop_compact
10036	  	     (operands[0], operands[1], operands[2], operands[3]));
10037
10038  DONE;
10039})
10040
10041(define_expand "call_value"
10042  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
10043		   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
10044				 (match_operand 2 "" "")))
10045	      (match_operand 3 "" "")
10046	      (use (reg:SI FPSCR_MODES_REG))
10047	      (clobber (reg:SI PR_REG))])]
10048  ""
10049{
10050  if (TARGET_FDPIC)
10051    {
10052      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
10053      emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ());
10054    }
10055
10056  if (TARGET_SHMEDIA)
10057    {
10058      operands[1] = shmedia_prepare_call_address (operands[1], 0);
10059      emit_call_insn (gen_call_value_media (operands[0], operands[1],
10060					    operands[2]));
10061      DONE;
10062    }
10063  else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
10064    {
10065      rtx cookie_rtx = operands[3];
10066      long cookie = INTVAL (cookie_rtx);
10067      rtx func = XEXP (operands[1], 0);
10068      rtx r0, r1;
10069
10070      if (flag_pic)
10071	{
10072	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10073	    {
10074	      rtx reg = gen_reg_rtx (Pmode);
10075
10076	      emit_insn (gen_symGOTPLT2reg (reg, func));
10077	      func = reg;
10078	    }
10079	  else
10080	    func = legitimize_pic_address (func, Pmode, 0);
10081	}
10082
10083      r0 = gen_rtx_REG (SImode, R0_REG);
10084      r1 = gen_rtx_REG (SImode, R1_REG);
10085
10086      /* Since such a call function may use all call-clobbered
10087	 registers, we force a mode switch earlier, so that we don't
10088	 run out of registers when adjusting fpscr for the call.  */
10089      emit_insn (gen_force_mode_for_call ());
10090
10091      operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
10092				     SFUNC_GOT).sym;
10093      operands[1] = force_reg (SImode, operands[1]);
10094
10095      emit_move_insn (r0, func);
10096      emit_move_insn (r1, cookie_rtx);
10097
10098      if (cookie & CALL_COOKIE_RET_TRAMP (1))
10099	emit_call_insn (gen_call_value_compact_rettramp (operands[0],
10100							 operands[1],
10101							 operands[2],
10102							 operands[3]));
10103      else
10104	emit_call_insn (gen_call_value_compact (operands[0], operands[1],
10105						operands[2], operands[3]));
10106
10107      DONE;
10108    }
10109  else if (TARGET_SHCOMPACT && flag_pic
10110	   && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
10111	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
10112    {
10113      rtx reg = gen_reg_rtx (Pmode);
10114
10115      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
10116      XEXP (operands[1], 0) = reg;
10117    }
10118  if (!flag_pic && TARGET_SH2A
10119      && MEM_P (operands[1])
10120      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
10121    {
10122      if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
10123	{
10124	  emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
10125				 XEXP (operands[1], 0), operands[2]));
10126	  DONE;
10127	}
10128    }
10129  if (flag_pic && TARGET_SH2
10130      && MEM_P (operands[1])
10131      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
10132    {
10133      emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
10134					    operands[2]));
10135      DONE;
10136    }
10137  else
10138    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
10139
10140  if (TARGET_FDPIC)
10141    {
10142      operands[1] = sh_load_function_descriptor (operands[1]);
10143      emit_call_insn (gen_call_valuei_fdpic (operands[0], operands[1],
10144					     operands[2]));
10145    }
10146  else
10147    emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
10148  DONE;
10149})
10150
10151(define_insn "sibcalli"
10152  [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
10153	 (match_operand 1 "" ""))
10154   (use (reg:SI FPSCR_MODES_REG))
10155   (return)]
10156  "TARGET_SH1 && !TARGET_FDPIC"
10157  "jmp	@%0%#"
10158  [(set_attr "needs_delay_slot" "yes")
10159   (set (attr "fp_mode")
10160	(if_then_else (eq_attr "fpu_single" "yes")
10161		      (const_string "single") (const_string "double")))
10162   (set_attr "type" "jump_ind")])
10163
10164(define_insn "sibcalli_fdpic"
10165  [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
10166	 (match_operand 1))
10167   (use (reg:SI FPSCR_MODES_REG))
10168   (use (reg:SI PIC_REG))
10169   (return)]
10170  "TARGET_FDPIC"
10171  "jmp	@%0%#"
10172  [(set_attr "needs_delay_slot" "yes")
10173   (set (attr "fp_mode")
10174	(if_then_else (eq_attr "fpu_single" "yes")
10175		      (const_string "single") (const_string "double")))
10176   (set_attr "type" "jump_ind")])
10177
10178(define_insn "sibcalli_pcrel"
10179  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
10180	 (match_operand 1 "" ""))
10181   (use (match_operand 2 "" ""))
10182   (use (reg:SI FPSCR_MODES_REG))
10183   (return)]
10184  "TARGET_SH2 && !TARGET_FDPIC"
10185{
10186  return       "braf	%0"	"\n"
10187	 "%O2:%#";
10188}
10189  [(set_attr "needs_delay_slot" "yes")
10190   (set (attr "fp_mode")
10191	(if_then_else (eq_attr "fpu_single" "yes")
10192		      (const_string "single") (const_string "double")))
10193   (set_attr "type" "jump_ind")])
10194
10195(define_insn "sibcalli_pcrel_fdpic"
10196  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
10197	 (match_operand 1))
10198   (use (match_operand 2))
10199   (use (reg:SI FPSCR_MODES_REG))
10200   (use (reg:SI PIC_REG))
10201   (return)]
10202  "TARGET_SH2 && TARGET_FDPIC"
10203{
10204  return       "braf	%0"	"\n"
10205	 "%O2:%#";
10206}
10207  [(set_attr "needs_delay_slot" "yes")
10208   (set (attr "fp_mode")
10209	(if_then_else (eq_attr "fpu_single" "yes")
10210		      (const_string "single") (const_string "double")))
10211   (set_attr "type" "jump_ind")])
10212
10213;; This uses an unspec to describe that the symbol_ref is very close.
10214(define_insn "sibcalli_thunk"
10215  [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
10216			     UNSPEC_THUNK))
10217	 (match_operand 1 "" ""))
10218   (use (reg:SI FPSCR_MODES_REG))
10219   (return)]
10220  "TARGET_SH1"
10221  "bra	%O0"
10222  [(set_attr "needs_delay_slot" "yes")
10223   (set (attr "fp_mode")
10224	(if_then_else (eq_attr "fpu_single" "yes")
10225		      (const_string "single") (const_string "double")))
10226   (set_attr "type" "jump")
10227   (set_attr "length" "2")])
10228
10229(define_insn_and_split "sibcall_pcrel"
10230  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
10231	 (match_operand 1 "" ""))
10232   (use (reg:SI FPSCR_MODES_REG))
10233   (clobber (match_scratch:SI 2 "=&k"))
10234   (return)]
10235  "TARGET_SH2 && !TARGET_FDPIC"
10236  "#"
10237  "reload_completed"
10238  [(const_int 0)]
10239{
10240  rtx lab = PATTERN (gen_call_site ());
10241  rtx call_insn;
10242
10243  sh_expand_sym_label2reg (operands[2], operands[0], lab, true);
10244  call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
10245						  copy_rtx (lab)));
10246  SIBLING_CALL_P (call_insn) = 1;
10247  DONE;
10248}
10249  [(set_attr "needs_delay_slot" "yes")
10250   (set (attr "fp_mode")
10251	(if_then_else (eq_attr "fpu_single" "yes")
10252		      (const_string "single") (const_string "double")))
10253   (set_attr "type" "jump_ind")])
10254
10255(define_insn_and_split "sibcall_pcrel_fdpic"
10256  [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand"))
10257	 (match_operand 1))
10258   (use (reg:SI FPSCR_MODES_REG))
10259   (use (reg:SI PIC_REG))
10260   (clobber (match_scratch:SI 2 "=k"))
10261   (return)]
10262  "TARGET_SH2 && TARGET_FDPIC"
10263  "#"
10264  "&& reload_completed"
10265  [(const_int 0)]
10266{
10267  rtx lab = PATTERN (gen_call_site ());
10268
10269  sh_expand_sym_label2reg (operands[2], operands[0], lab, true);
10270  rtx i = emit_call_insn (gen_sibcalli_pcrel_fdpic (operands[2], operands[1],
10271						    copy_rtx (lab)));
10272  SIBLING_CALL_P (i) = 1;
10273  DONE;
10274}
10275  [(set_attr "needs_delay_slot" "yes")
10276   (set (attr "fp_mode")
10277	(if_then_else (eq_attr "fpu_single" "yes")
10278		      (const_string "single") (const_string "double")))
10279   (set_attr "type" "jump_ind")])
10280
10281(define_insn "sibcall_compact"
10282  [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
10283	 (match_operand 1 "" ""))
10284   (return)
10285   (use (match_operand:SI 2 "register_operand" "z,x"))
10286   (use (reg:SI R1_REG))
10287   (use (reg:SI FPSCR_MODES_REG))
10288   ;; We want to make sure the `x' above will only match MACH_REG
10289   ;; because sibcall_epilogue may clobber MACL_REG.
10290   (clobber (reg:SI MACL_REG))]
10291  "TARGET_SHCOMPACT"
10292{
10293  static const char* alt[] =
10294  {
10295       "jmp	@%0%#",
10296
10297       "jmp	@%0"	"\n"
10298    "	sts	%2,r0"
10299  };
10300  return alt[which_alternative];
10301}
10302  [(set_attr "needs_delay_slot" "yes,no")
10303   (set_attr "length" "2,4")
10304   (set (attr "fp_mode") (const_string "single"))
10305   (set_attr "type" "jump_ind")])
10306
10307(define_insn "sibcall_media"
10308  [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
10309	 (match_operand 1 "" ""))
10310   (use (reg:SI PR_MEDIA_REG))
10311   (return)]
10312  "TARGET_SHMEDIA"
10313  "blink	%0, r63"
10314  [(set_attr "type" "jump_media")])
10315
10316(define_expand "sibcall"
10317  [(parallel
10318    [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
10319	   (match_operand 1 "" ""))
10320     (match_operand 2 "" "")
10321   (use (reg:SI FPSCR_MODES_REG))
10322     (return)])]
10323  ""
10324{
10325  if (TARGET_FDPIC)
10326    {
10327      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
10328      emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ());
10329    }
10330
10331  if (TARGET_SHMEDIA)
10332    {
10333      operands[0] = shmedia_prepare_call_address (operands[0], 1);
10334      emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
10335      DONE;
10336    }
10337  else if (TARGET_SHCOMPACT && operands[2]
10338	   && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
10339    {
10340      rtx cookie_rtx = operands[2];
10341      long cookie = INTVAL (cookie_rtx);
10342      rtx func = XEXP (operands[0], 0);
10343      rtx mach, r1;
10344
10345      if (flag_pic)
10346	{
10347	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10348	    {
10349	      rtx reg = gen_reg_rtx (Pmode);
10350
10351	      emit_insn (gen_symGOT2reg (reg, func));
10352	      func = reg;
10353	    }
10354	  else
10355	    func = legitimize_pic_address (func, Pmode, 0);
10356	}
10357
10358      /* FIXME: if we could tell whether all argument registers are
10359	 already taken, we could decide whether to force the use of
10360	 MACH_REG or to stick to R0_REG.  Unfortunately, there's no
10361	 simple way to tell.  We could use the CALL_COOKIE, but we
10362	 can't currently tell a register used for regular argument
10363	 passing from one that is unused.  If we leave it up to reload
10364	 to decide which register to use, it seems to always choose
10365	 R0_REG, which leaves no available registers in SIBCALL_REGS
10366	 to hold the address of the trampoline.  */
10367      mach = gen_rtx_REG (SImode, MACH_REG);
10368      r1 = gen_rtx_REG (SImode, R1_REG);
10369
10370      /* Since such a call function may use all call-clobbered
10371	 registers, we force a mode switch earlier, so that we don't
10372	 run out of registers when adjusting fpscr for the call.  */
10373      emit_insn (gen_force_mode_for_call ());
10374
10375      operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
10376				     SFUNC_GOT).sym;
10377      operands[0] = force_reg (SImode, operands[0]);
10378
10379      /* We don't need a return trampoline, since the callee will
10380	 return directly to the upper caller.  */
10381      if (cookie & CALL_COOKIE_RET_TRAMP (1))
10382	{
10383	  cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
10384	  cookie_rtx = GEN_INT (cookie);
10385	}
10386
10387      emit_move_insn (mach, func);
10388      emit_move_insn (r1, cookie_rtx);
10389
10390      emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
10391      DONE;
10392    }
10393  else if (TARGET_SHCOMPACT && flag_pic
10394	   && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
10395	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
10396    {
10397      rtx reg = gen_reg_rtx (Pmode);
10398
10399      emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
10400      XEXP (operands[0], 0) = reg;
10401    }
10402  if (flag_pic && TARGET_SH2
10403      && MEM_P (operands[0])
10404      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
10405      /* The PLT needs the PIC register, but the epilogue would have
10406	 to restore it, so we can only use PC-relative PIC calls for
10407	 static functions.  */
10408      && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
10409    {
10410      if (TARGET_FDPIC)
10411	emit_call_insn (gen_sibcall_pcrel_fdpic (XEXP (operands[0], 0),
10412						 operands[1]));
10413      else
10414	emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
10415      DONE;
10416    }
10417  else
10418    operands[0] = force_reg (SImode, XEXP (operands[0], 0));
10419
10420  if (TARGET_FDPIC)
10421    {
10422      operands[0] = sh_load_function_descriptor (operands[0]);
10423      emit_call_insn (gen_sibcalli_fdpic (operands[0], operands[1]));
10424    }
10425  else
10426    emit_call_insn (gen_sibcalli (operands[0], operands[1]));
10427  DONE;
10428})
10429
10430(define_insn "sibcall_valuei"
10431  [(set (match_operand 0 "" "=rf")
10432	(call (mem:SI (match_operand:SI 1 "register_operand" "k"))
10433	      (match_operand 2 "" "")))
10434   (use (reg:SI FPSCR_MODES_REG))
10435   (return)]
10436  "TARGET_SH1 && !TARGET_FDPIC"
10437  "jmp	@%1%#"
10438  [(set_attr "needs_delay_slot" "yes")
10439   (set (attr "fp_mode")
10440       (if_then_else (eq_attr "fpu_single" "yes")
10441		     (const_string "single") (const_string "double")))
10442   (set_attr "type" "jump_ind")])
10443
10444(define_insn "sibcall_valuei_fdpic"
10445  [(set (match_operand 0 "" "=rf")
10446	(call (mem:SI (match_operand:SI 1 "register_operand" "k"))
10447	      (match_operand 2)))
10448   (use (reg:SI FPSCR_MODES_REG))
10449   (use (reg:SI PIC_REG))
10450   (return)]
10451  "TARGET_FDPIC"
10452  "jmp	@%1%#"
10453  [(set_attr "needs_delay_slot" "yes")
10454   (set (attr "fp_mode")
10455	(if_then_else (eq_attr "fpu_single" "yes")
10456		      (const_string "single") (const_string "double")))
10457   (set_attr "type" "jump_ind")])
10458
10459(define_insn "sibcall_valuei_pcrel"
10460  [(set (match_operand 0 "" "=rf")
10461	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
10462	      (match_operand 2 "" "")))
10463   (use (match_operand 3 "" ""))
10464   (use (reg:SI FPSCR_MODES_REG))
10465   (return)]
10466  "TARGET_SH2 && !TARGET_FDPIC"
10467{
10468  return       "braf	%1"	"\n"
10469	 "%O3:%#";
10470}
10471  [(set_attr "needs_delay_slot" "yes")
10472   (set (attr "fp_mode")
10473	(if_then_else (eq_attr "fpu_single" "yes")
10474		      (const_string "single") (const_string "double")))
10475   (set_attr "type" "jump_ind")])
10476
10477(define_insn "sibcall_valuei_pcrel_fdpic"
10478  [(set (match_operand 0 "" "=rf")
10479	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
10480	      (match_operand 2)))
10481   (use (match_operand 3))
10482   (use (reg:SI FPSCR_MODES_REG))
10483   (use (reg:SI PIC_REG))
10484   (return)]
10485  "TARGET_SH2 && TARGET_FDPIC"
10486{
10487  return       "braf	%1"	"\n"
10488	 "%O3:%#";
10489}
10490  [(set_attr "needs_delay_slot" "yes")
10491   (set (attr "fp_mode")
10492	(if_then_else (eq_attr "fpu_single" "yes")
10493		      (const_string "single") (const_string "double")))
10494   (set_attr "type" "jump_ind")])
10495
10496;; sibcall_value_pcrel used to have a =&k clobber for the scratch register
10497;; that it needs for the branch address.  This causes troubles when there
10498;; is a big overlap of argument and return value registers.  Hence, use a
10499;; fixed call clobbered register for the address.  See also PR 67260.
10500(define_insn_and_split "sibcall_value_pcrel"
10501  [(set (match_operand 0 "" "=rf")
10502	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
10503	      (match_operand 2 "" "")))
10504   (use (reg:SI FPSCR_MODES_REG))
10505   (clobber (reg:SI R1_REG))
10506   (return)]
10507  "TARGET_SH2 && !TARGET_FDPIC"
10508  "#"
10509  "reload_completed"
10510  [(const_int 0)]
10511{
10512  rtx lab = PATTERN (gen_call_site ());
10513  rtx call_insn;
10514
10515  operands[3] =  gen_rtx_REG (SImode, R1_REG);
10516
10517  sh_expand_sym_label2reg (operands[3], operands[1], lab, true);
10518  call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
10519							operands[3],
10520							operands[2],
10521							copy_rtx (lab)));
10522  SIBLING_CALL_P (call_insn) = 1;
10523  DONE;
10524}
10525  [(set_attr "needs_delay_slot" "yes")
10526   (set (attr "fp_mode")
10527	(if_then_else (eq_attr "fpu_single" "yes")
10528		      (const_string "single") (const_string "double")))
10529   (set_attr "type" "jump_ind")])
10530
10531;; Like for sibcall_value_pcrel, use a fixed call clobbered register for
10532;; the branch address.
10533(define_insn_and_split "sibcall_value_pcrel_fdpic"
10534  [(set (match_operand 0 "" "=rf")
10535	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand"))
10536	      (match_operand 2)))
10537   (use (reg:SI FPSCR_MODES_REG))
10538   (use (reg:SI PIC_REG))
10539   (clobber (reg:SI R1_REG))
10540   (return)]
10541  "TARGET_SH2 && TARGET_FDPIC"
10542  "#"
10543  "&& reload_completed"
10544  [(const_int 0)]
10545{
10546  rtx lab = PATTERN (gen_call_site ());
10547
10548  operands[3] =  gen_rtx_REG (SImode, R1_REG);
10549
10550  sh_expand_sym_label2reg (operands[3], operands[1], lab, true);
10551  rtx i = emit_call_insn (gen_sibcall_valuei_pcrel_fdpic (operands[0],
10552							  operands[3],
10553							  operands[2],
10554							  copy_rtx (lab)));
10555  SIBLING_CALL_P (i) = 1;
10556  DONE;
10557}
10558  [(set_attr "needs_delay_slot" "yes")
10559   (set (attr "fp_mode")
10560	(if_then_else (eq_attr "fpu_single" "yes")
10561		      (const_string "single") (const_string "double")))
10562   (set_attr "type" "jump_ind")])
10563
10564(define_insn "sibcall_value_compact"
10565  [(set (match_operand 0 "" "=rf,rf")
10566	(call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
10567	      (match_operand 2 "" "")))
10568   (return)
10569   (use (match_operand:SI 3 "register_operand" "z,x"))
10570   (use (reg:SI R1_REG))
10571   (use (reg:SI FPSCR_MODES_REG))
10572   ;; We want to make sure the `x' above will only match MACH_REG
10573   ;; because sibcall_epilogue may clobber MACL_REG.
10574   (clobber (reg:SI MACL_REG))]
10575  "TARGET_SHCOMPACT"
10576{
10577  static const char* alt[] =
10578  {
10579       "jmp	@%1%#",
10580
10581       "jmp	@%1"	"\n"
10582    "	sts	%3,r0"
10583  };
10584  return alt[which_alternative];
10585}
10586  [(set_attr "needs_delay_slot" "yes,no")
10587   (set_attr "length" "2,4")
10588   (set (attr "fp_mode") (const_string "single"))
10589   (set_attr "type" "jump_ind")])
10590
10591(define_insn "sibcall_value_media"
10592  [(set (match_operand 0 "" "=rf")
10593	(call (mem:DI (match_operand 1 "target_reg_operand" "k"))
10594	      (match_operand 2 "" "")))
10595   (use (reg:SI PR_MEDIA_REG))
10596   (return)]
10597  "TARGET_SHMEDIA"
10598  "blink	%1, r63"
10599  [(set_attr "type" "jump_media")])
10600
10601(define_expand "sibcall_value"
10602  [(parallel
10603    [(set (match_operand 0 "arith_reg_operand" "")
10604	  (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
10605	  	(match_operand 2 "" "")))
10606     (match_operand 3 "" "")
10607   (use (reg:SI FPSCR_MODES_REG))
10608     (return)])]
10609  ""
10610{
10611  if (TARGET_FDPIC)
10612    {
10613      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
10614      emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ());
10615    }
10616
10617  if (TARGET_SHMEDIA)
10618    {
10619      operands[1] = shmedia_prepare_call_address (operands[1], 1);
10620      emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
10621					       operands[2]));
10622      DONE;
10623    }
10624  else if (TARGET_SHCOMPACT && operands[3]
10625	   && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
10626    {
10627      rtx cookie_rtx = operands[3];
10628      long cookie = INTVAL (cookie_rtx);
10629      rtx func = XEXP (operands[1], 0);
10630      rtx mach, r1;
10631
10632      if (flag_pic)
10633	{
10634	  if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10635	    {
10636	      rtx reg = gen_reg_rtx (Pmode);
10637
10638	      emit_insn (gen_symGOT2reg (reg, func));
10639	      func = reg;
10640	    }
10641	  else
10642	    func = legitimize_pic_address (func, Pmode, 0);
10643	}
10644
10645      /* FIXME: if we could tell whether all argument registers are
10646	 already taken, we could decide whether to force the use of
10647	 MACH_REG or to stick to R0_REG.  Unfortunately, there's no
10648	 simple way to tell.  We could use the CALL_COOKIE, but we
10649	 can't currently tell a register used for regular argument
10650	 passing from one that is unused.  If we leave it up to reload
10651	 to decide which register to use, it seems to always choose
10652	 R0_REG, which leaves no available registers in SIBCALL_REGS
10653	 to hold the address of the trampoline.  */
10654      mach = gen_rtx_REG (SImode, MACH_REG);
10655      r1 = gen_rtx_REG (SImode, R1_REG);
10656
10657      /* Since such a call function may use all call-clobbered
10658	 registers, we force a mode switch earlier, so that we don't
10659	 run out of registers when adjusting fpscr for the call.  */
10660      emit_insn (gen_force_mode_for_call ());
10661
10662      operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
10663				     SFUNC_GOT).sym;
10664      operands[1] = force_reg (SImode, operands[1]);
10665
10666      /* We don't need a return trampoline, since the callee will
10667	 return directly to the upper caller.  */
10668      if (cookie & CALL_COOKIE_RET_TRAMP (1))
10669	{
10670	  cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
10671	  cookie_rtx = GEN_INT (cookie);
10672	}
10673
10674      emit_move_insn (mach, func);
10675      emit_move_insn (r1, cookie_rtx);
10676
10677      emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
10678						 operands[2], mach));
10679      DONE;
10680    }
10681  else if (TARGET_SHCOMPACT && flag_pic
10682	   && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
10683	   && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
10684    {
10685      rtx reg = gen_reg_rtx (Pmode);
10686
10687      emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
10688      XEXP (operands[1], 0) = reg;
10689    }
10690  if (flag_pic && TARGET_SH2
10691      && MEM_P (operands[1])
10692      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
10693      /* The PLT needs the PIC register, but the epilogue would have
10694	 to restore it, so we can only use PC-relative PIC calls for
10695	 static functions.  */
10696      && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
10697    {
10698      if (TARGET_FDPIC)
10699       emit_call_insn (gen_sibcall_value_pcrel_fdpic (operands[0],
10700						      XEXP (operands[1], 0),
10701						      operands[2]));
10702      else
10703       emit_call_insn (gen_sibcall_value_pcrel (operands[0],
10704						XEXP (operands[1], 0),
10705						operands[2]));
10706      DONE;
10707    }
10708  else
10709    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
10710
10711  if (TARGET_FDPIC)
10712    {
10713      operands[1] = sh_load_function_descriptor (operands[1]);
10714      emit_call_insn (gen_sibcall_valuei_fdpic (operands[0], operands[1],
10715						operands[2]));
10716    }
10717  else
10718    emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
10719  DONE;
10720})
10721
10722(define_insn "call_value_pop_compact"
10723  [(set (match_operand 0 "" "=rf")
10724	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
10725	      (match_operand 2 "" "")))
10726   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
10727				 (match_operand 4 "immediate_operand" "n")))
10728   (match_operand 3 "immediate_operand" "n")
10729   (use (reg:SI R0_REG))
10730   (use (reg:SI R1_REG))
10731   (use (reg:SI FPSCR_MODES_REG))
10732   (clobber (reg:SI PR_REG))]
10733  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
10734  "jsr	@%1%#"
10735  [(set_attr "type" "call")
10736   (set (attr "fp_mode")
10737	(if_then_else (eq_attr "fpu_single" "yes")
10738		      (const_string "single") (const_string "double")))
10739   (set_attr "needs_delay_slot" "yes")])
10740
10741(define_insn "call_value_pop_compact_rettramp"
10742  [(set (match_operand 0 "" "=rf")
10743	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
10744	      (match_operand 2 "" "")))
10745   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
10746				 (match_operand 4 "immediate_operand" "n")))
10747   (match_operand 3 "immediate_operand" "n")
10748   (use (reg:SI R0_REG))
10749   (use (reg:SI R1_REG))
10750   (use (reg:SI FPSCR_MODES_REG))
10751   (clobber (reg:SI R10_REG))
10752   (clobber (reg:SI PR_REG))]
10753  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
10754  "jsr	@%1%#"
10755  [(set_attr "type" "call")
10756   (set (attr "fp_mode")
10757	(if_then_else (eq_attr "fpu_single" "yes")
10758		      (const_string "single") (const_string "double")))
10759   (set_attr "needs_delay_slot" "yes")])
10760
10761(define_expand "call_value_pop"
10762  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
10763		   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
10764				 (match_operand 2 "" "")))
10765	      (match_operand 3 "" "")
10766	      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
10767					    (match_operand 4 "" "")))])]
10768  "TARGET_SHCOMPACT"
10769{
10770  rtx cookie_rtx;
10771  long cookie;
10772  rtx func;
10773  rtx r0, r1;
10774
10775  gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
10776  cookie_rtx = operands[3];
10777  cookie = INTVAL (cookie_rtx);
10778  func = XEXP (operands[1], 0);
10779
10780  if (flag_pic)
10781    {
10782      if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10783	{
10784	  rtx reg = gen_reg_rtx (Pmode);
10785
10786	  emit_insn (gen_symGOTPLT2reg (reg, func));
10787	  func = reg;
10788	}
10789      else
10790	func = legitimize_pic_address (func, Pmode, 0);
10791    }
10792
10793  r0 = gen_rtx_REG (SImode, R0_REG);
10794  r1 = gen_rtx_REG (SImode, R1_REG);
10795
10796  /* Since such a call function may use all call-clobbered
10797     registers, we force a mode switch earlier, so that we don't
10798     run out of registers when adjusting fpscr for the call.  */
10799  emit_insn (gen_force_mode_for_call ());
10800
10801  operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
10802				 SFUNC_GOT).sym;
10803  operands[1] = force_reg (SImode, operands[1]);
10804
10805  emit_move_insn (r0, func);
10806  emit_move_insn (r1, cookie_rtx);
10807
10808  if (cookie & CALL_COOKIE_RET_TRAMP (1))
10809    emit_call_insn (gen_call_value_pop_compact_rettramp
10810			(operands[0], operands[1], operands[2],
10811			 operands[3], operands[4]));
10812  else
10813    emit_call_insn (gen_call_value_pop_compact
10814			(operands[0], operands[1], operands[2],
10815			 operands[3], operands[4]));
10816
10817  DONE;
10818})
10819
10820(define_expand "sibcall_epilogue"
10821  [(return)]
10822  ""
10823{
10824  sh_expand_epilogue (true);
10825  if (TARGET_SHCOMPACT)
10826    {
10827      rtx_insn *insn;
10828      rtx set;
10829
10830      /* If epilogue clobbers r0, preserve it in macl.  */
10831      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
10832	if ((set = single_set (insn))
10833	    && REG_P (SET_DEST (set))
10834	    && REGNO (SET_DEST (set)) == R0_REG)
10835	  {
10836	    rtx r0 = gen_rtx_REG (SImode, R0_REG);
10837	    rtx tmp = gen_rtx_REG (SImode, MACL_REG);
10838
10839	    /* We can't tell at this point whether the sibcall is a
10840	       sibcall_compact and, if it is, whether it uses r0 or
10841	       mach as operand 2, so let the instructions that
10842	       preserve r0 be optimized away if r0 turns out to be
10843	       dead.  */
10844	    emit_insn_before (gen_rtx_SET (tmp, r0), insn);
10845	    emit_move_insn (r0, tmp);
10846	    break;
10847	  }
10848    }
10849  DONE;
10850})
10851
10852(define_insn "indirect_jump_compact"
10853  [(set (pc)
10854	(match_operand:SI 0 "arith_reg_operand" "r"))]
10855  "TARGET_SH1"
10856  "jmp	@%0%#"
10857  [(set_attr "needs_delay_slot" "yes")
10858   (set_attr "type" "jump_ind")])
10859
10860(define_expand "indirect_jump"
10861  [(set (pc)
10862	(match_operand 0 "register_operand" ""))]
10863  ""
10864{
10865  if (GET_MODE (operands[0]) != Pmode)
10866    operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
10867})
10868
10869;; The use of operand 1 / 2 helps us distinguish case table jumps
10870;; which can be present in structured code from indirect jumps which can not
10871;; be present in structured code.  This allows -fprofile-arcs to work.
10872
10873;; For SH1 processors.
10874(define_insn "casesi_jump_1"
10875  [(set (pc)
10876	(match_operand:SI 0 "register_operand" "r"))
10877   (use (label_ref (match_operand 1 "" "")))]
10878  "TARGET_SH1"
10879  "jmp	@%0%#"
10880  [(set_attr "needs_delay_slot" "yes")
10881   (set_attr "type" "jump_ind")])
10882
10883;; For all later processors.
10884(define_insn "casesi_jump_2"
10885  [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
10886		      (label_ref (match_operand 1 "" ""))))
10887   (use (label_ref (match_operand 2 "" "")))]
10888  "TARGET_SH2
10889   && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
10890  "braf	%0%#"
10891  [(set_attr "needs_delay_slot" "yes")
10892   (set_attr "type" "jump_ind")])
10893
10894(define_insn "casesi_jump_media"
10895  [(set (pc) (match_operand 0 "target_reg_operand" "b"))
10896   (use (label_ref (match_operand 1 "" "")))]
10897  "TARGET_SHMEDIA"
10898  "blink	%0, r63"
10899  [(set_attr "type" "jump_media")])
10900
10901;; Call subroutine returning any type.
10902;; ??? This probably doesn't work.
10903(define_expand "untyped_call"
10904  [(parallel [(call (match_operand 0 "" "")
10905		    (const_int 0))
10906	      (match_operand 1 "" "")
10907	      (match_operand 2 "" "")])]
10908  "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
10909{
10910  if (! TARGET_SHMEDIA)
10911    {
10912      /* RA does not know that the call sets the function value registers.
10913	 We avoid problems by claiming that those registers are clobbered
10914	 at this point.  */
10915      for (int i = 0; i < XVECLEN (operands[2], 0); i++)
10916	{
10917	  rtx set = XVECEXP (operands[2], 0, i);
10918	  emit_clobber (SET_SRC (set));
10919	}
10920    }
10921
10922  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
10923
10924  for (int i = 0; i < XVECLEN (operands[2], 0); i++)
10925    {
10926      rtx set = XVECEXP (operands[2], 0, i);
10927      emit_move_insn (SET_DEST (set), SET_SRC (set));
10928    }
10929
10930  /* The optimizer does not know that the call sets the function value
10931     registers we stored in the result block.  We avoid problems by
10932     claiming that all hard registers are used and clobbered at this
10933     point.  */
10934  emit_insn (gen_blockage ());
10935
10936  DONE;
10937})
10938
10939;; ------------------------------------------------------------------------
10940;; Misc insns
10941;; ------------------------------------------------------------------------
10942
10943(define_insn "dect"
10944  [(set (reg:SI T_REG)
10945	(eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
10946   (set (match_operand:SI 0 "arith_reg_dest" "=r")
10947	(plus:SI (match_dup 1) (const_int -1)))]
10948  "TARGET_SH2"
10949  "dt	%0"
10950  [(set_attr "type" "arith")])
10951
10952(define_insn "nop"
10953  [(const_int 0)]
10954  ""
10955  "nop")
10956
10957;; Load address of a label. This is only generated by the casesi expand,
10958;; and by machine_dependent_reorg (fixing up fp moves).
10959;; This must use unspec, because this only works for labels that are
10960;; within range.
10961(define_insn "mova"
10962  [(set (reg:SI R0_REG)
10963	(unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
10964  "TARGET_SH1"
10965  "mova	%O0,r0"
10966  [(set_attr "in_delay_slot" "no")
10967   (set_attr "type" "arith")])
10968
10969;; machine_dependent_reorg will make this a `mova'.
10970(define_insn "mova_const"
10971  [(set (reg:SI R0_REG)
10972	(unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
10973  "TARGET_SH1"
10974  "#"
10975  [(set_attr "in_delay_slot" "no")
10976   (set_attr "type" "arith")])
10977
10978;; Loads of the GOTPC relocation values must not be optimized away
10979;; by e.g. any kind of CSE and must stay as they are.  Although there
10980;; are other various ways to ensure this, we use an artificial counter
10981;; operand to generate unique symbols.
10982(define_expand "GOTaddr2picreg"
10983  [(set (reg:SI R0_REG)
10984	(unspec:SI [(const:SI (unspec:SI [(match_dup 2)
10985					  (match_operand:SI 0 "" "")]
10986					 UNSPEC_PIC))] UNSPEC_MOVA))
10987   (set (match_dup 1)
10988	(const:SI (unspec:SI [(match_dup 2) (match_dup 0)] UNSPEC_PIC)))
10989   (set (match_dup 1) (plus:SI (match_dup 1) (reg:SI R0_REG)))]
10990  ""
10991{
10992  if (TARGET_VXWORKS_RTP)
10993    {
10994      rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
10995      rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
10996      emit_insn (gen_vxworks_picreg (gott_base, gott_index));
10997      DONE;
10998    }
10999
11000  if (TARGET_FDPIC)
11001    {
11002      rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG);
11003      emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ());
11004      DONE;
11005    }
11006
11007  operands[1] = gen_rtx_REG (Pmode, PIC_REG);
11008  operands[2] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
11009
11010  if (TARGET_SHMEDIA)
11011    {
11012      rtx tr = gen_rtx_REG (Pmode, TR0_REG);
11013      rtx pic = operands[1];
11014      rtx lab = PATTERN (gen_call_site ());
11015      rtx insn, equiv;
11016
11017      equiv = operands[2];
11018      operands[2] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], lab),
11019				    UNSPEC_PCREL_SYMOFF);
11020      operands[2] = gen_rtx_CONST (Pmode, operands[2]);
11021
11022      if (Pmode == SImode)
11023	{
11024	  emit_insn (gen_movsi_const (pic, operands[2]));
11025	  emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
11026	}
11027      else
11028	{
11029	  emit_insn (gen_movdi_const (pic, operands[2]));
11030	  emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
11031	}
11032
11033      insn = emit_move_insn (operands[1], tr);
11034
11035      set_unique_reg_note (insn, REG_EQUAL, equiv);
11036
11037      DONE;
11038    }
11039})
11040
11041;; A helper for GOTaddr2picreg to finish up the initialization of the
11042;; PIC register.
11043(define_expand "vxworks_picreg"
11044  [(set (reg:SI PIC_REG)
11045	(const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
11046   (set (reg:SI R0_REG)
11047	(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
11048   (set (reg:SI PIC_REG)
11049	(mem:SI (reg:SI PIC_REG)))
11050   (set (reg:SI PIC_REG)
11051	(mem:SI (plus:SI (reg:SI PIC_REG)
11052			 (reg:SI R0_REG))))]
11053  "TARGET_VXWORKS_RTP")
11054
11055(define_insn "*ptb"
11056  [(set (match_operand 0 "target_reg_operand" "=b")
11057	(const (unspec [(match_operand 1 "" "Csy")]
11058			     UNSPEC_DATALABEL)))]
11059  "TARGET_SHMEDIA && flag_pic
11060   && satisfies_constraint_Csy (operands[1])"
11061  "ptb/u	datalabel %1, %0"
11062  [(set_attr "type" "ptabs_media")
11063   (set_attr "length" "*")])
11064
11065(define_insn "ptrel_si"
11066  [(set (match_operand:SI 0 "target_reg_operand" "=b")
11067	(plus:SI (match_operand:SI 1 "register_operand" "r")
11068	      (pc)))
11069   (match_operand:SI 2 "" "")]
11070  "TARGET_SHMEDIA"
11071  "%O2: ptrel/u	%1, %0"
11072  [(set_attr "type" "ptabs_media")])
11073
11074(define_insn "ptrel_di"
11075  [(set (match_operand:DI 0 "target_reg_operand" "=b")
11076	(plus:DI (match_operand:DI 1 "register_operand" "r")
11077	      (pc)))
11078   (match_operand:DI 2 "" "")]
11079  "TARGET_SHMEDIA"
11080  "%O2: ptrel/u	%1, %0"
11081  [(set_attr "type" "ptabs_media")])
11082
11083(define_expand "builtin_setjmp_receiver"
11084  [(match_operand 0 "" "")]
11085  "flag_pic"
11086{
11087  emit_insn (gen_GOTaddr2picreg (const0_rtx));
11088  DONE;
11089})
11090
11091(define_expand "call_site"
11092  [(unspec [(match_dup 0)] UNSPEC_CALLER)]
11093  "TARGET_SH1"
11094{
11095  static HOST_WIDE_INT i = 0;
11096  operands[0] = GEN_INT (i);
11097  i++;
11098})
11099
11100;; op0 = op1 + r12 but hide it before reload completed.  See the comment
11101;; in symGOT_load expand.
11102(define_insn_and_split "chk_guard_add"
11103  [(set (match_operand:SI 0 "register_operand" "=&r")
11104	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
11105		    (reg:SI PIC_REG)]
11106		   UNSPEC_CHKADD))]
11107  "TARGET_SH1"
11108  "#"
11109  "TARGET_SH1 && reload_completed"
11110  [(set (match_dup 0) (reg:SI PIC_REG))
11111   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
11112  ""
11113  [(set_attr "type" "arith")])
11114
11115(define_expand "sym_label2reg"
11116  [(set (match_operand:SI 0 "" "")
11117	(const:SI (unspec:SI [(match_operand:SI 1 "" "")
11118			      (const (plus:SI (match_operand:SI 2 "" "")
11119					      (const_int 2)))]
11120			     UNSPEC_SYMOFF)))]
11121  "TARGET_SH1" "")
11122
11123(define_expand "symPCREL_label2reg"
11124  [(set (match_operand:SI 0 "" "")
11125	(const:SI
11126	 (unspec:SI
11127	  [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PCREL))
11128	   (const:SI (plus:SI (match_operand:SI 2 "" "")
11129			      (const_int 2)))] UNSPEC_PCREL_SYMOFF)))]
11130  "TARGET_SH1"
11131  "")
11132
11133(define_expand "symGOT_load"
11134  [(set (match_dup 2) (match_operand 1 "" ""))
11135   (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
11136   (set (match_operand 0 "" "") (mem (match_dup 3)))]
11137  ""
11138{
11139  rtx mem;
11140  bool stack_chk_guard_p = false;
11141
11142  rtx picreg = TARGET_FDPIC ? sh_get_fdpic_reg_initial_val ()
11143			    : gen_rtx_REG (Pmode, PIC_REG);
11144
11145  operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
11146  operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
11147
11148  if (!TARGET_SHMEDIA && !TARGET_FDPIC
11149      && flag_stack_protect
11150      && GET_CODE (operands[1]) == CONST
11151      && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
11152      && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
11153      && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
11154		 "__stack_chk_guard") == 0)
11155    stack_chk_guard_p = true;
11156
11157  if (TARGET_SHMEDIA)
11158    {
11159      rtx reg = operands[2];
11160
11161      if (Pmode == DImode)
11162	{      
11163	  if (flag_pic > 1)
11164	    emit_insn (gen_movdi_const_32bit (reg, operands[1]));
11165	  else
11166	    emit_insn (gen_movdi_const_16bit (reg, operands[1]));
11167	}
11168      else
11169	{
11170	  if (flag_pic > 1)
11171	    emit_insn (gen_movsi_const (reg, operands[1]));
11172	  else
11173	    emit_insn (gen_movsi_const_16bit (reg, operands[1]));
11174	}
11175    }
11176  else
11177    emit_move_insn (operands[2], operands[1]);
11178
11179  /* When stack protector inserts codes after the result is set to
11180     R0, @(rX, r12) will cause a spill failure for R0.  Use a unspec
11181     insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
11182     when rX is a GOT address for the guard symbol.  Ugly but doesn't
11183     matter because this is a rare situation.  */
11184  if (stack_chk_guard_p)
11185    emit_insn (gen_chk_guard_add (operands[3], operands[2]));
11186  else
11187    emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2], picreg));
11188
11189  /* N.B. This is not constant for a GOTPLT relocation.  */
11190  mem = gen_rtx_MEM (Pmode, operands[3]);
11191  MEM_NOTRAP_P (mem) = 1;
11192  /* ??? Should we have a special alias set for the GOT?  */
11193  emit_move_insn (operands[0], mem);
11194
11195  DONE;
11196})
11197
11198(define_expand "sym2GOT"
11199  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
11200  ""
11201  "")
11202
11203(define_expand "symGOT2reg"
11204  [(match_operand 0 "" "") (match_operand 1 "" "")]
11205  ""
11206{
11207  rtx gotsym, insn;
11208
11209  gotsym = gen_sym2GOT (operands[1]);
11210  PUT_MODE (gotsym, Pmode);
11211  insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
11212
11213  MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
11214
11215  DONE;
11216})
11217
11218(define_expand "sym2GOTFUNCDESC"
11219  [(const (unspec [(match_operand 0)] UNSPEC_GOTFUNCDESC))]
11220  "TARGET_FDPIC")
11221
11222(define_expand "symGOTFUNCDESC2reg"
11223  [(match_operand 0) (match_operand 1)]
11224  "TARGET_FDPIC"
11225{
11226  rtx gotsym = gen_sym2GOTFUNCDESC (operands[1]);
11227  PUT_MODE (gotsym, Pmode);
11228  rtx insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
11229
11230  MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
11231
11232  DONE;
11233})
11234
11235(define_expand "symGOTPLT2reg"
11236  [(match_operand 0 "" "") (match_operand 1 "" "")]
11237  ""
11238{
11239  rtx pltsym = gen_rtx_CONST (Pmode,
11240			      gen_rtx_UNSPEC (Pmode,
11241					      gen_rtvec (1, operands[1]),
11242					      UNSPEC_GOTPLT));
11243  emit_insn (gen_symGOT_load (operands[0], pltsym));
11244  DONE;
11245})
11246
11247(define_expand "sym2GOTOFF"
11248  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
11249  ""
11250  "")
11251
11252(define_expand "symGOTOFF2reg"
11253  [(match_operand 0 "" "") (match_operand 1 "" "")]
11254  ""
11255{
11256  rtx gotoffsym, insn;
11257  rtx t = (!can_create_pseudo_p ()
11258	   ? operands[0]
11259	   : gen_reg_rtx (GET_MODE (operands[0])));
11260
11261  rtx picreg = TARGET_FDPIC ? sh_get_fdpic_reg_initial_val ()
11262			    : gen_rtx_REG (Pmode, PIC_REG);
11263
11264  gotoffsym = gen_sym2GOTOFF (operands[1]);
11265  PUT_MODE (gotoffsym, Pmode);
11266  emit_move_insn (t, gotoffsym);
11267  insn = emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg));
11268
11269  set_unique_reg_note (insn, REG_EQUAL, operands[1]);
11270
11271  DONE;
11272})
11273
11274(define_expand "sym2GOTOFFFUNCDESC"
11275  [(const (unspec [(match_operand 0)] UNSPEC_GOTOFFFUNCDESC))]
11276  "TARGET_FDPIC")
11277
11278(define_expand "symGOTOFFFUNCDESC2reg"
11279  [(match_operand 0) (match_operand 1)]
11280  "TARGET_FDPIC"
11281{
11282  rtx picreg = sh_get_fdpic_reg_initial_val ();
11283  rtx t = !can_create_pseudo_p ()
11284	  ? operands[0]
11285	  : gen_reg_rtx (GET_MODE (operands[0]));
11286
11287  rtx gotoffsym = gen_sym2GOTOFFFUNCDESC (operands[1]);
11288  PUT_MODE (gotoffsym, Pmode);
11289  emit_move_insn (t, gotoffsym);
11290  emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg));
11291  DONE;
11292})
11293
11294(define_expand "symPLT_label2reg"
11295  [(set (match_operand:SI 0 "" "")
11296	(const:SI
11297	 (unspec:SI
11298	  [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
11299	   (const:SI (plus:SI (match_operand:SI 2 "" "")
11300			      (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
11301   ;; Even though the PIC register is not really used by the call
11302   ;; sequence in which this is expanded, the PLT code assumes the PIC
11303   ;; register is set, so we must not skip its initialization.  Since
11304   ;; we only use this expand as part of calling sequences, and never
11305   ;; to take the address of a function, this is the best point to
11306   ;; insert the (use).  Using the PLT to take the address of a
11307   ;; function would be wrong, not only because the PLT entry could
11308   ;; then be called from a function that doesn't initialize the PIC
11309   ;; register to the proper GOT, but also because pointers to the
11310   ;; same function might not compare equal, should they be set by
11311   ;; different shared libraries.
11312   (use (reg:SI PIC_REG))]
11313  "TARGET_SH1"
11314  "")
11315
11316(define_expand "sym2PIC"
11317  [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
11318  ""
11319  "")
11320
11321;; -------------------------------------------------------------------------
11322;; TLS code generation.
11323
11324;; FIXME: The multi-insn asm blocks should be converted to use
11325;; define_insn_and_split.
11326;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
11327;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
11328;; for details.
11329
11330(define_insn "tls_global_dynamic"
11331  [(set (match_operand:SI 0 "register_operand" "=&z")
11332	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
11333				  UNSPEC_TLSGD))
11334	      (const_int 0)))
11335   (use (reg:SI FPSCR_MODES_REG))
11336   (use (reg:SI PIC_REG))
11337   (clobber (reg:SI PR_REG))
11338   (clobber (scratch:SI))]
11339  "TARGET_SH1"
11340{
11341  return       "mov.l	1f,r4"			"\n"
11342	 "	mova	2f,r0"			"\n"
11343	 "	mov.l	2f,r1"			"\n"
11344	 "	add	r0,r1"			"\n"
11345	 "	jsr	@r1"			"\n"
11346	 "	add	r12,r4"			"\n"
11347	 "	bra	3f"			"\n"
11348	 "	nop"				"\n"
11349	 "	.align	2"			"\n"
11350	 "1:	.long	%a1@TLSGD"		"\n"
11351	 "2:	.long	__tls_get_addr@PLT"	"\n"
11352	 "3:";
11353}
11354  [(set_attr "type" "tls_load")
11355   (set_attr "length" "26")])
11356
11357(define_insn "tls_local_dynamic"
11358  [(set (match_operand:SI 0 "register_operand" "=&z")
11359	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
11360				  UNSPEC_TLSLDM))
11361	      (const_int 0)))
11362   (use (reg:SI FPSCR_MODES_REG))
11363   (use (reg:SI PIC_REG))
11364   (clobber (reg:SI PR_REG))
11365   (clobber (scratch:SI))]
11366  "TARGET_SH1"
11367{
11368  return       "mov.l	1f,r4"			"\n"
11369	 "	mova	2f,r0"			"\n"
11370	 "	mov.l	2f,r1"			"\n"
11371	 "	add	r0,r1"			"\n"
11372	 "	jsr	@r1"			"\n"
11373	 "	add	r12,r4"			"\n"
11374	 "	bra	3f"			"\n"
11375	 "	nop"				"\n"
11376	 "	.align	2"			"\n"
11377	 "1:	.long	%a1@TLSLDM"		"\n"
11378	 "2:	.long	__tls_get_addr@PLT"	"\n"
11379	 "3:";
11380}
11381  [(set_attr "type" "tls_load")
11382   (set_attr "length" "26")])
11383
11384(define_expand "sym2DTPOFF"
11385  [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
11386  ""
11387  "")
11388
11389(define_expand "symDTPOFF2reg"
11390  [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
11391  ""
11392{
11393  rtx dtpoffsym;
11394  rtx t = (!can_create_pseudo_p ()
11395	   ? operands[0]
11396	   : gen_reg_rtx (GET_MODE (operands[0])));
11397
11398  dtpoffsym = gen_sym2DTPOFF (operands[1]);
11399  PUT_MODE (dtpoffsym, Pmode);
11400  emit_move_insn (t, dtpoffsym);
11401  emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
11402  DONE;
11403})
11404
11405(define_expand "sym2GOTTPOFF"
11406  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
11407  ""
11408  "")
11409
11410(define_insn "tls_initial_exec"
11411  [(set (match_operand:SI 0 "register_operand" "=&r")
11412	(unspec:SI [(match_operand:SI 1 "" "")]
11413		    UNSPEC_TLSIE))
11414   (use (reg:SI GBR_REG))
11415   (use (reg:SI PIC_REG))
11416   (clobber (reg:SI R0_REG))]
11417  ""
11418{
11419  return       "mov.l	1f,r0"		"\n"
11420	 "	stc	gbr,%0"		"\n"
11421	 "	mov.l	@(r0,r12),r0"	"\n"
11422	 "	bra	2f"		"\n"
11423	 "	add	r0,%0"		"\n"
11424	 "	.align	2"		"\n"
11425	 "1:	.long	%a1"		"\n"
11426	 "2:";
11427}
11428  [(set_attr "type" "tls_load")
11429   (set_attr "length" "16")])
11430
11431(define_expand "sym2TPOFF"
11432  [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
11433  ""
11434  "")
11435
11436(define_expand "symTPOFF2reg"
11437  [(match_operand 0 "" "") (match_operand 1 "" "")]
11438  ""
11439{
11440  rtx tpoffsym;
11441
11442  tpoffsym = gen_sym2TPOFF (operands[1]);
11443  PUT_MODE (tpoffsym, Pmode);
11444  emit_move_insn (operands[0], tpoffsym);
11445  DONE;
11446})
11447
11448;;------------------------------------------------------------------------------
11449;; Thread pointer getter and setter.
11450;;
11451;; On SH the thread pointer is kept in the GBR.
11452;; These patterns are usually expanded from the respective built-in functions.
11453(define_expand "get_thread_pointersi"
11454  [(set (match_operand:SI 0 "arith_reg_dest") (reg:SI GBR_REG))]
11455  "TARGET_SH1")
11456
11457;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
11458(define_insn "store_gbr"
11459  [(set (match_operand:SI 0 "arith_reg_dest" "=r") (reg:SI GBR_REG))]
11460  ""
11461  "stc	gbr,%0"
11462  [(set_attr "type" "tls_load")])
11463
11464(define_expand "set_thread_pointersi"
11465  [(set (reg:SI GBR_REG)
11466	(unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand")]
11467	 UNSPECV_GBR))]
11468  "TARGET_SH1")
11469
11470(define_insn "load_gbr"
11471  [(set (reg:SI GBR_REG)
11472	(unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand" "r")]
11473	 UNSPECV_GBR))]
11474  "TARGET_SH1"
11475  "ldc	%0,gbr"
11476  [(set_attr "type" "move")])
11477
11478;;------------------------------------------------------------------------------
11479;; Thread pointer relative memory loads and stores.
11480;;
11481;; On SH there are GBR displacement address modes which can be utilized to
11482;; access memory behind the thread pointer.
11483;; Since we do not allow using GBR for general purpose memory accesses, these
11484;; GBR addressing modes are formed by the combine pass.
11485;; This could be done with fewer patterns than below by using a mem predicate
11486;; for the GBR mem, but then reload would try to reload addresses with a
11487;; zero displacement for some strange reason.
11488
11489(define_insn "*mov<mode>_gbr_load"
11490  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z")
11491	(mem:QIHISI (plus:SI (reg:SI GBR_REG)
11492			     (match_operand:QIHISI 1 "gbr_displacement"))))]
11493  "TARGET_SH1"
11494  "mov.<bwl>	@(%O1,gbr),%0"
11495  [(set_attr "type" "load")])
11496
11497(define_insn "*mov<mode>_gbr_load"
11498  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z")
11499	(mem:QIHISI (reg:SI GBR_REG)))]
11500  "TARGET_SH1"
11501  "mov.<bwl>	@(0,gbr),%0"
11502  [(set_attr "type" "load")])
11503
11504(define_insn "*mov<mode>_gbr_load"
11505  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11506	(sign_extend:SI
11507	  (mem:QIHI (plus:SI (reg:SI GBR_REG)
11508			     (match_operand:QIHI 1 "gbr_displacement")))))]
11509  "TARGET_SH1"
11510  "mov.<bw>	@(%O1,gbr),%0"
11511  [(set_attr "type" "load")])
11512
11513(define_insn "*mov<mode>_gbr_load"
11514  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11515	(sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
11516  "TARGET_SH1"
11517  "mov.<bw>	@(0,gbr),%0"
11518  [(set_attr "type" "load")])
11519
11520(define_insn "*mov<mode>_gbr_store"
11521  [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
11522			     (match_operand:QIHISI 0 "gbr_displacement")))
11523	(match_operand:QIHISI 1 "register_operand" "z"))]
11524  "TARGET_SH1"
11525  "mov.<bwl>	%1,@(%O0,gbr)"
11526  [(set_attr "type" "store")])
11527
11528(define_insn "*mov<mode>_gbr_store"
11529  [(set (mem:QIHISI (reg:SI GBR_REG))
11530	(match_operand:QIHISI 0 "register_operand" "z"))]
11531  "TARGET_SH1"
11532  "mov.<bwl>	%0,@(0,gbr)"
11533  [(set_attr "type" "store")])
11534
11535;; DImode memory accesses have to be split in two SImode accesses.
11536;; Split them before reload, so that it gets a better chance to figure out
11537;; how to deal with the R0 restriction for the individual SImode accesses.
11538;; Do not match this insn during or after reload because it can't be split
11539;; afterwards.
11540(define_insn_and_split "*movdi_gbr_load"
11541  [(set (match_operand:DI 0 "arith_reg_dest")
11542	(match_operand:DI 1 "gbr_address_mem"))]
11543  "TARGET_SH1 && can_create_pseudo_p ()"
11544  "#"
11545  "&& 1"
11546  [(set (match_dup 3) (match_dup 5))
11547   (set (match_dup 4) (match_dup 6))]
11548{
11549  /* Swap low/high part load order on little endian, so that the result reg
11550     of the second load can be used better.  */
11551  int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
11552  operands[3 + off] = gen_lowpart (SImode, operands[0]);
11553  operands[5 + off] = gen_lowpart (SImode, operands[1]);
11554  operands[4 - off] = gen_highpart (SImode, operands[0]);
11555  operands[6 - off] = gen_highpart (SImode, operands[1]);
11556})
11557
11558(define_insn_and_split "*movdi_gbr_store"
11559  [(set (match_operand:DI 0 "gbr_address_mem")
11560	(match_operand:DI 1 "register_operand"))]
11561  "TARGET_SH1 && can_create_pseudo_p ()"
11562  "#"
11563  "&& 1"
11564  [(set (match_dup 3) (match_dup 5))
11565   (set (match_dup 4) (match_dup 6))]
11566{
11567  /* Swap low/high part store order on big endian, so that stores of function
11568     call results can save a reg copy.  */
11569  int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
11570  operands[3 + off] = gen_lowpart (SImode, operands[0]);
11571  operands[5 + off] = gen_lowpart (SImode, operands[1]);
11572  operands[4 - off] = gen_highpart (SImode, operands[0]);
11573  operands[6 - off] = gen_highpart (SImode, operands[1]);
11574})
11575
11576;; Sometimes memory accesses do not get combined with the store_gbr insn,
11577;; in particular when the displacements are in the range of the regular move
11578;; insns.  Thus, in the first split pass after the combine pass we search
11579;; for missed opportunities and try to fix them up ourselves.
11580;; If an equivalent GBR address can be determined the load / store is split
11581;; into one of the GBR load / store patterns.
11582;; All of that must happen before reload (GBR address modes use R0 as the
11583;; other operand) and there's no point of doing it if the GBR is not
11584;; referenced in a function at all.
11585(define_split
11586  [(set (match_operand:QIHISIDI 0 "register_operand")
11587	(match_operand:QIHISIDI 1 "memory_operand"))]
11588  "TARGET_SH1 && !reload_in_progress && !reload_completed
11589   && df_regs_ever_live_p (GBR_REG)"
11590  [(set (match_dup 0) (match_dup 1))]
11591{
11592  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
11593  if (gbr_mem != NULL_RTX)
11594    operands[1] = replace_equiv_address (operands[1], gbr_mem);
11595  else
11596    FAIL;
11597})
11598
11599(define_split
11600  [(set (match_operand:SI 0 "register_operand")
11601	(sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
11602  "TARGET_SH1 && !reload_in_progress && !reload_completed
11603   && df_regs_ever_live_p (GBR_REG)"
11604  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
11605{
11606  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
11607  if (gbr_mem != NULL_RTX)
11608    operands[1] = replace_equiv_address (operands[1], gbr_mem);
11609  else
11610    FAIL;
11611})
11612
11613;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
11614;; Split those so that a GBR load can be used.
11615(define_split
11616  [(set (match_operand:SI 0 "register_operand")
11617	(zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
11618  "TARGET_SH2A && !reload_in_progress && !reload_completed
11619   && df_regs_ever_live_p (GBR_REG)"
11620  [(set (match_dup 2) (match_dup 1))
11621   (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
11622{
11623  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
11624  if (gbr_mem != NULL_RTX)
11625    {
11626      operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
11627      operands[1] = replace_equiv_address (operands[1], gbr_mem);
11628    }
11629  else
11630    FAIL;
11631})
11632
11633(define_split
11634  [(set (match_operand:QIHISIDI 0 "memory_operand")
11635	(match_operand:QIHISIDI 1 "register_operand"))]
11636  "TARGET_SH1 && !reload_in_progress && !reload_completed
11637   && df_regs_ever_live_p (GBR_REG)"
11638  [(set (match_dup 0) (match_dup 1))]
11639{
11640  rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
11641  if (gbr_mem != NULL_RTX)
11642    operands[0] = replace_equiv_address (operands[0], gbr_mem);
11643  else
11644    FAIL;
11645})
11646
11647;;------------------------------------------------------------------------------
11648;; case instruction for switch statements.
11649
11650;; operand 0 is index
11651;; operand 1 is the minimum bound
11652;; operand 2 is the maximum bound - minimum bound + 1
11653;; operand 3 is CODE_LABEL for the table;
11654;; operand 4 is the CODE_LABEL to go to if index out of range.
11655(define_expand "casesi"
11656  [(match_operand:SI 0 "arith_reg_operand" "")
11657   (match_operand:SI 1 "arith_reg_operand" "")
11658   (match_operand:SI 2 "arith_reg_operand" "")
11659   (match_operand 3 "" "") (match_operand 4 "" "")]
11660  ""
11661{
11662  rtx reg = gen_reg_rtx (SImode);
11663  rtx reg2 = gen_reg_rtx (SImode);
11664  if (TARGET_SHMEDIA)
11665    {
11666      rtx reg = gen_reg_rtx (DImode);
11667      rtx reg2 = gen_reg_rtx (DImode);
11668      rtx reg3 = gen_reg_rtx (Pmode);
11669      rtx reg4 = gen_reg_rtx (Pmode);
11670      rtx reg5 = gen_reg_rtx (Pmode);
11671      rtx load, test;
11672
11673      operands[0] = convert_modes (DImode, SImode, operands[0], 0);
11674      operands[1] = convert_modes (DImode, SImode, operands[1], 0);
11675      operands[2] = convert_modes (DImode, SImode, operands[2], 1);
11676
11677      test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
11678      emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0],
11679				      operands[4]));
11680      emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
11681      test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
11682      emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
11683      emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
11684      emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
11685					       (Pmode, operands[3])));
11686      /* Messy: can we subreg to clean this up? */
11687      if (Pmode == DImode)
11688	load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
11689      else
11690	load = gen_casesi_load_media (reg4,
11691				      gen_rtx_SUBREG (DImode, reg3, 0),
11692				      reg2, operands[3]);
11693      PUT_MODE (SET_SRC (load), Pmode);
11694      emit_insn (load);
11695      /* ??? The following add could be eliminated if we used ptrel.  */
11696      emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
11697      emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
11698      emit_barrier ();
11699      DONE;
11700    }
11701  operands[1] = copy_to_mode_reg (SImode, operands[1]);
11702  operands[2] = copy_to_mode_reg (SImode, operands[2]);
11703  /* If optimizing, casesi_worker depends on the mode of the instruction
11704     before label it 'uses' - operands[3].  */
11705  emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
11706			   reg));
11707  emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
11708  if (TARGET_SH2)
11709    emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
11710  else
11711    emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
11712  /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
11713     operands[3], but to lab.  We will fix this up in
11714     machine_dependent_reorg.  */
11715  emit_barrier ();
11716  DONE;
11717})
11718
11719(define_expand "casesi_0"
11720  [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
11721   (set (match_dup 4) (minus:SI (match_dup 4)
11722				(match_operand:SI 1 "arith_operand" "")))
11723   (set (reg:SI T_REG)
11724	(gtu:SI (match_dup 4)
11725		(match_operand:SI 2 "arith_reg_operand" "")))
11726   (set (pc)
11727	(if_then_else (ne (reg:SI T_REG)
11728			  (const_int 0))
11729		      (label_ref (match_operand 3 "" ""))
11730		      (pc)))]
11731  "TARGET_SH1"
11732  "")
11733
11734;; ??? reload might clobber r0 if we use it explicitly in the RTL before
11735;; reload; using a R0_REGS pseudo reg is likely to give poor code.
11736;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
11737;;
11738;; The use on the T_REG in the casesi_worker* patterns links the bounds
11739;; checking insns and the table memory access.  See also PR 69713.
11740(define_insn "casesi_worker_0"
11741  [(set (match_operand:SI 0 "register_operand" "=r,r")
11742	(unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
11743		 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11744   (clobber (match_scratch:SI 3 "=X,1"))
11745   (clobber (match_scratch:SI 4 "=&z,z"))
11746   (use (reg:SI T_REG))]
11747  "TARGET_SH1"
11748  "#")
11749
11750(define_split
11751  [(set (match_operand:SI 0 "register_operand" "")
11752	(unspec:SI [(match_operand:SI 1 "register_operand" "")
11753		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11754   (clobber (match_scratch:SI 3 ""))
11755   (clobber (match_scratch:SI 4))
11756   (use (reg:SI T_REG))]
11757  "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
11758  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
11759   (parallel [(set (match_dup 0)
11760	      (unspec:SI [(reg:SI R0_REG) (match_dup 1)
11761			  (label_ref (match_dup 2))] UNSPEC_CASESI))
11762	      (clobber (match_dup 3))])
11763   (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
11764{
11765  if (GET_CODE (operands[2]) == CODE_LABEL)
11766    LABEL_NUSES (operands[2])++;
11767})
11768
11769(define_split
11770  [(set (match_operand:SI 0 "register_operand" "")
11771	(unspec:SI [(match_operand:SI 1 "register_operand" "")
11772		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11773   (clobber (match_scratch:SI 3 ""))
11774   (clobber (match_scratch:SI 4))
11775   (use (reg:SI T_REG))]
11776  "TARGET_SH2 && reload_completed"
11777  [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
11778   (parallel [(set (match_dup 0)
11779	      (unspec:SI [(reg:SI R0_REG) (match_dup 1)
11780			  (label_ref (match_dup 2))] UNSPEC_CASESI))
11781	      (clobber (match_dup 3))])]
11782{
11783  if (GET_CODE (operands[2]) == CODE_LABEL)
11784    LABEL_NUSES (operands[2])++;
11785})
11786
11787;; This may be replaced with casesi_worker_2 in sh_reorg for PIC.
11788;; The insn length is set to 8 for that case.
11789(define_insn "casesi_worker_1"
11790  [(set (match_operand:SI 0 "register_operand" "=r,r")
11791	(unspec:SI [(reg:SI R0_REG)
11792		    (match_operand:SI 1 "register_operand" "0,r")
11793		    (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11794   (clobber (match_scratch:SI 3 "=X,1"))]
11795  "TARGET_SH1"
11796{
11797  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
11798
11799  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11800
11801  switch (GET_MODE (diff_vec))
11802    {
11803    case SImode:
11804      return   "shll2	%1"	"\n"
11805	     "	mov.l	@(r0,%1),%0";
11806    case HImode:
11807      return   "add	%1,%1"	"\n"
11808	     "	mov.w	@(r0,%1),%0";
11809    case QImode:
11810      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11811	return         "mov.b	@(r0,%1),%0"	"\n"
11812	       "	extu.b	%0,%0";
11813      else
11814	return "mov.b	@(r0,%1),%0";
11815
11816    default:
11817      gcc_unreachable ();
11818    }
11819}
11820  [(set_attr_alternative "length"
11821     [(if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))
11822      (if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))])])
11823
11824(define_insn "casesi_worker_2"
11825  [(set (match_operand:SI 0 "register_operand" "=r,r")
11826	(unspec:SI [(reg:SI R0_REG)
11827		    (match_operand:SI 1 "register_operand" "0,r")
11828		    (label_ref (match_operand 2 "" ""))
11829		    (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
11830   (clobber (match_operand:SI 4 "" "=X,1"))]
11831  "TARGET_SH2 && reload_completed && flag_pic"
11832{
11833  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
11834  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11835
11836  switch (GET_MODE (diff_vec))
11837    {
11838    case SImode:
11839      return   "shll2	%1"		"\n"
11840	     "	add	r0,%1"		"\n"
11841	     "	mova	%O3,r0"		"\n"
11842	     "  mov.l	@(r0,%1),%0";
11843    case HImode:
11844      return   "add	%1,%1"		"\n"
11845	     "	add	r0,%1"		"\n"
11846	     "	mova	%O3,r0"		"\n"
11847	     "	mov.w	@(r0,%1),%0";
11848    case QImode:
11849      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11850	return	       "add	r0,%1"		"\n"
11851		"	mova	%O3,r0"		"\n"
11852		"	mov.b	@(r0,%1),%0"	"\n"
11853		"	extu.b	%0,%0";
11854      else
11855	return	       "add	r0,%1"		"\n"
11856		"	mova	%O3,r0"		"\n"
11857		"	mov.b	@(r0,%1),%0";
11858    default:
11859      gcc_unreachable ();
11860    }
11861}
11862  [(set_attr "length" "8")])
11863
11864(define_insn "casesi_shift_media"
11865  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11866	(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
11867		   (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
11868		    UNSPEC_CASESI)))]
11869  "TARGET_SHMEDIA"
11870{
11871  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
11872
11873  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11874
11875  switch (GET_MODE (diff_vec))
11876    {
11877    case SImode:
11878      return "shlli	%1, 2, %0";
11879    case HImode:
11880      return "shlli	%1, 1, %0";
11881    case QImode:
11882      if (rtx_equal_p (operands[0], operands[1]))
11883	return "";
11884      return "add	%1, r63, %0";
11885    default:
11886      gcc_unreachable ();
11887    }
11888}
11889  [(set_attr "type" "arith_media")])
11890
11891(define_insn "casesi_load_media"
11892  [(set (match_operand 0 "any_arith_reg_dest" "=r")
11893	(mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
11894		      (match_operand:DI 2 "arith_reg_operand" "r")
11895		      (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
11896  "TARGET_SHMEDIA"
11897{
11898  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[3])));
11899
11900  gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11901
11902  switch (GET_MODE (diff_vec))
11903    {
11904    case SImode:
11905      return "ldx.l	%1, %2, %0";
11906    case HImode:
11907#if 0
11908      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11909	return "ldx.uw	%1, %2, %0";
11910#endif
11911      return "ldx.w	%1, %2, %0";
11912    case QImode:
11913      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11914	return "ldx.ub	%1, %2, %0";
11915      return "ldx.b	%1, %2, %0";
11916    default:
11917      gcc_unreachable ();
11918    }
11919}
11920  [(set_attr "type" "load_media")])
11921
11922(define_expand "simple_return"
11923  [(simple_return)]
11924 "sh_can_use_simple_return_p ()")
11925
11926(define_expand "return"
11927  [(return)]
11928 "reload_completed && epilogue_completed"
11929{
11930  if (TARGET_SHMEDIA)
11931    {
11932      emit_jump_insn (gen_return_media ());
11933      DONE;
11934    }
11935
11936  if (TARGET_SHCOMPACT
11937      && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
11938    {
11939      emit_jump_insn (gen_shcompact_return_tramp ());
11940      DONE;
11941    }
11942})
11943
11944(define_insn "*<code>_i"
11945  [(any_return)]
11946  "TARGET_SH1 && ! (TARGET_SHCOMPACT
11947		    && (crtl->args.info.call_cookie
11948			& CALL_COOKIE_RET_TRAMP (1)))
11949   && reload_completed
11950   && ! sh_cfun_trap_exit_p ()"
11951{
11952  if (TARGET_SH2A && (dbr_sequence_length () == 0)
11953      && !current_function_interrupt)
11954    return "rts/n";
11955  else
11956    return "%@	%#";
11957}
11958  [(set_attr "type" "return")
11959   (set_attr "needs_delay_slot" "yes")])
11960
11961;; trapa has no delay slot.
11962(define_insn "*return_trapa"
11963  [(return)]
11964  "TARGET_SH1 && !TARGET_SHCOMPACT
11965   && reload_completed"
11966  "%@"
11967  [(set_attr "type" "return")])
11968
11969(define_expand "shcompact_return_tramp"
11970  [(return)]
11971  "TARGET_SHCOMPACT
11972   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11973{
11974  rtx reg = gen_rtx_REG (Pmode, R0_REG);
11975
11976  function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
11977  emit_jump_insn (gen_shcompact_return_tramp_i ());
11978  DONE;
11979})
11980
11981(define_insn "shcompact_return_tramp_i"
11982  [(parallel [(return) (use (reg:SI R0_REG))])]
11983  "TARGET_SHCOMPACT
11984   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11985  "jmp	@r0%#"
11986  [(set_attr "type" "jump_ind")
11987   (set_attr "needs_delay_slot" "yes")])
11988
11989(define_insn "return_media_i"
11990  [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
11991  "TARGET_SHMEDIA && reload_completed"
11992  "blink	%0, r63"
11993  [(set_attr "type" "jump_media")])
11994
11995(define_insn "return_media_rte"
11996  [(return)]
11997  "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
11998  "rte"
11999  [(set_attr "type" "jump_media")])
12000
12001(define_expand "return_media"
12002  [(return)]
12003  "TARGET_SHMEDIA && reload_completed"
12004{
12005  int tr_regno = sh_media_register_for_return ();
12006  rtx tr;
12007
12008  if (current_function_interrupt)
12009    {
12010      emit_jump_insn (gen_return_media_rte ());
12011      DONE;
12012    }
12013  if (tr_regno < 0)
12014    {
12015      rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
12016
12017      gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
12018      tr_regno = TR0_REG;
12019      tr = gen_rtx_REG (Pmode, tr_regno);
12020      emit_move_insn (tr, r18);
12021    }
12022  else
12023    tr = gen_rtx_REG (Pmode, tr_regno);
12024
12025  emit_jump_insn (gen_return_media_i (tr));
12026  DONE;
12027})
12028
12029(define_insn "shcompact_preserve_incoming_args"
12030  [(set (match_operand:SI 0 "register_operand" "+r")
12031	(unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
12032  "TARGET_SHCOMPACT"
12033  ""
12034  [(set_attr "length" "0")])
12035
12036(define_insn "shcompact_incoming_args"
12037  [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
12038   (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
12039   (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
12040   (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
12041   (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
12042   (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
12043   (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
12044   (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
12045   (set (mem:BLK (reg:SI MACL_REG))
12046	(unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
12047   (use (reg:SI R0_REG))
12048   (clobber (reg:SI R0_REG))
12049   (clobber (reg:SI MACL_REG))
12050   (clobber (reg:SI MACH_REG))
12051   (clobber (reg:SI PR_REG))]
12052  "TARGET_SHCOMPACT"
12053  "jsr	@r0%#"
12054  [(set_attr "needs_delay_slot" "yes")])
12055
12056(define_insn "shmedia_save_restore_regs_compact"
12057  [(set (reg:SI SP_REG)
12058	(plus:SI (reg:SI SP_REG)
12059		 (match_operand:SI 0 "immediate_operand" "i")))
12060   (use (reg:SI R0_REG))
12061   (clobber (reg:SI PR_REG))]
12062  "TARGET_SHCOMPACT
12063   && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
12064       || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
12065  "jsr @r0%#"
12066  [(set_attr "needs_delay_slot" "yes")])
12067
12068(define_expand "prologue"
12069  [(const_int 0)]
12070  ""
12071{
12072  sh_expand_prologue ();
12073  DONE;
12074})
12075
12076(define_expand "epilogue"
12077  [(return)]
12078  ""
12079{
12080  sh_expand_epilogue (false);
12081  if (TARGET_SHMEDIA
12082      || (TARGET_SHCOMPACT
12083	  && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
12084    {
12085      emit_jump_insn (gen_return ());
12086      DONE;
12087    }
12088})
12089
12090(define_expand "eh_return"
12091  [(use (match_operand 0 "register_operand" ""))]
12092  ""
12093{
12094  rtx ra = operands[0];
12095
12096  if (TARGET_SHMEDIA64)
12097    emit_insn (gen_eh_set_ra_di (ra));
12098  else
12099    emit_insn (gen_eh_set_ra_si (ra));
12100
12101  DONE;
12102})
12103
12104;; Clobber the return address on the stack.  We can't expand this
12105;; until we know where it will be put in the stack frame.
12106
12107(define_insn "eh_set_ra_si"
12108  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
12109      UNSPECV_EH_RETURN)
12110   (clobber (match_scratch:SI 1 "=&r"))]
12111  "! TARGET_SHMEDIA64"
12112  "#")
12113
12114(define_insn "eh_set_ra_di"
12115  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
12116      UNSPECV_EH_RETURN)
12117   (clobber (match_scratch:DI 1 "=&r"))]
12118  "TARGET_SHMEDIA64"
12119  "#")
12120
12121(define_split
12122  [(unspec_volatile [(match_operand 0 "register_operand" "")]
12123      UNSPECV_EH_RETURN)
12124   (clobber (match_scratch 1 ""))]
12125  "reload_completed"
12126  [(const_int 0)]
12127{
12128  sh_set_return_address (operands[0], operands[1]);
12129  DONE;
12130})
12131
12132(define_insn "blockage"
12133  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
12134  ""
12135  ""
12136  [(set_attr "length" "0")])
12137
12138;; Define movml instructions for SH2A target.  Currently they are
12139;; used to push and pop all banked registers only.
12140
12141(define_insn "movml_push_banked"
12142  [(set (match_operand:SI 0 "register_operand" "=r")
12143	  (plus (match_dup 0) (const_int -32)))
12144   (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
12145   (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
12146   (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
12147   (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
12148   (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
12149   (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
12150   (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
12151   (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
12152  "TARGET_SH2A && REGNO (operands[0]) == 15"
12153  "movml.l	r7,@-r15"
12154  [(set_attr "in_delay_slot" "no")])
12155
12156(define_insn "movml_pop_banked"
12157  [(set (match_operand:SI 0 "register_operand" "=r")
12158	  (plus (match_dup 0) (const_int 32)))
12159   (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
12160   (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
12161   (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
12162   (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
12163   (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
12164   (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
12165   (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
12166   (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
12167  "TARGET_SH2A && REGNO (operands[0]) == 15"
12168  "movml.l	@r15+,r7"
12169  [(set_attr "in_delay_slot" "no")])
12170
12171;; ------------------------------------------------------------------------
12172;; Scc instructions
12173;; ------------------------------------------------------------------------
12174
12175(define_insn "movt"
12176  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12177	(match_operand:SI 1 "t_reg_operand"))]
12178  "TARGET_SH1"
12179  "movt	%0"
12180  [(set_attr "type" "arith")])
12181
12182(define_insn "movrt"
12183  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12184	(xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
12185  "TARGET_SH2A"
12186  "movrt	%0"
12187  [(set_attr "type" "arith")])
12188
12189(define_expand "cstore4_media"
12190  [(set (match_operand:SI 0 "register_operand" "=r")
12191	(match_operator:SI 1 "sh_float_comparison_operator"
12192	 [(match_operand 2 "logical_operand" "")
12193	  (match_operand 3 "cmp_operand" "")]))]
12194  "TARGET_SHMEDIA"
12195{
12196  machine_mode mode = GET_MODE (operands[2]);
12197  enum rtx_code code = GET_CODE (operands[1]);
12198  bool invert, swap;
12199  if (mode == VOIDmode)
12200    mode = GET_MODE (operands[3]);
12201  if (operands[2] == const0_rtx)
12202    {
12203      if (code == EQ || code == NE)
12204	operands[2] = operands[3], operands[3] = const0_rtx;
12205    }
12206  else
12207    operands[2] = force_reg (mode, operands[2]);
12208  if (operands[3] != const0_rtx)
12209    operands[3] = force_reg (mode, operands[3]);
12210
12211  switch (code)
12212    {
12213    case GEU:
12214    case GE:
12215      swap = invert = !FLOAT_MODE_P (mode);
12216      break;
12217
12218    case LEU:
12219    case LE:
12220      swap = FLOAT_MODE_P (mode), invert = !swap;
12221      break;
12222
12223    case LTU:
12224    case LT:
12225      swap = true, invert = false;
12226      break;
12227
12228    case GTU:
12229    case GT:
12230    case EQ:
12231    case UNORDERED:
12232      swap = invert = false;
12233      break;
12234
12235    case NE:
12236      swap = invert = true;
12237      break;
12238
12239    default:
12240      gcc_unreachable ();
12241  }
12242
12243  if (swap)
12244    {
12245      std::swap (operands[2], operands[3]);
12246      code = swap_condition (code);
12247    }
12248
12249  if (invert)
12250    {
12251      rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
12252      code = reverse_condition (code);
12253      operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
12254      emit_insn (gen_cstore4_media (tem, operands[1],
12255				    operands[2], operands[3]));
12256      code = EQ;
12257      operands[2] = tem;
12258      operands[3] = const0_rtx;
12259    }
12260
12261  operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
12262})
12263
12264(define_expand "cstoresi4"
12265  [(set (match_operand:SI 0 "register_operand" "=r")
12266	(match_operator:SI 1 "comparison_operator"
12267	 [(match_operand:SI 2 "cmpsi_operand" "")
12268	  (match_operand:SI 3 "arith_operand" "")]))]
12269  "TARGET_SH1 || TARGET_SHMEDIA"
12270{
12271  if (TARGET_SHMEDIA)
12272    {
12273      emit_insn (gen_cstore4_media (operands[0], operands[1],
12274				    operands[2], operands[3]));
12275      DONE;
12276    }
12277
12278   if (sh_expand_t_scc (operands))
12279     DONE;
12280
12281   if (! currently_expanding_to_rtl)
12282     FAIL;
12283   
12284   sh_emit_compare_and_set (operands, SImode);
12285   DONE;
12286})
12287
12288(define_expand "cstoredi4"
12289  [(set (match_operand:SI 0 "register_operand" "=r")
12290	(match_operator:SI 1 "comparison_operator"
12291	 [(match_operand:DI 2 "arith_operand" "")
12292	  (match_operand:DI 3 "arith_operand" "")]))]
12293  "TARGET_SH2 || TARGET_SHMEDIA"
12294{
12295  if (TARGET_SHMEDIA)
12296    {
12297      emit_insn (gen_cstore4_media (operands[0], operands[1],
12298				    operands[2], operands[3]));
12299      DONE;
12300    }
12301
12302   if (sh_expand_t_scc (operands))
12303     DONE;
12304
12305   if (! currently_expanding_to_rtl)
12306     FAIL;
12307   
12308   sh_emit_compare_and_set (operands, DImode);
12309   DONE;
12310})
12311
12312;; Move the complement of the T reg to a reg.
12313;; On SH2A the movrt insn can be used.
12314;; On anything else than SH2A this has to be done with multiple instructions.
12315;; One obvious way would be:
12316;;	cmp/eq	...
12317;;	movt	r0
12318;;	xor	#1,r0
12319;;
12320;; However, this puts pressure on r0 in most cases and thus the following is
12321;; more appealing:
12322;;	cmp/eq	...
12323;;	mov	#-1,temp
12324;;	negc	temp,dest
12325;;
12326;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
12327;; becomes a one instruction operation.  Moreover, care must be taken that
12328;; the insn can still be combined with inverted compare and branch code
12329;; around it.  On the other hand, if a function returns the complement of
12330;; a previous comparison result in the T bit, the xor #1,r0 approach might
12331;; lead to better code.
12332(define_expand "movnegt"
12333  [(set (match_operand:SI 0 "arith_reg_dest" "")
12334	(xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
12335  "TARGET_SH1"
12336{
12337  if (TARGET_SH2A)
12338    emit_insn (gen_movrt (operands[0], operands[1]));
12339  else
12340    {
12341      rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
12342      emit_insn (gen_movrt_negc (operands[0], operands[1], val));
12343    }
12344  DONE;
12345})
12346
12347(define_insn_and_split "movrt_negc"
12348  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12349	(xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
12350   (set (reg:SI T_REG) (const_int 1))
12351   (use (match_operand:SI 2 "arith_reg_operand" "r"))]
12352  "TARGET_SH1"
12353  "negc	%2,%0"
12354  "&& !sh_in_recog_treg_set_expr ()"
12355  [(const_int 0)]
12356{
12357  if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands))
12358    DONE;
12359  else
12360    FAIL;
12361}
12362  [(set_attr "type" "arith")])
12363
12364;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
12365;; pattern can be used by the combine pass.  Using a scratch reg for the
12366;; -1 constant results in slightly better register allocations compared to
12367;; generating a pseudo reg before reload.
12368(define_insn_and_split "*movrt_negc"
12369  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12370	(xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
12371   (clobber (match_scratch:SI 2 "=r"))
12372   (clobber (reg:SI T_REG))]
12373  "TARGET_SH1 && ! TARGET_SH2A"
12374  "#"
12375  "&& !sh_in_recog_treg_set_expr ()"
12376  [(const_int 0)]
12377{
12378  if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands))
12379    DONE;
12380  else if (reload_completed)
12381    {
12382      emit_move_insn (operands[2], gen_int_mode (-1, SImode));
12383      emit_insn (gen_movrt_negc (operands[0], operands[1], operands[2]));
12384      DONE;
12385    }
12386  else
12387    FAIL;
12388})
12389
12390;; Store the negated T bit in a reg using r0 and xor.  This one doesn't
12391;; clobber the T bit, which is useful when storing the T bit and the
12392;; negated T bit in parallel.  On SH2A the movrt insn can be used for that.
12393;; Usually we don't want this insn to be matched, except for cases where the
12394;; T bit clobber is really not appreciated.  Hence the extra use on T_REG.
12395(define_insn_and_split "movrt_xor"
12396  [(set (match_operand:SI 0 "arith_reg_dest" "=z")
12397	(xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
12398   (use (reg:SI T_REG))]
12399  "TARGET_SH1"
12400  "#"
12401  "&& reload_completed"
12402  [(set (match_dup 0) (reg:SI T_REG))
12403   (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
12404
12405;; 0x7fffffff + T
12406;; 0x7fffffff + (1-T) = 0 - 0x80000000 - T
12407;;
12408;; Notice that 0 - 0x80000000 = 0x80000000.
12409
12410;; Single bit tests are usually done with zero_extract.  On non-SH2A this
12411;; will use a tst-negc sequence.  On SH2A it will use a bld-addc sequence.
12412;; The zeroth bit requires a special pattern, otherwise we get a shlr-addc.
12413;; This is a special case of the generic treg_set_expr pattern and thus has
12414;; to come first or it will never match.
12415(define_insn_and_split "*mov_t_msb_neg"
12416  [(set (match_operand:SI 0 "arith_reg_dest")
12417	(plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
12418			 (const_int 1))
12419		 (const_int 2147483647)))
12420   (clobber (reg:SI T_REG))]
12421  "TARGET_SH1"
12422  "#"
12423  "&& can_create_pseudo_p ()"
12424  [(parallel [(set (match_dup 0)
12425		   (plus:SI (zero_extract:SI (match_dup 1)
12426					     (const_int 1) (const_int 0))
12427			    (const_int 2147483647)))
12428	      (clobber (reg:SI T_REG))])])
12429
12430(define_insn_and_split "*mov_t_msb_neg"
12431  [(set (match_operand:SI 0 "arith_reg_dest")
12432	(plus:SI (match_operand 1 "treg_set_expr")
12433		 (const_int 2147483647)))  ;; 0x7fffffff
12434   (clobber (reg:SI T_REG))]
12435  "TARGET_SH1"
12436   "#"
12437   "&& can_create_pseudo_p ()"
12438  [(const_int 0)]
12439{
12440  if (negt_reg_operand (operands[1], VOIDmode))
12441    {
12442      emit_insn (gen_negc (operands[0],
12443			   force_reg (SImode, GEN_INT (-2147483648LL))));
12444      DONE;
12445    }
12446
12447  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12448  if (ti.remove_trailing_nott ())
12449    emit_insn (gen_negc (operands[0],
12450			 force_reg (SImode, GEN_INT (-2147483648LL))));
12451  else
12452    emit_insn (gen_addc (operands[0],
12453			 force_reg (SImode, const0_rtx),
12454			 force_reg (SImode, GEN_INT (2147483647))));
12455  DONE;
12456})
12457
12458(define_insn_and_split "*mov_t_msb_neg"
12459  [(set (match_operand:SI 0 "arith_reg_dest")
12460	(if_then_else:SI (match_operand 1 "treg_set_expr")
12461			 (match_operand 2 "const_int_operand")
12462			 (match_operand 3 "const_int_operand")))
12463   (clobber (reg:SI T_REG))]
12464  "TARGET_SH1 && can_create_pseudo_p ()
12465   && ((INTVAL (operands[2]) == -2147483648LL
12466	&& INTVAL (operands[3]) == 2147483647LL)
12467       || (INTVAL (operands[2]) == 2147483647LL
12468	   && INTVAL (operands[3]) == -2147483648LL))"
12469  "#"
12470  "&& 1"
12471  [(const_int 0)]
12472{
12473  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12474
12475  if (INTVAL (operands[2]) == -2147483648LL)
12476    {
12477      if (ti.remove_trailing_nott ())
12478	emit_insn (gen_negc (operands[0],
12479			     force_reg (SImode, GEN_INT (-2147483648LL))));
12480      else
12481	emit_insn (gen_addc (operands[0],
12482			     force_reg (SImode, const0_rtx),
12483			     force_reg (SImode, operands[3])));
12484      DONE;
12485    }
12486  else if (INTVAL (operands[2]) == 2147483647LL)
12487    {
12488      if (ti.remove_trailing_nott ())
12489	emit_insn (gen_addc (operands[0],
12490			     force_reg (SImode, const0_rtx),
12491			     force_reg (SImode, GEN_INT (2147483647LL))));
12492      else
12493	emit_insn (gen_negc (operands[0],
12494			     force_reg (SImode, GEN_INT (-2147483648LL))));
12495      DONE;
12496    }
12497  else
12498    gcc_unreachable ();
12499})
12500
12501;; The *negnegt pattern helps the combine pass to figure out how to fold 
12502;; an explicit double T bit negation.
12503(define_insn_and_split "*negnegt"
12504  [(set (reg:SI T_REG)
12505	(eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
12506  "TARGET_SH1"
12507  "#"
12508  ""
12509  [(const_int 0)])
12510
12511;; Store (negated) T bit as all zeros or ones in a reg.
12512;;	subc	Rn,Rn	! Rn = Rn - Rn - T; T = T
12513;;	not	Rn,Rn	! Rn = 0 - Rn
12514(define_insn_and_split "mov_neg_si_t"
12515  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12516	(neg:SI (match_operand 1 "treg_set_expr")))]
12517  "TARGET_SH1"
12518{
12519  gcc_assert (t_reg_operand (operands[1], VOIDmode));
12520  return "subc	%0,%0";
12521}
12522  "&& can_create_pseudo_p () && !t_reg_operand (operands[1], VOIDmode)"
12523  [(const_int 0)]
12524{
12525  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12526  emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
12527
12528  if (ti.remove_trailing_nott ())
12529    emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
12530
12531  DONE;
12532}
12533  [(set_attr "type" "arith")])
12534
12535;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
12536(define_insn_and_split "*movtt"
12537  [(set (reg:SI T_REG)
12538	(eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
12539  "TARGET_SH1"
12540  "#"
12541  ""
12542  [(const_int 0)])
12543
12544;; Invert the T bit.
12545;; On SH2A we can use the nott insn.  On anything else this must be done with
12546;; multiple insns like:
12547;;	movt	Rn
12548;;	tst	Rn,Rn
12549;; This requires an additional pseudo.  The SH specific sh_treg_combine RTL
12550;; pass will look for this insn.  Disallow using it if pseudos can't be
12551;; created.
12552;; Don't split the nott inside the splitting of a treg_set_expr, or else
12553;; surrounding insns might not see and recombine it.  Defer the splitting
12554;; of the nott until after the whole insn containing the treg_set_expr
12555;; has been split.
12556(define_insn_and_split "nott"
12557  [(set (reg:SI T_REG)
12558	(xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))]
12559  "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())"
12560{
12561  gcc_assert (TARGET_SH2A);
12562  return "nott";
12563}
12564  "!TARGET_SH2A && can_create_pseudo_p () && !sh_in_recog_treg_set_expr ()"
12565  [(set (match_dup 0) (reg:SI T_REG))
12566   (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
12567{
12568  operands[0] = gen_reg_rtx (SImode);
12569})
12570
12571;; Store T bit as MSB in a reg.
12572;; T = 0: 0x00000000 -> reg
12573;; T = 1: 0x80000000 -> reg
12574(define_insn_and_split "*movt_msb"
12575  [(set (match_operand:SI 0 "arith_reg_dest")
12576	(mult:SI (match_operand:SI 1 "t_reg_operand")
12577		 (const_int -2147483648)))  ;; 0xffffffff80000000
12578   (clobber (reg:SI T_REG))]
12579  "TARGET_SH1"
12580  "#"
12581  "&& 1"
12582  [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
12583
12584;; Store inverted T bit as MSB in a reg.
12585;; T = 0: 0x80000000 -> reg
12586;; T = 1: 0x00000000 -> reg
12587;; On SH2A we can get away without clobbering the T_REG using the movrt insn.
12588;; On non SH2A we resort to the following sequence:
12589;;	movt	Rn
12590;;	tst	Rn,Rn
12591;;	rotcr	Rn
12592;; The T bit value will be modified during the sequence, but the rotcr insn
12593;; will restore its original value.
12594(define_insn_and_split "*negt_msb"
12595  [(set (match_operand:SI 0 "arith_reg_dest")
12596	(match_operand:SI 1 "negt_reg_shl31_operand"))]
12597  "TARGET_SH1"
12598  "#"
12599  "&& can_create_pseudo_p ()"
12600  [(const_int 0)]
12601{
12602  rtx tmp = gen_reg_rtx (SImode);
12603
12604  if (TARGET_SH2A)
12605    {
12606      emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
12607      emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
12608    }
12609  else
12610    {
12611      emit_move_insn (tmp, get_t_reg_rtx ());
12612      emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
12613      emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
12614    }
12615  DONE;
12616})
12617
12618;; The *cset_zero patterns convert optimizations such as
12619;;	"if (test) x = 0;"
12620;; to
12621;;	"x &= -(test == 0);"
12622;; back to conditional branch sequences if zero-displacement branches
12623;; are enabled.
12624;; FIXME: These patterns can be removed when conditional execution patterns
12625;; are implemented, since ifcvt will not perform these optimizations if
12626;; conditional execution is supported.
12627(define_insn "*cset_zero"
12628  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12629	(and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
12630			 (const_int -1))
12631		(match_operand:SI 2 "arith_reg_operand" "0")))]
12632  "TARGET_SH1 && TARGET_ZDCBRANCH"
12633{
12634  return       "bf	0f"	"\n"
12635	 "	mov	#0,%0"	"\n"
12636	 "0:";
12637}
12638  [(set_attr "type" "arith") ;; poor approximation
12639   (set_attr "length" "4")])
12640
12641(define_insn "*cset_zero"
12642  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12643	(if_then_else:SI (match_operand:SI 1 "cbranch_treg_value")
12644			 (match_operand:SI 2 "arith_reg_operand" "0")
12645			 (const_int 0)))]
12646  "TARGET_SH1 && TARGET_ZDCBRANCH"
12647{
12648  int tval = sh_eval_treg_value (operands[1]);
12649  if (tval == true)
12650    return     "bt	0f"	"\n"
12651	   "	mov	#0,%0"	"\n"
12652	   "0:";
12653  else if (tval == false)
12654    return     "bf	0f"	"\n"
12655	   "	mov	#0,%0"	"\n"
12656	   "0:";
12657  else
12658    gcc_unreachable ();
12659}
12660  [(set_attr "type" "arith") ;; poor approximation
12661   (set_attr "length" "4")])
12662
12663(define_expand "cstoresf4"
12664  [(set (match_operand:SI 0 "register_operand" "=r")
12665	(match_operator:SI 1 "sh_float_comparison_operator"
12666	 [(match_operand:SF 2 "arith_operand" "")
12667	  (match_operand:SF 3 "arith_operand" "")]))]
12668  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12669{
12670  if (TARGET_SHMEDIA)
12671    {
12672      emit_insn (gen_cstore4_media (operands[0], operands[1],
12673				    operands[2], operands[3]));
12674      DONE;
12675    }
12676
12677  if (! currently_expanding_to_rtl)
12678    FAIL;
12679   
12680  sh_emit_compare_and_set (operands, SFmode);
12681  DONE;
12682})
12683
12684(define_expand "cstoredf4"
12685  [(set (match_operand:SI 0 "register_operand" "=r")
12686	(match_operator:SI 1 "sh_float_comparison_operator"
12687	 [(match_operand:DF 2 "arith_operand" "")
12688	  (match_operand:DF 3 "arith_operand" "")]))]
12689  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12690{
12691  if (TARGET_SHMEDIA)
12692    {
12693      emit_insn (gen_cstore4_media (operands[0], operands[1],
12694				    operands[2], operands[3]));
12695      DONE;
12696    }
12697
12698  if (! currently_expanding_to_rtl)
12699    FAIL;
12700   
12701  sh_emit_compare_and_set (operands, DFmode);
12702  DONE;
12703})
12704
12705;; Sometimes the T bit result of insns is needed in normal registers.
12706;; Instead of open coding all the pattern variations, use the treg_set_expr
12707;; predicate to match any T bit output insn and split it out after.
12708;; This pattern should be below all other related patterns so that it is
12709;; considered as a last resort option during matching.   This allows
12710;; overriding it with special case patterns.
12711(define_insn_and_split "any_treg_expr_to_reg"
12712  [(set (match_operand:SI 0 "arith_reg_dest")
12713	(match_operand 1 "treg_set_expr"))
12714   (clobber (reg:SI T_REG))]
12715  "TARGET_SH1 && can_create_pseudo_p ()"
12716  "#"
12717  "&& !sh_in_recog_treg_set_expr ()"
12718  [(const_int 0)]
12719{
12720  if (dump_file)
12721    fprintf (dump_file, "splitting any_treg_expr_to_reg\n");
12722
12723  if (t_reg_operand (operands[1], VOIDmode))
12724    {
12725      if (dump_file)
12726	fprintf (dump_file, "t_reg_operand: emitting movt\n");
12727      emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
12728      DONE;
12729    }
12730  if (negt_reg_operand (operands[1], VOIDmode))
12731    {
12732      if (dump_file)
12733	fprintf (dump_file, "negt_reg_operand: emitting movrt\n");
12734      emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
12735      DONE;
12736    }
12737
12738  /* If the split out insns ended with a nott, emit a movrt sequence,
12739     otherwise a normal movt.  */
12740  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12741  rtx_insn* i = NULL;
12742  if (ti.remove_trailing_nott ())
12743    {
12744      /* Emit this same insn_and_split again.  However, the next time it
12745	 is split, it will emit the actual negc/movrt insn.  This gives
12746	 other surrounding insns the chance to see the trailing movrt.  */
12747      if (dump_file)
12748	fprintf (dump_file,
12749		 "any_treg_expr_to_reg: replacing trailing nott with movrt\n");
12750      i = emit_insn (gen_any_treg_expr_to_reg (
12751			operands[0], gen_rtx_XOR (SImode, get_t_reg_rtx (),
12752			const1_rtx)));
12753    }
12754  else
12755    {
12756      i = emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
12757      if (dump_file)
12758	fprintf (dump_file, "any_treg_expr_to_reg: appending movt\n");
12759    }
12760
12761  add_reg_note (i, REG_UNUSED, get_t_reg_rtx ());
12762  DONE;
12763})
12764
12765;; -------------------------------------------------------------------------
12766;; Instructions to cope with inline literal tables
12767;; -------------------------------------------------------------------------
12768
12769;; 2 byte integer in line
12770(define_insn "consttable_2"
12771 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
12772		    (match_operand 1 "" "")]
12773		   UNSPECV_CONST2)]
12774 ""
12775{
12776  if (operands[1] != const0_rtx)
12777    assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
12778  return "";
12779}
12780 [(set_attr "length" "2")
12781 (set_attr "in_delay_slot" "no")])
12782
12783;; 4 byte integer in line
12784(define_insn "consttable_4"
12785 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
12786		    (match_operand 1 "" "")]
12787		   UNSPECV_CONST4)]
12788 ""
12789{
12790  if (operands[1] != const0_rtx)
12791    {
12792      assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
12793      mark_symbol_refs_as_used (operands[0]);
12794    }
12795  return "";
12796}
12797 [(set_attr "length" "4")
12798  (set_attr "in_delay_slot" "no")])
12799
12800;; 8 byte integer in line
12801(define_insn "consttable_8"
12802 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
12803		    (match_operand 1 "" "")]
12804		   UNSPECV_CONST8)]
12805 ""
12806{
12807  if (operands[1] != const0_rtx)
12808    assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
12809  return "";
12810}
12811 [(set_attr "length" "8")
12812  (set_attr "in_delay_slot" "no")])
12813
12814;; 4 byte floating point
12815(define_insn "consttable_sf"
12816 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
12817		    (match_operand 1 "" "")]
12818		   UNSPECV_CONST4)]
12819 ""
12820{
12821  if (operands[1] != const0_rtx)
12822    assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
12823		   SFmode, GET_MODE_ALIGNMENT (SFmode));
12824  return "";
12825}
12826 [(set_attr "length" "4")
12827  (set_attr "in_delay_slot" "no")])
12828
12829;; 8 byte floating point
12830(define_insn "consttable_df"
12831 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
12832		    (match_operand 1 "" "")]
12833		   UNSPECV_CONST8)]
12834 ""
12835{
12836  if (operands[1] != const0_rtx)
12837    assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
12838		   DFmode, GET_MODE_ALIGNMENT (DFmode));
12839  return "";
12840}
12841 [(set_attr "length" "8")
12842  (set_attr "in_delay_slot" "no")])
12843
12844;; Alignment is needed for some constant tables; it may also be added for
12845;; Instructions at the start of loops, or after unconditional branches.
12846;; ??? We would get more accurate lengths if we did instruction
12847;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
12848;; here is too conservative.
12849
12850;; align to a two byte boundary
12851(define_expand "align_2"
12852 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
12853 ""
12854 "")
12855
12856;; Align to a four byte boundary.
12857;; align_4 and align_log are instructions for the starts of loops, or
12858;; after unconditional branches, which may take up extra room.
12859(define_expand "align_4"
12860 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
12861 ""
12862 "")
12863
12864;; Align to a cache line boundary.
12865(define_insn "align_log"
12866 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
12867 ""
12868 ""
12869 [(set_attr "length" "0")
12870  (set_attr "in_delay_slot" "no")])
12871
12872;; Emitted at the end of the literal table, used to emit the
12873;; 32bit branch labels if needed.
12874(define_insn "consttable_end"
12875  [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
12876  ""
12877{
12878  return output_jump_label_table ();
12879}
12880  [(set_attr "in_delay_slot" "no")])
12881
12882;; Emitted at the end of the window in the literal table.
12883(define_insn "consttable_window_end"
12884  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
12885  ""
12886  ""
12887  [(set_attr "length" "0")
12888   (set_attr "in_delay_slot" "no")])
12889
12890;; -------------------------------------------------------------------------
12891;; Minimum / maximum operations.
12892;; -------------------------------------------------------------------------
12893
12894;; The SH2A clips.b and clips.w insns do a signed min-max function.  If smin
12895;; and smax standard name patterns are defined, they will be used during
12896;; initial expansion and combine will then be able to form the actual min-max
12897;; pattern.
12898;; The clips.b and clips.w set the SR.CS bit if the value in the register is
12899;; clipped, but there is currently no way of making use of this information.
12900;; The only way to read or reset the SR.CS bit is by accessing the SR.
12901(define_expand "<code>si3"
12902  [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
12903		   (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
12904				 (match_operand 2 "const_int_operand")))
12905	      (clobber (reg:SI T_REG))])]
12906  "TARGET_SH2A"
12907{
12908  /* Force the comparison value into a register, because greater-than
12909     comparisons can work only on registers.  Combine will be able to pick up
12910     the constant value from the REG_EQUAL note when trying to form a min-max
12911     pattern.  */
12912  operands[2] = force_reg (SImode, operands[2]);
12913})
12914
12915;; Convert
12916;;	smax (smin (...))
12917;; to
12918;;	smin (smax (...))
12919(define_insn_and_split "*clips"
12920  [(set (match_operand:SI 0 "arith_reg_dest")
12921	(smax:SI (smin:SI (match_operand:SI 1 "arith_reg_operand")
12922			  (match_operand 2 "clips_max_const_int"))
12923		 (match_operand 3 "clips_min_const_int")))]
12924  "TARGET_SH2A"
12925  "#"
12926  "&& 1"
12927  [(set (match_dup 0)
12928	(smin:SI (smax:SI (match_dup 1) (match_dup 3)) (match_dup 2)))])
12929
12930(define_insn "*clips"
12931  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12932	(smin:SI (smax:SI (match_operand:SI 1 "arith_reg_operand" "0")
12933			  (match_operand 2 "clips_min_const_int"))
12934		 (match_operand 3 "clips_max_const_int")))]
12935  "TARGET_SH2A"
12936{
12937  if (INTVAL (operands[3]) == 127)
12938    return "clips.b	%0";
12939  else if (INTVAL (operands[3]) == 32767)
12940    return "clips.w	%0";
12941  else
12942    gcc_unreachable ();
12943}
12944  [(set_attr "type" "arith")])
12945
12946;; If the expanded smin or smax patterns were not combined, split them into
12947;; a compare and branch sequence, because there are no real smin or smax
12948;; insns.
12949(define_insn_and_split "*<code>si3"
12950  [(set (match_operand:SI 0 "arith_reg_dest")
12951	(SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
12952		      (match_operand:SI 2 "arith_reg_or_0_or_1_operand")))
12953   (clobber (reg:SI T_REG))]
12954  "TARGET_SH2A && can_create_pseudo_p ()"
12955  "#"
12956  "&& 1"
12957  [(const_int 0)]
12958{
12959  rtx skip_label = gen_label_rtx ();
12960  emit_move_insn (operands[0], operands[1]);
12961
12962  rtx cmp_val = operands[2];
12963  if (satisfies_constraint_M (cmp_val))
12964    cmp_val = const0_rtx;
12965
12966  emit_insn (gen_cmpgtsi_t (operands[0], cmp_val));
12967  emit_jump_insn (<CODE> == SMIN
12968			    ? gen_branch_false (skip_label)
12969			    : gen_branch_true (skip_label));
12970
12971  emit_label_after (skip_label, emit_move_insn (operands[0], operands[2]));
12972  DONE;
12973})
12974
12975;; The SH2A clipu.b and clipu.w insns can be used to implement a min function
12976;; with a register and a constant.
12977;; The clipu.b and clipu.w set the SR.CS bit if the value in the register is
12978;; clipped, but there is currently no way of making use of this information.
12979;; The only way to read or reset the SR.CS bit is by accessing the SR.
12980(define_expand "uminsi3"
12981  [(set (match_operand:SI 0 "arith_reg_dest")
12982	(umin:SI (match_operand:SI 1 "arith_reg_operand")
12983		 (match_operand 2 "const_int_operand")))]
12984  "TARGET_SH2A"
12985{
12986  if (INTVAL (operands[2]) == 1)
12987    {
12988      emit_insn (gen_clipu_one (operands[0], operands[1]));
12989      DONE;
12990    }
12991  else if (! clipu_max_const_int (operands[2], VOIDmode))
12992    FAIL;
12993})
12994
12995(define_insn "*clipu"
12996  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12997	(umin:SI (match_operand:SI 1 "arith_reg_operand" "0")
12998		 (match_operand 2 "clipu_max_const_int")))]
12999  "TARGET_SH2A"
13000{
13001  if (INTVAL (operands[2]) == 255)
13002    return "clipu.b	%0";
13003  else if (INTVAL (operands[2]) == 65535)
13004    return "clipu.w	%0";
13005  else
13006    gcc_unreachable ();
13007}
13008  [(set_attr "type" "arith")])
13009
13010(define_insn_and_split "clipu_one"
13011  [(set (match_operand:SI 0 "arith_reg_dest")
13012	(umin:SI (match_operand:SI 1 "arith_reg_operand") (const_int 1)))
13013   (clobber (reg:SI T_REG))]
13014  "TARGET_SH2A"
13015  "#"
13016  "&& can_create_pseudo_p ()"
13017  [(const_int 0)]
13018{
13019  emit_insn (gen_cmpeqsi_t (operands[1], const0_rtx));
13020  emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
13021  DONE;
13022})
13023
13024;; -------------------------------------------------------------------------
13025;; Misc
13026;; -------------------------------------------------------------------------
13027
13028;; String/block move insn.
13029
13030(define_expand "movmemsi"
13031  [(parallel [(set (mem:BLK (match_operand:BLK 0))
13032		   (mem:BLK (match_operand:BLK 1)))
13033	      (use (match_operand:SI 2 "nonmemory_operand"))
13034	      (use (match_operand:SI 3 "immediate_operand"))
13035	      (clobber (reg:SI PR_REG))
13036	      (clobber (reg:SI R4_REG))
13037	      (clobber (reg:SI R5_REG))
13038	      (clobber (reg:SI R0_REG))])]
13039  "TARGET_SH1 && ! TARGET_SH5"
13040{
13041  if (expand_block_move (operands))
13042    DONE;
13043  else
13044    FAIL;
13045})
13046
13047(define_insn "block_move_real"
13048  [(parallel [(set (mem:BLK (reg:SI R4_REG))
13049		   (mem:BLK (reg:SI R5_REG)))
13050	      (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
13051	      (use (match_operand 1 "" "Z,Ccl"))
13052	      (clobber (reg:SI PR_REG))
13053	      (clobber (reg:SI R0_REG))])]
13054  "TARGET_SH1 && ! TARGET_HARD_SH4"
13055  "@
13056	jsr	@%0%#
13057	bsrf	%0\n%O1:%#"
13058  [(set_attr "type" "sfunc")
13059   (set_attr "needs_delay_slot" "yes")])
13060
13061(define_insn "block_lump_real"
13062  [(parallel [(set (mem:BLK (reg:SI R4_REG))
13063		   (mem:BLK (reg:SI R5_REG)))
13064	      (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
13065	      (use (match_operand 1 "" "Z,Ccl"))
13066	      (use (reg:SI R6_REG))
13067	      (clobber (reg:SI PR_REG))
13068	      (clobber (reg:SI T_REG))
13069	      (clobber (reg:SI R4_REG))
13070	      (clobber (reg:SI R5_REG))
13071	      (clobber (reg:SI R6_REG))
13072	      (clobber (reg:SI R0_REG))])]
13073  "TARGET_SH1 && ! TARGET_HARD_SH4"
13074  "@
13075	jsr	@%0%#
13076	bsrf	%0\n%O1:%#"
13077  [(set_attr "type" "sfunc")
13078   (set_attr "needs_delay_slot" "yes")])
13079
13080(define_insn "block_move_real_i4"
13081  [(parallel [(set (mem:BLK (reg:SI R4_REG))
13082		   (mem:BLK (reg:SI R5_REG)))
13083	      (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
13084	      (use (match_operand 1 "" "Z,Ccl"))
13085	      (clobber (reg:SI PR_REG))
13086	      (clobber (reg:SI R0_REG))
13087	      (clobber (reg:SI R1_REG))
13088	      (clobber (reg:SI R2_REG))])]
13089  "TARGET_HARD_SH4"
13090  "@
13091	jsr	@%0%#
13092	bsrf	%0\n%O1:%#"
13093  [(set_attr "type" "sfunc")
13094   (set_attr "needs_delay_slot" "yes")])
13095
13096(define_insn "block_lump_real_i4"
13097  [(parallel [(set (mem:BLK (reg:SI R4_REG))
13098		   (mem:BLK (reg:SI R5_REG)))
13099	      (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
13100	      (use (match_operand 1 "" "Z,Ccl"))
13101	      (use (reg:SI R6_REG))
13102	      (clobber (reg:SI PR_REG))
13103	      (clobber (reg:SI T_REG))
13104	      (clobber (reg:SI R4_REG))
13105	      (clobber (reg:SI R5_REG))
13106	      (clobber (reg:SI R6_REG))
13107	      (clobber (reg:SI R0_REG))
13108	      (clobber (reg:SI R1_REG))
13109	      (clobber (reg:SI R2_REG))
13110	      (clobber (reg:SI R3_REG))])]
13111  "TARGET_HARD_SH4"
13112  "@
13113	jsr	@%0%#
13114	bsrf	%0\n%O1:%#"
13115  [(set_attr "type" "sfunc")
13116   (set_attr "needs_delay_slot" "yes")])
13117
13118;; byte compare pattern
13119;; temp = a ^ b;
13120;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F))
13121(define_insn "cmpstr_t"
13122  [(set (reg:SI T_REG)
13123	(eq:SI (and:SI
13124		 (and:SI
13125		   (and:SI
13126		     (zero_extract:SI
13127		       (xor:SI (match_operand:SI 0 "arith_reg_operand" "r")
13128			       (match_operand:SI 1 "arith_reg_operand" "r"))
13129		       (const_int 8) (const_int 0))
13130		     (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
13131				      (const_int 8) (const_int 8)))
13132		    (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
13133				     (const_int 8) (const_int 16)))
13134		 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
13135				  (const_int 8) (const_int 24)))
13136	       (const_int 0)))]
13137  "TARGET_SH1"
13138  "cmp/str	%0,%1"
13139  [(set_attr "type" "mt_group")])
13140
13141(define_expand "cmpstrsi"
13142  [(set (match_operand:SI 0 "register_operand")
13143	(compare:SI (match_operand:BLK 1 "memory_operand")
13144		    (match_operand:BLK 2 "memory_operand")))
13145   (use (match_operand 3 "immediate_operand"))]
13146  "TARGET_SH1 && optimize"
13147{
13148  if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands))
13149    DONE;
13150  else
13151    FAIL;
13152})
13153
13154(define_expand "cmpstrnsi"
13155  [(set (match_operand:SI 0 "register_operand")
13156	(compare:SI (match_operand:BLK 1 "memory_operand")
13157		    (match_operand:BLK 2 "memory_operand")))
13158   (use (match_operand:SI 3 "nonmemory_operand"))
13159   (use (match_operand:SI 4 "immediate_operand"))]
13160  "TARGET_SH1 && optimize"
13161{
13162  if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands))
13163    DONE;
13164  else
13165    FAIL;
13166})
13167
13168(define_expand "strlensi"
13169  [(set (match_operand:SI 0 "register_operand")
13170	(unspec:SI [(match_operand:BLK 1 "memory_operand")
13171		   (match_operand:SI 2 "immediate_operand")
13172		   (match_operand:SI 3 "immediate_operand")]
13173		  UNSPEC_BUILTIN_STRLEN))]
13174  "TARGET_SH1 && optimize"
13175{
13176 if (! optimize_insn_for_size_p () && sh_expand_strlen (operands))
13177   DONE;
13178 else
13179   FAIL;
13180})
13181
13182(define_expand "setmemqi"
13183  [(parallel [(set (match_operand:BLK 0 "memory_operand")
13184                   (match_operand 2 "const_int_operand"))
13185              (use (match_operand:QI 1 "const_int_operand"))
13186              (use (match_operand:QI 3 "const_int_operand"))])]
13187  "TARGET_SH1 && optimize"
13188  {
13189    if (optimize_insn_for_size_p ())
13190       FAIL;
13191
13192    sh_expand_setmem (operands);
13193    DONE;
13194  })
13195
13196
13197;; -------------------------------------------------------------------------
13198;; Floating point instructions.
13199;; -------------------------------------------------------------------------
13200
13201;; FIXME: For now we disallow any memory operands for fpscr loads/stores,
13202;; except for post-inc loads and pre-dec stores for push/pop purposes.
13203;; This avoids problems with reload.  As a consequence, user initiated fpscr
13204;; stores to memory will always be ferried through a general register.
13205;; User initiated fpscr loads always have to undergo bit masking to preserve
13206;; the current fpu mode settings for the compiler generated code.  Thus such
13207;; fpscr loads will always have to go through general registers anyways.
13208(define_insn "lds_fpscr"
13209  [(set (reg:SI FPSCR_REG)
13210	(match_operand:SI 0 "fpscr_movsrc_operand" "r,>"))
13211   (set (reg:SI FPSCR_STAT_REG)
13212	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_STAT))
13213   (set (reg:SI FPSCR_MODES_REG)
13214	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
13215  "TARGET_FPU_ANY"
13216  "@
13217	lds	%0,fpscr
13218	lds.l	%0,fpscr"
13219  [(set_attr "type" "gp_fpscr,mem_fpscr")])
13220
13221;; A move fpscr -> reg schedules like a move mac -> reg.  Thus we use mac_gp
13222;; type for it.
13223(define_insn "sts_fpscr"
13224  [(set (match_operand:SI 0 "fpscr_movdst_operand" "=r,<")
13225	(reg:SI FPSCR_REG))
13226   (use (reg:SI FPSCR_STAT_REG))
13227   (use (reg:SI FPSCR_MODES_REG))]
13228  "TARGET_FPU_ANY"
13229  "@
13230	sts	fpscr,%0
13231	sts.l	fpscr,%0"
13232  [(set_attr "type" "mac_gp,fstore")])
13233
13234(define_expand "set_fpscr"
13235  [(parallel [(set (reg:SI FPSCR_REG)
13236		   (match_operand:SI 0 "general_operand"))
13237	      (set (reg:SI FPSCR_STAT_REG)
13238		   (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))])]
13239  "TARGET_FPU_ANY"
13240{
13241  /* We have to mask out the FR, SZ and PR bits.  To do that, we need to
13242     get the current FPSCR value first.
13243     (a & ~mask) | (b & mask) = a ^ ((a ^ b) & mask)  */
13244
13245  rtx mask = force_reg (SImode, GEN_INT (FPSCR_FR | FPSCR_SZ | FPSCR_PR));
13246
13247  rtx a = force_reg (SImode, operands[0]);
13248
13249  rtx b = gen_reg_rtx (SImode);
13250  emit_insn (gen_sts_fpscr (b));
13251
13252  rtx a_xor_b = gen_reg_rtx (SImode);
13253  emit_insn (gen_xorsi3 (a_xor_b, a, b));
13254
13255  rtx a_xor_b_and_mask = gen_reg_rtx (SImode);
13256  emit_insn (gen_andsi3 (a_xor_b_and_mask, a_xor_b, mask));
13257
13258  rtx r = gen_reg_rtx (SImode);
13259  emit_insn (gen_xorsi3 (r, a_xor_b_and_mask, a));
13260  emit_insn (gen_lds_fpscr (r));
13261
13262  DONE;
13263})
13264
13265;; ??? This uses the fp unit, but has no type indicating that.
13266;; If we did that, this would either give a bogus latency or introduce
13267;; a bogus FIFO constraint.
13268;; Since this insn is currently only used for prologues/epilogues,
13269;; it is probably best to claim no function unit, which matches the
13270;; current setting.
13271(define_insn "toggle_sz"
13272  [(set (reg:SI FPSCR_REG)
13273	(xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_SZ)))
13274   (set (reg:SI FPSCR_MODES_REG)
13275	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
13276  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13277  "fschg"
13278  [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
13279
13280;; Toggle FPU precision PR mode.
13281
13282(define_insn "toggle_pr"
13283  [(set (reg:SI FPSCR_REG)
13284	(xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_PR)))
13285   (set (reg:SI FPSCR_MODES_REG)
13286	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
13287  "TARGET_SH4A_FP"
13288  "fpchg"
13289  [(set_attr "type" "fpscr_toggle")])
13290
13291(define_expand "addsf3"
13292  [(set (match_operand:SF 0 "fp_arith_reg_operand")
13293	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand")
13294		 (match_operand:SF 2 "fp_arith_reg_operand")))]
13295  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13296{
13297  if (TARGET_SH2E)
13298    {
13299      emit_insn (gen_addsf3_i (operands[0], operands[1], operands[2]));
13300      DONE;
13301    }
13302})
13303
13304(define_insn "*addsf3_media"
13305  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13306	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
13307		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13308  "TARGET_SHMEDIA_FPU"
13309  "fadd.s	%1, %2, %0"
13310  [(set_attr "type" "fparith_media")])
13311
13312(define_insn_and_split "unary_sf_op"
13313  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
13314	(vec_select:V2SF
13315	 (vec_concat:V2SF
13316	  (vec_select:SF
13317	   (match_dup 0)
13318	   (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
13319	  (match_operator:SF 2 "unary_float_operator"
13320	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
13321			    (parallel [(match_operand 4
13322					"const_int_operand" "n")]))]))
13323	 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
13324  "TARGET_SHMEDIA_FPU"
13325  "#"
13326  "TARGET_SHMEDIA_FPU && reload_completed"
13327  [(set (match_dup 5) (match_dup 6))]
13328{
13329  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
13330  rtx op1 = gen_rtx_REG (SFmode,
13331			 (true_regnum (operands[1])
13332			  + (INTVAL (operands[4]) ^ endian)));
13333
13334  operands[7] = gen_rtx_REG (SFmode,
13335			     (true_regnum (operands[0])
13336			      + (INTVAL (operands[3]) ^ endian)));
13337  operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
13338}
13339  [(set_attr "type" "fparith_media")])
13340
13341(define_insn_and_split "binary_sf_op0"
13342  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
13343	(vec_concat:V2SF
13344	  (match_operator:SF 3 "binary_float_operator"
13345	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
13346			    (parallel [(const_int 0)]))
13347	     (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
13348			    (parallel [(const_int 0)]))])
13349	  (vec_select:SF
13350	   (match_dup 0)
13351	   (parallel [(const_int 1)]))))]
13352  "TARGET_SHMEDIA_FPU"
13353  "#"
13354  "&& reload_completed"
13355  [(set (match_dup 4) (match_dup 5))]
13356{
13357  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
13358  rtx op1 = gen_rtx_REG (SFmode,
13359			 true_regnum (operands[1]) + endian);
13360  rtx op2 = gen_rtx_REG (SFmode,
13361			 true_regnum (operands[2]) + endian);
13362
13363  operands[4] = gen_rtx_REG (SFmode,
13364			     true_regnum (operands[0]) + endian);
13365  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
13366}
13367  [(set_attr "type" "fparith_media")])
13368
13369(define_insn_and_split "binary_sf_op1"
13370  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
13371	(vec_concat:V2SF
13372	  (vec_select:SF
13373	   (match_dup 0)
13374	   (parallel [(const_int 0)]))
13375	  (match_operator:SF 3 "binary_float_operator"
13376	    [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
13377			    (parallel [(const_int 1)]))
13378	     (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
13379			    (parallel [(const_int 1)]))])))]
13380  "TARGET_SHMEDIA_FPU"
13381  "#"
13382  "&& reload_completed"
13383  [(set (match_dup 4) (match_dup 5))]
13384{
13385  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
13386  rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
13387  rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
13388
13389  operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
13390  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
13391}
13392  [(set_attr "type" "fparith_media")])
13393
13394(define_insn "addsf3_i"
13395  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13396	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
13397		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13398   (clobber (reg:SI FPSCR_STAT_REG))
13399   (use (reg:SI FPSCR_MODES_REG))]
13400  "TARGET_SH2E"
13401  "fadd	%2,%0"
13402  [(set_attr "type" "fp")
13403   (set_attr "fp_mode" "single")])
13404
13405(define_expand "subsf3"
13406  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13407	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
13408		  (match_operand:SF 2 "fp_arith_reg_operand" "")))]
13409  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13410{
13411  if (TARGET_SH2E)
13412    {
13413      emit_insn (gen_subsf3_i (operands[0], operands[1], operands[2]));
13414      DONE;
13415    }
13416})
13417
13418(define_insn "*subsf3_media"
13419  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13420	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
13421		  (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13422  "TARGET_SHMEDIA_FPU"
13423  "fsub.s	%1, %2, %0"
13424  [(set_attr "type" "fparith_media")])
13425
13426(define_insn "subsf3_i"
13427  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13428	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
13429		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13430   (clobber (reg:SI FPSCR_STAT_REG))
13431   (use (reg:SI FPSCR_MODES_REG))]
13432  "TARGET_SH2E"
13433  "fsub	%2,%0"
13434  [(set_attr "type" "fp")
13435   (set_attr "fp_mode" "single")])
13436
13437(define_expand "mulsf3"
13438  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13439	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
13440		 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
13441  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13442{
13443  if (TARGET_SH2E)
13444    {
13445      emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2]));
13446      DONE;
13447    }
13448})
13449
13450(define_insn "*mulsf3_media"
13451  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13452	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
13453		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13454  "TARGET_SHMEDIA_FPU"
13455  "fmul.s	%1, %2, %0"
13456  [(set_attr "type" "fparith_media")])
13457
13458(define_insn "mulsf3_i"
13459  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13460	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
13461		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13462   (clobber (reg:SI FPSCR_STAT_REG))
13463   (use (reg:SI FPSCR_MODES_REG))]
13464  "TARGET_SH2E"
13465  "fmul	%2,%0"
13466  [(set_attr "type" "fp")
13467   (set_attr "fp_mode" "single")])
13468
13469;; FMA (fused multiply-add) patterns
13470(define_expand "fmasf4"
13471  [(set (match_operand:SF 0 "fp_arith_reg_operand")
13472	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand")
13473		(match_operand:SF 2 "fp_arith_reg_operand")
13474		(match_operand:SF 3 "fp_arith_reg_operand")))]
13475  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13476{
13477  if (TARGET_SH2E)
13478    {
13479      emit_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
13480			       operands[3]));
13481      DONE;
13482    }
13483})
13484
13485(define_insn "fmasf4_i"
13486  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13487	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
13488		(match_operand:SF 2 "fp_arith_reg_operand" "f")
13489		(match_operand:SF 3 "fp_arith_reg_operand" "0")))
13490   (clobber (reg:SI FPSCR_STAT_REG))
13491   (use (reg:SI FPSCR_MODES_REG))]
13492  "TARGET_SH2E"
13493  "fmac	%1,%2,%0"
13494  [(set_attr "type" "fp")
13495   (set_attr "fp_mode" "single")])
13496
13497(define_insn "fmasf4_media"
13498  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13499	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
13500		(match_operand:SF 2 "fp_arith_reg_operand" "f")
13501		(match_operand:SF 3 "fp_arith_reg_operand" "0")))]
13502  "TARGET_SHMEDIA_FPU"
13503  "fmac.s %1, %2, %0"
13504  [(set_attr "type" "fparith_media")])
13505
13506;; For some cases such as 'a * b + a' the FMA pattern is not generated by
13507;; previous transformations.  If FMA is generally allowed, let the combine
13508;; pass utilize it.
13509(define_insn_and_split "*fmasf4"
13510  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13511	(plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
13512			  (match_operand:SF 2 "fp_arith_reg_operand" "f"))
13513		 (match_operand:SF 3 "arith_reg_operand" "0")))
13514   (clobber (reg:SI FPSCR_STAT_REG))
13515   (use (reg:SI FPSCR_MODES_REG))]
13516  "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
13517  "fmac	%1,%2,%0"
13518  "&& can_create_pseudo_p ()"
13519  [(parallel [(set (match_dup 0)
13520		   (fma:SF (match_dup 1) (match_dup 2) (match_dup 3)))
13521	      (clobber (reg:SI FPSCR_STAT_REG))
13522	      (use (reg:SI FPSCR_MODES_REG))])]
13523{
13524  /* Change 'b * a + a' into 'a * b + a'.
13525     This is better for register allocation.  */
13526  if (REGNO (operands[2]) == REGNO (operands[3]))
13527    std::swap (operands[1], operands[2]);
13528}
13529  [(set_attr "type" "fp")
13530   (set_attr "fp_mode" "single")])
13531
13532(define_insn "*fmasf4_media"
13533  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13534	(plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
13535			  (match_operand:SF 2 "fp_arith_reg_operand" "f"))
13536		 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
13537  "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF"
13538  "fmac.s %1, %2, %0"
13539  [(set_attr "type" "fparith_media")])
13540
13541(define_expand "divsf3"
13542  [(set (match_operand:SF 0 "fp_arith_reg_operand")
13543	(div:SF (match_operand:SF 1 "fp_arith_reg_operand")
13544		(match_operand:SF 2 "fp_arith_reg_operand")))]
13545  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13546{
13547  if (TARGET_SH2E)
13548    {
13549      emit_insn (gen_divsf3_i (operands[0], operands[1], operands[2]));
13550      DONE;
13551    }
13552})
13553
13554(define_insn "*divsf3_media"
13555  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13556	(div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
13557		(match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13558  "TARGET_SHMEDIA_FPU"
13559  "fdiv.s	%1, %2, %0"
13560  [(set_attr "type" "fdiv_media")])
13561
13562(define_insn "divsf3_i"
13563  [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f")
13564	(div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
13565		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13566   (clobber (reg:SI FPSCR_STAT_REG))
13567   (use (reg:SI FPSCR_MODES_REG))]
13568  "TARGET_SH2E"
13569  "fdiv	%2,%0"
13570  [(set_attr "type" "fdiv")
13571   (set_attr "fp_mode" "single")])
13572
13573(define_insn "floatdisf2"
13574  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13575	(float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
13576  "TARGET_SHMEDIA_FPU"
13577  "float.qs %1, %0"
13578  [(set_attr "type" "fpconv_media")])
13579
13580(define_expand "floatsisf2"
13581  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13582	(float:SF (match_operand:SI 1 "fpul_operand" "")))]
13583  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13584{
13585  if (!TARGET_SHMEDIA_FPU)
13586    {
13587      emit_insn (gen_floatsisf2_i4 (operands[0], operands[1]));
13588      DONE;
13589    }
13590})
13591
13592(define_insn "*floatsisf2_media"
13593  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13594	(float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
13595  "TARGET_SHMEDIA_FPU"
13596  "float.ls	%1, %0"
13597  [(set_attr "type" "fpconv_media")])
13598
13599(define_insn "floatsisf2_i4"
13600  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13601	(float:SF (match_operand:SI 1 "fpul_operand" "y")))
13602   (clobber (reg:SI FPSCR_STAT_REG))
13603   (use (reg:SI FPSCR_MODES_REG))]
13604  "TARGET_SH2E"
13605  "float	%1,%0"
13606  [(set_attr "type" "fp")
13607   (set_attr "fp_mode" "single")])
13608
13609(define_insn "fix_truncsfdi2"
13610  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
13611	(fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13612  "TARGET_SHMEDIA_FPU"
13613  "ftrc.sq %1, %0"
13614  [(set_attr "type" "fpconv_media")])
13615
13616(define_expand "fix_truncsfsi2"
13617  [(set (match_operand:SI 0 "fpul_operand" "=y")
13618	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13619  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13620{
13621  if (!TARGET_SHMEDIA_FPU)
13622    {
13623      emit_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1]));
13624      DONE;
13625    }
13626})
13627
13628(define_insn "*fix_truncsfsi2_media"
13629  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
13630	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13631  "TARGET_SHMEDIA_FPU"
13632  "ftrc.sl	%1, %0"
13633  [(set_attr "type" "fpconv_media")])
13634
13635(define_insn "fix_truncsfsi2_i4"
13636  [(set (match_operand:SI 0 "fpul_operand" "=y")
13637	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
13638   (clobber (reg:SI FPSCR_STAT_REG))
13639   (use (reg:SI FPSCR_MODES_REG))]
13640  "TARGET_SH2E"
13641  "ftrc	%1,%0"
13642  [(set_attr "type" "ftrc_s")
13643   (set_attr "fp_mode" "single")])
13644
13645(define_insn "cmpgtsf_t"
13646  [(set (reg:SI T_REG)
13647	(gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
13648	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
13649   (clobber (reg:SI FPSCR_STAT_REG))
13650   (use (reg:SI FPSCR_MODES_REG))]
13651  "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
13652  "fcmp/gt	%1,%0"
13653  [(set_attr "type" "fp_cmp")
13654   (set_attr "fp_mode" "single")])
13655
13656(define_insn "cmpeqsf_t"
13657  [(set (reg:SI T_REG)
13658	(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
13659	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
13660   (clobber (reg:SI FPSCR_STAT_REG))
13661   (use (reg:SI FPSCR_MODES_REG))]
13662  "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
13663  "fcmp/eq	%1,%0"
13664  [(set_attr "type" "fp_cmp")
13665   (set_attr "fp_mode" "single")])
13666
13667(define_insn "ieee_ccmpeqsf_t"
13668  [(set (reg:SI T_REG)
13669	(ior:SI (reg:SI T_REG)
13670		(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
13671		       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
13672   (clobber (reg:SI FPSCR_STAT_REG))
13673   (use (reg:SI FPSCR_MODES_REG))]
13674  "TARGET_IEEE && TARGET_SH2E"
13675{
13676  return output_ieee_ccmpeq (insn, operands);
13677}
13678  [(set_attr "length" "4")
13679   (set_attr "fp_mode" "single")])
13680
13681(define_insn "cmpeqsf_media"
13682  [(set (match_operand:SI 0 "register_operand" "=r")
13683	(eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13684	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13685  "TARGET_SHMEDIA_FPU"
13686  "fcmpeq.s	%1, %2, %0"
13687  [(set_attr "type" "fcmp_media")])
13688
13689(define_insn "cmpgtsf_media"
13690  [(set (match_operand:SI 0 "register_operand" "=r")
13691	(gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13692	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13693  "TARGET_SHMEDIA_FPU"
13694  "fcmpgt.s	%1, %2, %0"
13695  [(set_attr "type" "fcmp_media")])
13696
13697(define_insn "cmpgesf_media"
13698  [(set (match_operand:SI 0 "register_operand" "=r")
13699	(ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13700	       (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13701  "TARGET_SHMEDIA_FPU"
13702  "fcmpge.s	%1, %2, %0"
13703  [(set_attr "type" "fcmp_media")])
13704
13705(define_insn "cmpunsf_media"
13706  [(set (match_operand:SI 0 "register_operand" "=r")
13707	(unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13708		      (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13709  "TARGET_SHMEDIA_FPU"
13710  "fcmpun.s	%1, %2, %0"
13711  [(set_attr "type" "fcmp_media")])
13712
13713(define_expand "cbranchsf4"
13714  [(set (pc)
13715	(if_then_else (match_operator 0 "sh_float_comparison_operator"
13716		       [(match_operand:SF 1 "arith_operand" "")
13717			(match_operand:SF 2 "arith_operand" "")])
13718		      (match_operand 3 "" "")
13719		      (pc)))]
13720  "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13721{
13722  if (TARGET_SHMEDIA)
13723    emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
13724					  operands[3]));
13725  else
13726    sh_emit_compare_and_branch (operands, SFmode);
13727  DONE;
13728})
13729
13730(define_expand "negsf2"
13731  [(set (match_operand:SF 0 "fp_arith_reg_operand")
13732	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand")))]
13733  "TARGET_SH2E || TARGET_SHMEDIA_FPU")
13734
13735(define_insn "*negsf2_media"
13736  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13737	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13738  "TARGET_SHMEDIA_FPU"
13739  "fneg.s	%1, %0"
13740  [(set_attr "type" "fmove_media")])
13741
13742(define_insn "*negsf2_i"
13743  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13744	(neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))]
13745  "TARGET_SH2E"
13746  "fneg	%0"
13747  [(set_attr "type" "fmove")])
13748
13749(define_expand "sqrtsf2"
13750  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13751	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
13752  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
13753{
13754  if (TARGET_SH3E)
13755    {
13756      emit_insn (gen_sqrtsf2_i (operands[0], operands[1]));
13757      DONE;
13758    }
13759})
13760
13761(define_insn "*sqrtsf2_media"
13762  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13763	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13764  "TARGET_SHMEDIA_FPU"
13765  "fsqrt.s	%1, %0"
13766  [(set_attr "type" "fdiv_media")])
13767
13768(define_insn "sqrtsf2_i"
13769  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13770	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
13771   (clobber (reg:SI FPSCR_STAT_REG))
13772   (use (reg:SI FPSCR_MODES_REG))]
13773  "TARGET_SH3E"
13774  "fsqrt	%0"
13775  [(set_attr "type" "fdiv")
13776   (set_attr "fp_mode" "single")])
13777
13778(define_insn "rsqrtsf2"
13779  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13780	(unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "0")]
13781		   UNSPEC_FSRRA))
13782   (clobber (reg:SI FPSCR_STAT_REG))
13783   (use (reg:SI FPSCR_MODES_REG))]
13784  "TARGET_FPU_ANY && TARGET_FSRRA"
13785  "fsrra	%0"
13786  [(set_attr "type" "fsrra")
13787   (set_attr "fp_mode" "single")])
13788
13789;; When the sincos pattern is defined, the builtin functions sin and cos
13790;; will be expanded to the sincos pattern and one of the output values will
13791;; remain unused.
13792(define_expand "sincossf3"
13793  [(set (match_operand:SF 0 "nonimmediate_operand")
13794	(unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
13795   (set (match_operand:SF 1 "nonimmediate_operand")
13796	(unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
13797  "TARGET_FPU_ANY && TARGET_FSCA"
13798{
13799  rtx scaled = gen_reg_rtx (SFmode);
13800  rtx truncated = gen_reg_rtx (SImode);
13801  rtx fsca = gen_reg_rtx (V2SFmode);
13802  rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
13803
13804  emit_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
13805  emit_insn (gen_fix_truncsfsi2 (truncated, scaled));
13806  emit_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf ()));
13807
13808  emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
13809  emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
13810  DONE;
13811})
13812
13813(define_insn_and_split "fsca"
13814  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
13815	(vec_concat:V2SF
13816	 (unspec:SF [(mult:SF
13817		      (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
13818		      (match_operand:SF 2 "fsca_scale_factor" "i"))
13819		    ] UNSPEC_FSINA)
13820	 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
13821		    ] UNSPEC_FCOSA)))
13822   (clobber (reg:SI FPSCR_STAT_REG))
13823   (use (reg:SI FPSCR_MODES_REG))]
13824  "TARGET_FPU_ANY && TARGET_FSCA"
13825  "fsca	fpul,%d0"
13826  "&& !fpul_operand (operands[1], SImode)"
13827  [(const_int 0)]
13828{
13829  /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
13830     to a simple reg, otherwise reload will have trouble reloading the
13831     pseudo into fpul.  */
13832  rtx x = XEXP (operands[1], 0);
13833  while (x != NULL_RTX && !fpul_operand (x, SImode))
13834    {
13835      gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
13836      x = XEXP (x, 0);
13837    }
13838  gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
13839  emit_insn (gen_fsca (operands[0], x, operands[2]));
13840  DONE;
13841}
13842  [(set_attr "type" "fsca")
13843   (set_attr "fp_mode" "single")])
13844
13845(define_expand "abssf2"
13846  [(set (match_operand:SF 0 "fp_arith_reg_operand")
13847	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand")))]
13848  "TARGET_SH2E || TARGET_SHMEDIA_FPU")
13849
13850(define_insn "*abssf2_media"
13851  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13852	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13853  "TARGET_SHMEDIA_FPU"
13854  "fabs.s	%1, %0"
13855  [(set_attr "type" "fmove_media")])
13856
13857(define_insn "*abssf2_i"
13858  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13859	(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))]
13860  "TARGET_SH2E"
13861  "fabs	%0"
13862  [(set_attr "type" "fmove")])
13863
13864(define_expand "adddf3"
13865  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13866	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13867		 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13868  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13869{
13870  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13871    {
13872      emit_insn (gen_adddf3_i (operands[0], operands[1], operands[2]));
13873      DONE;
13874    }
13875})
13876
13877(define_insn "*adddf3_media"
13878  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13879	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
13880		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13881  "TARGET_SHMEDIA_FPU"
13882  "fadd.d	%1, %2, %0"
13883  [(set_attr "type" "dfparith_media")])
13884
13885(define_insn "adddf3_i"
13886  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13887	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
13888		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13889   (clobber (reg:SI FPSCR_STAT_REG))
13890   (use (reg:SI FPSCR_MODES_REG))]
13891  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13892  "fadd	%2,%0"
13893  [(set_attr "type" "dfp_arith")
13894   (set_attr "fp_mode" "double")])
13895
13896(define_expand "subdf3"
13897  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13898	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13899		  (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13900  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13901{
13902  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13903    {
13904      emit_insn (gen_subdf3_i (operands[0], operands[1], operands[2]));
13905      DONE;
13906    }
13907})
13908
13909(define_insn "*subdf3_media"
13910  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13911	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
13912		  (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13913  "TARGET_SHMEDIA_FPU"
13914  "fsub.d	%1, %2, %0"
13915  [(set_attr "type" "dfparith_media")])
13916
13917(define_insn "subdf3_i"
13918  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13919	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
13920		  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13921   (clobber (reg:SI FPSCR_STAT_REG))
13922   (use (reg:SI FPSCR_MODES_REG))]
13923  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13924  "fsub	%2,%0"
13925  [(set_attr "type" "dfp_arith")
13926   (set_attr "fp_mode" "double")])
13927
13928(define_expand "muldf3"
13929  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13930	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13931		 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13932  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13933{
13934  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13935    {
13936      emit_insn (gen_muldf3_i (operands[0], operands[1], operands[2]));
13937      DONE;
13938    }
13939})
13940
13941(define_insn "*muldf3_media"
13942  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13943	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
13944		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13945  "TARGET_SHMEDIA_FPU"
13946  "fmul.d	%1, %2, %0"
13947  [(set_attr "type" "dfmul_media")])
13948
13949(define_insn "muldf3_i"
13950  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13951	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
13952		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13953   (clobber (reg:SI FPSCR_STAT_REG))
13954   (use (reg:SI FPSCR_MODES_REG))]
13955  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13956  "fmul	%2,%0"
13957  [(set_attr "type" "dfp_mul")
13958   (set_attr "fp_mode" "double")])
13959
13960(define_expand "divdf3"
13961  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13962	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13963		(match_operand:DF 2 "fp_arith_reg_operand" "")))]
13964  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13965{
13966  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13967    {
13968      emit_insn (gen_divdf3_i (operands[0], operands[1], operands[2]));
13969      DONE;
13970    }
13971})
13972
13973(define_insn "*divdf3_media"
13974  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13975	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
13976		(match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13977  "TARGET_SHMEDIA_FPU"
13978  "fdiv.d	%1, %2, %0"
13979  [(set_attr "type" "dfdiv_media")])
13980
13981(define_insn "divdf3_i"
13982  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13983	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
13984		(match_operand:DF 2 "fp_arith_reg_operand" "f")))
13985   (clobber (reg:SI FPSCR_STAT_REG))
13986   (use (reg:SI FPSCR_MODES_REG))]
13987  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13988  "fdiv	%2,%0"
13989  [(set_attr "type" "dfdiv")
13990   (set_attr "fp_mode" "double")])
13991
13992(define_insn "floatdidf2"
13993  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13994	(float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
13995  "TARGET_SHMEDIA_FPU"
13996  "float.qd	%1, %0"
13997  [(set_attr "type" "dfpconv_media")])
13998
13999(define_expand "floatsidf2"
14000  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
14001	(float:DF (match_operand:SI 1 "fpul_operand" "")))]
14002  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
14003{
14004  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
14005    {
14006      emit_insn (gen_floatsidf2_i (operands[0], operands[1]));
14007      DONE;
14008    }
14009})
14010
14011(define_insn "*floatsidf2_media"
14012  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14013	(float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
14014  "TARGET_SHMEDIA_FPU"
14015  "float.ld	%1, %0"
14016  [(set_attr "type" "dfpconv_media")])
14017
14018(define_insn "floatsidf2_i"
14019  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14020	(float:DF (match_operand:SI 1 "fpul_operand" "y")))
14021   (clobber (reg:SI FPSCR_STAT_REG))
14022   (use (reg:SI FPSCR_MODES_REG))]
14023  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14024  "float	%1,%0"
14025  [(set_attr "type" "dfp_conv")
14026   (set_attr "fp_mode" "double")])
14027
14028(define_insn "fix_truncdfdi2"
14029  [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
14030	(fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
14031  "TARGET_SHMEDIA_FPU"
14032  "ftrc.dq	%1, %0"
14033  [(set_attr "type" "dfpconv_media")])
14034
14035(define_expand "fix_truncdfsi2"
14036  [(set (match_operand:SI 0 "fpul_operand" "")
14037	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
14038  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
14039{
14040  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
14041    {
14042      emit_insn (gen_fix_truncdfsi2_i (operands[0], operands[1]));
14043      DONE;
14044    }
14045})
14046
14047(define_insn "*fix_truncdfsi2_media"
14048  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
14049	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
14050  "TARGET_SHMEDIA_FPU"
14051  "ftrc.dl	%1, %0"
14052  [(set_attr "type" "dfpconv_media")])
14053
14054(define_insn "fix_truncdfsi2_i"
14055  [(set (match_operand:SI 0 "fpul_operand" "=y")
14056	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
14057   (clobber (reg:SI FPSCR_STAT_REG))
14058   (use (reg:SI FPSCR_MODES_REG))]
14059  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14060  "ftrc	%1,%0"
14061  [(set_attr "type" "dfp_conv")
14062   (set_attr "dfp_comp" "no")
14063   (set_attr "fp_mode" "double")])
14064
14065(define_insn "cmpgtdf_t"
14066  [(set (reg:SI T_REG)
14067	(gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
14068	       (match_operand:DF 1 "fp_arith_reg_operand" "f")))
14069   (clobber (reg:SI FPSCR_STAT_REG))
14070   (use (reg:SI FPSCR_MODES_REG))]
14071  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14072  "fcmp/gt	%1,%0"
14073  [(set_attr "type" "dfp_cmp")
14074   (set_attr "fp_mode" "double")])
14075
14076(define_insn "cmpeqdf_t"
14077  [(set (reg:SI T_REG)
14078	(eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
14079	       (match_operand:DF 1 "fp_arith_reg_operand" "f")))
14080   (clobber (reg:SI FPSCR_STAT_REG))
14081   (use (reg:SI FPSCR_MODES_REG))]
14082  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14083  "fcmp/eq	%1,%0"
14084  [(set_attr "type" "dfp_cmp")
14085   (set_attr "fp_mode" "double")])
14086
14087(define_insn "*ieee_ccmpeqdf_t"
14088  [(set (reg:SI T_REG)
14089	(ior:SI (reg:SI T_REG)
14090		(eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
14091		       (match_operand:DF 1 "fp_arith_reg_operand" "f"))))
14092   (clobber (reg:SI FPSCR_STAT_REG))
14093   (use (reg:SI FPSCR_MODES_REG))]
14094  "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14095{
14096  return output_ieee_ccmpeq (insn, operands);
14097}
14098  [(set_attr "length" "4")
14099   (set_attr "fp_mode" "double")])
14100
14101(define_insn "cmpeqdf_media"
14102  [(set (match_operand:SI 0 "register_operand" "=r")
14103	(eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
14104	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
14105  "TARGET_SHMEDIA_FPU"
14106  "fcmpeq.d	%1,%2,%0"
14107  [(set_attr "type" "fcmp_media")])
14108
14109(define_insn "cmpgtdf_media"
14110  [(set (match_operand:SI 0 "register_operand" "=r")
14111	(gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
14112	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
14113  "TARGET_SHMEDIA_FPU"
14114  "fcmpgt.d	%1,%2,%0"
14115  [(set_attr "type" "fcmp_media")])
14116
14117(define_insn "cmpgedf_media"
14118  [(set (match_operand:SI 0 "register_operand" "=r")
14119	(ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
14120	       (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
14121  "TARGET_SHMEDIA_FPU"
14122  "fcmpge.d	%1,%2,%0"
14123  [(set_attr "type" "fcmp_media")])
14124
14125(define_insn "cmpundf_media"
14126  [(set (match_operand:SI 0 "register_operand" "=r")
14127	(unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
14128		      (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
14129  "TARGET_SHMEDIA_FPU"
14130  "fcmpun.d	%1,%2,%0"
14131  [(set_attr "type" "fcmp_media")])
14132
14133(define_expand "cbranchdf4"
14134  [(set (pc)
14135	(if_then_else (match_operator 0 "sh_float_comparison_operator"
14136		       [(match_operand:DF 1 "arith_operand" "")
14137			(match_operand:DF 2 "arith_operand" "")])
14138		      (match_operand 3 "" "")
14139		      (pc)))]
14140  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
14141{
14142  if (TARGET_SHMEDIA)
14143    emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
14144					  operands[3]));
14145  else
14146    sh_emit_compare_and_branch (operands, DFmode);
14147  DONE;
14148})
14149
14150(define_expand "negdf2"
14151  [(set (match_operand:DF 0 "fp_arith_reg_operand")
14152	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
14153  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU")
14154
14155(define_insn "*negdf2_media"
14156  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14157	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
14158  "TARGET_SHMEDIA_FPU"
14159  "fneg.d	%1, %0"
14160  [(set_attr "type" "fmove_media")])
14161
14162(define_insn "*negdf2_i"
14163  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14164	(neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))]
14165  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14166  "fneg	%0"
14167  [(set_attr "type" "fmove")])
14168
14169(define_expand "sqrtdf2"
14170  [(set (match_operand:DF 0 "fp_arith_reg_operand")
14171	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
14172  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
14173{
14174  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
14175    {
14176      emit_insn (gen_sqrtdf2_i (operands[0], operands[1]));
14177      DONE;
14178    }
14179})
14180
14181(define_insn "*sqrtdf2_media"
14182  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14183	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
14184  "TARGET_SHMEDIA_FPU"
14185  "fsqrt.d	%1, %0"
14186  [(set_attr "type" "dfdiv_media")])
14187
14188(define_insn "sqrtdf2_i"
14189  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14190	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
14191   (clobber (reg:SI FPSCR_STAT_REG))
14192   (use (reg:SI FPSCR_MODES_REG))]
14193  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14194  "fsqrt	%0"
14195  [(set_attr "type" "dfdiv")
14196   (set_attr "fp_mode" "double")])
14197
14198(define_expand "absdf2"
14199  [(set (match_operand:DF 0 "fp_arith_reg_operand")
14200	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
14201  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU")
14202
14203(define_insn "*absdf2_media"
14204  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14205	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
14206  "TARGET_SHMEDIA_FPU"
14207  "fabs.d	%1, %0"
14208  [(set_attr "type" "fmove_media")])
14209
14210(define_insn "*absdf2_i"
14211  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14212	(abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))]
14213  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14214  "fabs	%0"
14215  [(set_attr "type" "fmove")])
14216
14217(define_expand "extendsfdf2"
14218  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
14219	(float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
14220  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
14221{
14222  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
14223    {
14224      emit_insn (gen_extendsfdf2_i4 (operands[0], operands[1]));
14225      DONE;
14226    }
14227})
14228
14229(define_insn "*extendsfdf2_media"
14230  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14231	(float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
14232  "TARGET_SHMEDIA_FPU"
14233  "fcnv.sd	%1, %0"
14234  [(set_attr "type" "dfpconv_media")])
14235
14236(define_insn "extendsfdf2_i4"
14237  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
14238	(float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
14239   (clobber (reg:SI FPSCR_STAT_REG))
14240   (use (reg:SI FPSCR_MODES_REG))]
14241  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14242  "fcnvsd  %1,%0"
14243  [(set_attr "type" "fp")
14244   (set_attr "fp_mode" "double")])
14245
14246(define_expand "truncdfsf2"
14247  [(set (match_operand:SF 0 "fpul_operand" "")
14248	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
14249  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
14250{
14251  if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
14252    {
14253      emit_insn (gen_truncdfsf2_i4 (operands[0], operands[1]));
14254      DONE;
14255    }
14256})
14257
14258(define_insn "*truncdfsf2_media"
14259  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14260	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
14261  "TARGET_SHMEDIA_FPU"
14262  "fcnv.ds	%1, %0"
14263  [(set_attr "type" "dfpconv_media")])
14264
14265(define_insn "truncdfsf2_i4"
14266  [(set (match_operand:SF 0 "fpul_operand" "=y")
14267	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
14268   (clobber (reg:SI FPSCR_STAT_REG))
14269   (use (reg:SI FPSCR_MODES_REG))]
14270  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
14271  "fcnvds  %1,%0"
14272  [(set_attr "type" "fp")
14273   (set_attr "fp_mode" "double")])
14274
14275;; -------------------------------------------------------------------------
14276;; Bit field extract patterns.
14277;; -------------------------------------------------------------------------
14278
14279;; These give better code for packed bitfields,  because they allow
14280;; auto-increment addresses to be generated.
14281
14282(define_expand "insv"
14283  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
14284			 (match_operand:SI 1 "immediate_operand" "")
14285			 (match_operand:SI 2 "immediate_operand" ""))
14286	(match_operand:SI 3 "general_operand" ""))]
14287  "TARGET_SH1 && TARGET_BIG_ENDIAN"
14288{
14289  rtx addr_target, orig_address, shift_reg, qi_val;
14290  HOST_WIDE_INT bitsize, size, v = 0;
14291  rtx x = operands[3];
14292
14293  if (TARGET_SH2A && TARGET_BITOPS
14294      && (satisfies_constraint_Sbw (operands[0])
14295	  || satisfies_constraint_Sbv (operands[0]))
14296      && satisfies_constraint_M (operands[1])
14297      && satisfies_constraint_K03 (operands[2]))
14298    {
14299      if (satisfies_constraint_N (operands[3]))
14300	{
14301	  emit_insn (gen_bclr_m2a (operands[0], operands[2]));
14302	  DONE;
14303	}
14304      else if (satisfies_constraint_M (operands[3]))
14305	{
14306	  emit_insn (gen_bset_m2a (operands[0], operands[2]));
14307	  DONE;
14308	}
14309      else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
14310		&& satisfies_constraint_M (operands[1]))
14311	{
14312	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
14313	  DONE;
14314	}
14315      else if (REG_P (operands[3])
14316	       && satisfies_constraint_M (operands[1]))
14317	{
14318	  emit_insn (gen_bldsi_reg (operands[3], const0_rtx));
14319	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
14320	  DONE;
14321	}
14322    }
14323  /* ??? expmed doesn't care for non-register predicates.  */
14324  if (! memory_operand (operands[0], VOIDmode)
14325      || ! immediate_operand (operands[1], VOIDmode)
14326      || ! immediate_operand (operands[2], VOIDmode)
14327      || ! general_operand (x, VOIDmode))
14328    FAIL;
14329  /* If this isn't a 16 / 24 / 32 bit field, or if
14330     it doesn't start on a byte boundary, then fail.  */
14331  bitsize = INTVAL (operands[1]);
14332  if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
14333      || (INTVAL (operands[2]) % 8) != 0)
14334    FAIL;
14335
14336  size = bitsize / 8;
14337  orig_address = XEXP (operands[0], 0);
14338  shift_reg = gen_reg_rtx (SImode);
14339  if (CONST_INT_P (x))
14340    {
14341      v = INTVAL (x);
14342      qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
14343    }
14344  else
14345    {
14346      emit_insn (gen_movsi (shift_reg, operands[3]));
14347      qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
14348    }
14349  addr_target = copy_addr_to_reg (plus_constant (Pmode,
14350						 orig_address, size - 1));
14351
14352  operands[0] = replace_equiv_address (operands[0], addr_target);
14353  emit_insn (gen_movqi (operands[0], qi_val));
14354
14355  while (size -= 1)
14356    {
14357      if (CONST_INT_P (x))
14358	qi_val
14359	  = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
14360      else
14361	{
14362	  emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
14363	  qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
14364	}
14365      emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
14366      emit_insn (gen_movqi (operands[0], qi_val));
14367    }
14368
14369  DONE;
14370})
14371
14372(define_insn "movua"
14373  [(set (match_operand:SI 0 "register_operand" "=z")
14374	(unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
14375		   UNSPEC_MOVUA))]
14376  "TARGET_SH4A"
14377  "movua.l	%1,%0"
14378  [(set_attr "type" "movua")])
14379
14380;; We shouldn't need this, but cse replaces increments with references
14381;; to other regs before flow has a chance to create post_inc
14382;; addressing modes, and only postreload's cse_move2add brings the
14383;; increments back to a usable form.
14384(define_peephole2
14385  [(set (match_operand:SI 0 "register_operand" "")
14386	(sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
14387			 (const_int 32) (const_int 0)))
14388   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
14389  "TARGET_SH4A && REGNO (operands[0]) != REGNO (operands[1])"
14390  [(set (match_operand:SI 0 "register_operand" "")
14391	(sign_extract:SI (mem:SI (post_inc:SI
14392				  (match_operand:SI 1 "register_operand" "")))
14393			 (const_int 32) (const_int 0)))]
14394  "")
14395
14396(define_expand "extv"
14397  [(set (match_operand:SI 0 "register_operand" "")
14398	(sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
14399			 (match_operand 2 "const_int_operand" "")
14400			 (match_operand 3 "const_int_operand" "")))]
14401  "TARGET_SH4A || TARGET_SH2A"
14402{
14403  if (TARGET_SH2A && TARGET_BITOPS
14404      && (satisfies_constraint_Sbw (operands[1])
14405	  || satisfies_constraint_Sbv (operands[1]))
14406      && satisfies_constraint_M (operands[2])
14407      && satisfies_constraint_K03 (operands[3]))
14408   {
14409      emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
14410      if (REGNO (operands[0]) != T_REG)
14411	emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
14412      DONE;
14413   }
14414  if (TARGET_SH4A
14415      && INTVAL (operands[2]) == 32
14416      && INTVAL (operands[3]) == 0
14417      && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
14418    {
14419      rtx src = adjust_address (operands[1], BLKmode, 0);
14420      set_mem_size (src, 4);
14421      emit_insn (gen_movua (operands[0], src));
14422      DONE;
14423    }
14424
14425  FAIL;
14426})
14427
14428(define_expand "extzv"
14429  [(set (match_operand:SI 0 "register_operand" "")
14430	(zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
14431			 (match_operand 2 "const_int_operand" "")
14432			 (match_operand 3 "const_int_operand" "")))]
14433  "TARGET_SH4A || TARGET_SH2A"
14434{
14435  if (TARGET_SH2A && TARGET_BITOPS
14436      && (satisfies_constraint_Sbw (operands[1])
14437	  || satisfies_constraint_Sbv (operands[1]))
14438      && satisfies_constraint_M (operands[2])
14439      && satisfies_constraint_K03 (operands[3]))
14440    {
14441      emit_insn (gen_bld_m2a (operands[1], operands[3]));
14442      if (REGNO (operands[0]) != T_REG)
14443	emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
14444      DONE;
14445    }
14446  if (TARGET_SH4A
14447      && INTVAL (operands[2]) == 32
14448      && INTVAL (operands[3]) == 0
14449      && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
14450    {
14451      rtx src = adjust_address (operands[1], BLKmode, 0);
14452      set_mem_size (src, 4);
14453      emit_insn (gen_movua (operands[0], src));
14454      DONE;
14455    }
14456
14457  FAIL;
14458})
14459
14460;; -------------------------------------------------------------------------
14461;; Extract negated single bit and zero extend it.
14462;; Generally we don't care about the exact xor const_int value, as long
14463;; as it contains the extracted bit.  For simplicity, the pattern variations
14464;; that convert everything into the primary '*neg_zero_extract_0' pattern use
14465;; a xor const_int -1 value.
14466
14467(define_insn_and_split "*neg_zero_extract_0"
14468  [(set (reg:SI T_REG)
14469	(zero_extract:SI (xor:QIHISI (match_operand:QIHISI 0 "arith_reg_operand")
14470				     (match_operand 1 "const_int_operand"))
14471			 (const_int 1)
14472			 (match_operand 2 "const_int_operand")))]
14473  "TARGET_SH1 && can_create_pseudo_p ()
14474   && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))"
14475  "#"
14476  "&& 1"
14477  [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 2))
14478		       (const_int 0)))]
14479{
14480  if (INTVAL (operands[2]) == 31 && <MODE>mode == SImode)
14481    {
14482      /* Use cmp/pz to extract bit 31 into the T bit.  */
14483      emit_insn (gen_cmpgesi_t (operands[0], const0_rtx));
14484      DONE;
14485    }
14486
14487  operands[2] = GEN_INT ((1 << INTVAL (operands[2])));
14488  if (GET_MODE (operands[0]) != SImode)
14489    operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
14490})
14491
14492(define_insn_and_split "*neg_zero_extract_1"
14493  [(set (reg:SI T_REG)
14494	(and:SI (not:SI (match_operand:SI 0 "arith_reg_operand"))
14495		(const_int 1)))]
14496  "TARGET_SH1"
14497  "#"
14498  "&& 1"
14499  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14500					(const_int 1) (const_int 0)))])
14501
14502;; x & (1 << n) == 0: 0x00000000 + 1 = 1
14503;; x & (1 << n) != 0: 0xFFFFFFFF + 1 = 0
14504(define_insn_and_split "*neg_zero_extract_2"
14505  [(set (reg:SI T_REG)
14506	(plus:SI (sign_extract:SI (match_operand:QIHISI 0 "arith_reg_operand")
14507				  (const_int 1)
14508				  (match_operand 1 "const_int_operand"))
14509		 (const_int 1)))]
14510  "TARGET_SH1 && can_create_pseudo_p ()"
14511  "#"
14512  "&& 1"
14513  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14514					(const_int 1) (match_dup 1)))])
14515
14516;; (signed)x >> 31 + 1 = (x >= 0) ^ 1
14517(define_insn_and_split "*neg_zero_extract_3"
14518  [(set (reg:SI T_REG)
14519	(plus:SI (ashiftrt:SI (match_operand:SI 0 "arith_reg_operand")
14520			      (const_int 31))
14521		 (const_int 1)))]
14522  "TARGET_SH1 && can_create_pseudo_p ()"
14523  "#"
14524  "&& 1"
14525  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14526					(const_int 1) (const_int 31)))])
14527
14528;; This is required for some bit patterns of DImode subregs.
14529;; It looks like combine gets confused by the DImode right shift and fails
14530;; to simplify things.
14531(define_insn_and_split "*neg_zero_extract_4"
14532  [(set (reg:SI T_REG)
14533	(and:SI (and:SI
14534		  (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand")
14535				       (match_operand 1 "const_int_operand"))
14536			       (match_operand 2 "const_int_operand"))
14537		  (not:SI (ashift:SI (match_operand:SI 3 "arith_reg_operand")
14538				     (match_operand 4 "const_int_operand"))))
14539		(const_int 1)))]
14540  "TARGET_SH1 && can_create_pseudo_p ()
14541   && INTVAL (operands[4]) > 0
14542   && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))"
14543  "#"
14544  "&& 1"
14545  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
14546				    	(const_int 1) (match_dup 2)))])
14547
14548(define_insn_and_split "*neg_zero_extract_5"
14549  [(set (reg:SI T_REG)
14550	(and:SI (not:SI (subreg:SI
14551			  (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand")
14552				       (match_operand 1 "const_int_operand"))
14553			 0))
14554		(const_int 1)))]
14555  "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()
14556   && INTVAL (operands[1]) < 32"
14557  "#"
14558  "&& 1"
14559  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14560					(const_int 1) (match_dup 1)))]
14561{
14562  operands[0] = gen_lowpart (SImode, operands[0]);
14563})
14564
14565(define_insn_and_split "*neg_zero_extract_6"
14566  [(set (reg:SI T_REG)
14567	(and:SI (not:SI (subreg:SI
14568			  (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand")
14569				       (match_operand 1 "const_int_operand"))
14570			 4))
14571		(const_int 1)))]
14572  "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()
14573   && INTVAL (operands[1]) < 32"
14574  "#"
14575  "&& 1"
14576  [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14577					(const_int 1) (match_dup 1)))]
14578{
14579  operands[0] = gen_lowpart (SImode, operands[0]);
14580})
14581
14582;; -------------------------------------------------------------------------
14583;; Extract single bit and zero extend it.
14584;; All patterns store the result bit in the T bit, although that is not
14585;; always possible to do with a single insn and a nott must be appended.
14586;; The trailing nott will be optimized away in most cases.  E.g. if the
14587;; extracted bit is fed into a branch condition, the condition can be
14588;; inverted and the nott will be eliminated.
14589;; FIXME: In cases where the trailing nott can't be eliminated, try to
14590;; convert it into a (not, tst) sequence, which could be better on non-SH2A.
14591
14592;; On SH2A the 'bld<mode>_reg' insn will be used if the bit position fits.
14593(define_insn_and_split "*zero_extract_0"
14594  [(set (reg:SI T_REG)
14595	(zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand")
14596			 (const_int 1)
14597			 (match_operand 1 "const_int_operand")))]
14598  "TARGET_SH1 && can_create_pseudo_p ()
14599   && !(TARGET_SH2A && satisfies_constraint_K03 (operands[1]))"
14600  "#"
14601  "&& 1"
14602  [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 1))
14603			      (const_int 0)))
14604   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]
14605{
14606  if (INTVAL (operands[1]) == 31 && <MODE>mode == SImode)
14607    {
14608      emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
14609      DONE;
14610    }
14611
14612  operands[1] = GEN_INT (1 << INTVAL (operands[1]));
14613  if (GET_MODE (operands[0]) != SImode)
14614    operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
14615})
14616
14617;; This is required for some bit patterns of DImode subregs.
14618;; It looks like combine gets confused by the DImode right shift and fails
14619;; to simplify things.
14620(define_insn_and_split "*zero_extract_1"
14621  [(set (reg:SI T_REG)
14622	(subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand")
14623				    (const_int 1)
14624				    (match_operand 1 "const_int_operand"))
14625	 0))]
14626  "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()
14627   && INTVAL (operands[1]) < 32"
14628  "#"
14629  "&& 1"
14630  [(set (reg:SI T_REG)
14631	(zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))])
14632
14633(define_insn_and_split "*zero_extract_2"
14634  [(set (reg:SI T_REG)
14635	(subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand")
14636				    (const_int 1)
14637				    (match_operand 1 "const_int_operand"))
14638	 4))]
14639  "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()
14640   && INTVAL (operands[1]) < 32"
14641  "#"
14642  "&& 1"
14643  [(set (reg:SI T_REG)
14644	(zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))])
14645
14646(define_insn_and_split "*zero_extract_3"
14647  [(set (match_operand:SI 0 "arith_reg_dest")
14648  	(and:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
14649  			     (match_operand 2 "const_int_operand"))
14650  		(match_operand 3 "const_int_operand")))
14651   (clobber (reg:SI T_REG))]
14652  "TARGET_SH1 && can_create_pseudo_p ()
14653   && exact_log2 (INTVAL (operands[3])) >= 0"
14654  "#"
14655  "&& 1"
14656  [(const_int 0)]
14657{
14658  int rshift = INTVAL (operands[2]);
14659  int lshift = exact_log2 (INTVAL (operands[3]));
14660
14661  rtx tmp = gen_reg_rtx (SImode);
14662  emit_insn (gen_rtx_PARALLEL (VOIDmode,
14663    gen_rtvec (2,
14664      gen_rtx_SET (tmp,
14665		   gen_rtx_ZERO_EXTRACT (SImode, operands[1], const1_rtx,
14666					 GEN_INT (rshift + lshift))),
14667      gen_rtx_CLOBBER (VOIDmode, get_t_reg_rtx ()))));
14668  emit_insn (gen_ashlsi3 (operands[0], tmp, GEN_INT (lshift)));
14669})
14670
14671;; -------------------------------------------------------------------------
14672;; SH2A instructions for bitwise operations.
14673;; FIXME: Convert multiple instruction insns to insn_and_split.
14674;; FIXME: Use iterators to fold at least and,xor,or insn variations.
14675
14676;; Clear a bit in a memory location.
14677(define_insn "bclr_m2a"
14678  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14679	(and:QI
14680	    (not:QI (ashift:QI (const_int 1)
14681			(match_operand:QI 1 "const_int_operand" "K03,K03")))
14682	    (match_dup 0)))]
14683  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14684  "@
14685	bclr.b	%1,%0
14686	bclr.b	%1,@(0,%t0)"
14687[(set_attr "length" "4,4")])
14688
14689(define_insn "bclrmem_m2a"
14690  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14691        (and:QI (match_dup 0)
14692                (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
14693  "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
14694  "@
14695        bclr.b	%W1,%0
14696        bclr.b	%W1,@(0,%t0)"
14697  [(set_attr "length" "4,4")])
14698
14699;; Set a bit in a memory location.
14700(define_insn "bset_m2a"
14701  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14702	(ior:QI
14703	    (ashift:QI (const_int 1)
14704		       (match_operand:QI 1 "const_int_operand" "K03,K03"))
14705	    (match_dup 0)))]
14706  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14707  "@
14708	bset.b	%1,%0
14709	bset.b	%1,@(0,%t0)"
14710  [(set_attr "length" "4,4")])
14711
14712(define_insn "bsetmem_m2a"
14713  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14714	(ior:QI (match_dup 0)
14715		(match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
14716  "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
14717  "@
14718        bset.b	%V1,%0
14719        bset.b	%V1,@(0,%t0)"
14720  [(set_attr "length" "4,4")])
14721
14722;;; Transfer the contents of the T bit to a specified bit of memory.
14723(define_insn "bst_m2a"
14724  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
14725	(if_then_else (eq (reg:SI T_REG) (const_int 0))
14726	    (and:QI
14727		(not:QI (ashift:QI (const_int 1)
14728			(match_operand:QI 1 "const_int_operand" "K03,K03")))
14729		(match_dup 0))
14730	    (ior:QI
14731		(ashift:QI (const_int 1) (match_dup 1))
14732		(match_dup 0))))]
14733  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14734  "@
14735	bst.b	%1,%0
14736	bst.b	%1,@(0,%t0)"
14737  [(set_attr "length" "4")])
14738
14739;; Store a specified bit of memory in the T bit.
14740(define_insn "bld_m2a"
14741  [(set (reg:SI T_REG)
14742	(zero_extract:SI
14743	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
14744	    (const_int 1)
14745	    (match_operand 1 "const_int_operand" "K03,K03")))]
14746  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14747  "@
14748	bld.b	%1,%0
14749	bld.b	%1,@(0,%t0)"
14750  [(set_attr "length" "4,4")])
14751
14752;; Store a specified bit of memory in the T bit.
14753(define_insn "bldsign_m2a"
14754  [(set (reg:SI T_REG)
14755	(sign_extract:SI
14756	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14757	    (const_int 1)
14758	    (match_operand 1 "const_int_operand" "K03,K03")))]
14759  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14760  "@
14761	bld.b	%1,%0
14762	bld.b	%1,@(0,%t0)"
14763  [(set_attr "length" "4,4")])
14764
14765;; Store a specified bit of the LSB 8 bits of a register in the T bit.
14766(define_insn "bld<mode>_reg"
14767  [(set (reg:SI T_REG)
14768	(zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand" "r")
14769			 (const_int 1)
14770			 (match_operand 1 "const_int_operand" "K03")))]
14771  "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
14772  "bld	%1,%0")
14773
14774;; Take logical and of a specified bit of memory with the T bit and
14775;; store its result in the T bit.
14776(define_insn "band_m2a"
14777  [(set (reg:SI T_REG)
14778	(and:SI (reg:SI T_REG)
14779		(zero_extract:SI
14780		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14781		    (const_int 1)
14782		    (match_operand 1 "const_int_operand" "K03,K03"))))]
14783  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14784  "@
14785	band.b	%1,%0
14786	band.b	%1,@(0,%t0)"
14787  [(set_attr "length" "4,4")])
14788
14789(define_insn "bandreg_m2a"
14790  [(set (match_operand:SI 0 "register_operand" "=r,r")
14791	(and:SI (zero_extract:SI
14792		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
14793		    (const_int 1)
14794		    (match_operand 2 "const_int_operand" "K03,K03"))
14795        	(match_operand:SI 3 "register_operand" "r,r")))]
14796  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
14797{
14798  static const char* alt[] =
14799  {
14800       "band.b	%2,%1"		"\n"
14801    "	movt	%0",
14802
14803       "band.b	%2,@(0,%t1)"	"\n"
14804    "	movt	%0"
14805  };
14806  return alt[which_alternative];
14807}
14808  [(set_attr "length" "6,6")])
14809
14810;; Take logical or of a specified bit of memory with the T bit and
14811;; store its result in the T bit.
14812(define_insn "bor_m2a"
14813  [(set (reg:SI T_REG)
14814	(ior:SI (reg:SI T_REG)
14815		(zero_extract:SI
14816		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14817		    (const_int 1)
14818		    (match_operand 1 "const_int_operand" "K03,K03"))))]
14819  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14820  "@
14821	bor.b	%1,%0
14822	bor.b	%1,@(0,%t0)"
14823  [(set_attr "length" "4,4")])
14824
14825(define_insn "borreg_m2a"
14826  [(set (match_operand:SI 0 "register_operand" "=r,r")
14827	(ior:SI (zero_extract:SI
14828		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
14829		    (const_int 1)
14830		    (match_operand 2 "const_int_operand" "K03,K03"))
14831		(match_operand:SI 3 "register_operand" "=r,r")))]
14832  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
14833{
14834  static const char* alt[] =
14835  {
14836       "bor.b	%2,%1"		"\n"
14837    "	movt	%0",
14838
14839       "bor.b	%2,@(0,%t1)"	"\n"
14840    "	movt	%0"
14841  };
14842  return alt[which_alternative];
14843}
14844  [(set_attr "length" "6,6")])
14845
14846;; Take exclusive or of a specified bit of memory with the T bit and
14847;; store its result in the T bit.
14848(define_insn "bxor_m2a"
14849  [(set (reg:SI T_REG)
14850	(xor:SI (reg:SI T_REG)
14851		(zero_extract:SI
14852		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14853		    (const_int 1)
14854		    (match_operand 1 "const_int_operand" "K03,K03"))))]
14855  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14856  "@
14857	bxor.b	%1,%0
14858	bxor.b	%1,@(0,%t0)"
14859  [(set_attr "length" "4,4")])
14860
14861(define_insn "bxorreg_m2a"
14862  [(set (match_operand:SI 0 "register_operand" "=r,r")
14863	(xor:SI (zero_extract:SI
14864		    (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
14865		    (const_int 1)
14866		    (match_operand 2 "const_int_operand" "K03,K03"))
14867		(match_operand:SI 3 "register_operand" "=r,r")))]
14868  "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
14869{
14870  static const char* alt[] =
14871  {
14872       "bxor.b	%2,%1"		"\n"
14873    "	movt	%0",
14874
14875       "bxor.b	%2,@(0,%t1)"	"\n"
14876    "	movt	%0"
14877  };
14878  return alt[which_alternative];
14879}
14880  [(set_attr "length" "6,6")])
14881
14882;; -------------------------------------------------------------------------
14883;; Peepholes
14884;; -------------------------------------------------------------------------
14885;; This matches cases where the bit in a memory location is set.
14886(define_peephole2
14887  [(set (match_operand:SI 0 "register_operand")
14888	(sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
14889   (set (match_dup 0)
14890	(ior:SI (match_dup 0)
14891	(match_operand:SI 2 "const_int_operand")))
14892   (set (match_dup 1)
14893	(match_operand 3 "arith_reg_operand"))]
14894  "TARGET_SH2A && TARGET_BITOPS
14895   && satisfies_constraint_Pso (operands[2])
14896   && REGNO (operands[0]) == REGNO (operands[3])"
14897  [(set (match_dup 1)
14898        (ior:QI (match_dup 1) (match_dup 2)))]
14899  "")
14900
14901;; This matches cases where the bit in a memory location is cleared.
14902(define_peephole2
14903  [(set (match_operand:SI 0 "register_operand")
14904	(sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
14905   (set (match_dup 0)
14906	(and:SI (match_dup 0)
14907	(match_operand:SI 2 "const_int_operand")))
14908   (set (match_dup 1)
14909	(match_operand 3 "arith_reg_operand"))]
14910  "TARGET_SH2A && TARGET_BITOPS
14911   && satisfies_constraint_Psz (operands[2])
14912   && REGNO (operands[0]) == REGNO (operands[3])"
14913  [(set (match_dup 1)
14914        (and:QI (match_dup 1) (match_dup 2)))]
14915  "")
14916
14917;; This matches cases where a stack pointer increment at the start of the
14918;; epilogue combines with a stack slot read loading the return value.
14919(define_peephole
14920  [(set (match_operand:SI 0 "arith_reg_operand" "")
14921	(mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
14922   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
14923  "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
14924  "mov.l	@%1+,%0")
14925
14926;; See the comment on the dt combiner pattern above.
14927(define_peephole
14928  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
14929	(plus:SI (match_dup 0)
14930		 (const_int -1)))
14931   (set (reg:SI T_REG)
14932	(eq:SI (match_dup 0) (const_int 0)))]
14933  "TARGET_SH2"
14934  "dt	%0")
14935
14936;; The following peepholes fold load sequences for which reload was not
14937;; able to generate a displacement addressing move insn.
14938;; This can happen when reload has to transform a move insn 
14939;; without displacement into one with displacement.  Or when reload can't
14940;; fit a displacement into the insn's constraints.  In the latter case, the
14941;; load destination reg remains at r0, which reload compensates by inserting
14942;; another mov insn.
14943
14944;; Fold sequence:
14945;;	mov #54,r0
14946;;	mov.{b,w} @(r0,r15),r0
14947;;	mov r0,r3
14948;; into:
14949;;	mov.{b,w} @(54,r15),r3
14950;;
14951(define_peephole2
14952  [(set (match_operand:SI 0 "arith_reg_dest" "")
14953	(match_operand:SI 1 "const_int_operand" ""))
14954   (set (match_operand:SI 2 "arith_reg_dest" "")
14955	(sign_extend:SI
14956	 (mem:QI (plus:SI (match_dup 0)
14957			  (match_operand:SI 3 "arith_reg_operand" "")))))
14958   (set (match_operand:QI 4 "arith_reg_dest" "")
14959	(match_operand:QI 5 "arith_reg_operand" ""))]
14960  "TARGET_SH2A
14961   && sh_legitimate_index_p (QImode, operands[1], true, true)
14962   && REGNO (operands[2]) == REGNO (operands[5])
14963   && peep2_reg_dead_p (3, operands[5])"
14964  [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
14965  "")
14966
14967(define_peephole2
14968  [(set (match_operand:SI 0 "arith_reg_dest" "")
14969	(match_operand:SI 1 "const_int_operand" ""))
14970   (set (match_operand:SI 2 "arith_reg_dest" "")
14971	(sign_extend:SI
14972	 (mem:HI (plus:SI (match_dup 0)
14973			  (match_operand:SI 3 "arith_reg_operand" "")))))
14974   (set (match_operand:HI 4 "arith_reg_dest" "")
14975	(match_operand:HI 5 "arith_reg_operand" ""))]
14976  "TARGET_SH2A
14977   && sh_legitimate_index_p (HImode, operands[1], true, true)
14978   && REGNO (operands[2]) == REGNO (operands[5])
14979   && peep2_reg_dead_p (3, operands[5])"
14980  [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
14981  "")
14982
14983;; Fold sequence:
14984;;	mov #54,r0
14985;;	mov.{b,w} @(r0,r15),r1
14986;; into:
14987;;	mov.{b,w} @(54,r15),r1
14988;;
14989(define_peephole2
14990  [(set (match_operand:SI 0 "arith_reg_dest" "")
14991	(match_operand:SI 1 "const_int_operand" ""))
14992   (set (match_operand:SI 2 "arith_reg_dest" "")
14993	 (sign_extend:SI
14994	 (mem:QI (plus:SI (match_dup 0)
14995			  (match_operand:SI 3 "arith_reg_operand" "")))))]
14996  "TARGET_SH2A
14997   && sh_legitimate_index_p (QImode, operands[1], true, true)
14998   && (peep2_reg_dead_p (2, operands[0])
14999       || REGNO (operands[0]) == REGNO (operands[2]))"
15000  [(set (match_dup 2)
15001	(sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
15002  "")
15003
15004(define_peephole2
15005  [(set (match_operand:SI 0 "arith_reg_dest" "")
15006	(match_operand:SI 1 "const_int_operand" ""))
15007   (set (match_operand:SI 2 "arith_reg_dest" "")
15008	 (sign_extend:SI
15009	 (mem:HI (plus:SI (match_dup 0)
15010			  (match_operand:SI 3 "arith_reg_operand" "")))))]
15011  "TARGET_SH2A
15012   && sh_legitimate_index_p (HImode, operands[1], true, true)
15013   && (peep2_reg_dead_p (2, operands[0])
15014       || REGNO (operands[0]) == REGNO (operands[2]))"
15015  [(set (match_dup 2)
15016	(sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
15017  "")
15018
15019;; Fold sequence:
15020;;	mov.{b,w} @(r0,r15),r0
15021;;	mov r0,r3
15022;; into:
15023;;	mov.{b,w} @(r0,r15),r3
15024;;
15025;; This can happen when initially a displacement address is picked, where
15026;; the destination reg is fixed to r0, and then the address is transformed
15027;; into 'r0 + reg'.
15028(define_peephole2
15029  [(set (match_operand:SI 0 "arith_reg_dest" "")
15030	(sign_extend:SI
15031	 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
15032			  (match_operand:SI 2 "arith_reg_operand" "")))))
15033   (set (match_operand:QI 3 "arith_reg_dest" "")
15034	(match_operand:QI 4 "arith_reg_operand" ""))]
15035  "TARGET_SH1
15036   && REGNO (operands[0]) == REGNO (operands[4])
15037   && peep2_reg_dead_p (2, operands[0])"
15038  [(set (match_dup 3)
15039	(mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
15040  "")
15041
15042(define_peephole2
15043  [(set (match_operand:SI 0 "arith_reg_dest" "")
15044	(sign_extend:SI
15045	 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
15046			  (match_operand:SI 2 "arith_reg_operand" "")))))
15047   (set (match_operand:HI 3 "arith_reg_dest" "")
15048	(match_operand:HI 4 "arith_reg_operand" ""))]
15049  "TARGET_SH1
15050   && REGNO (operands[0]) == REGNO (operands[4])
15051   && peep2_reg_dead_p (2, operands[0])"
15052  [(set (match_dup 3)
15053	(mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
15054  "")
15055
15056;;	extu.bw	a,b
15057;;	mov	b,c	->	extu.bw	a,c
15058(define_peephole2
15059  [(set (match_operand:SI 0 "arith_reg_dest")
15060	(zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand")))
15061   (set (match_operand:SI 2 "arith_reg_dest")
15062	(match_dup 0))]
15063  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
15064  [(set (match_dup 2) (zero_extend:SI (match_dup 1)))])
15065
15066;;	mov	r0,r1
15067;;	extu.bw	r1,r1   ->	extu.bw	r0,r1
15068(define_peephole2
15069  [(set (match_operand 0 "arith_reg_dest")
15070	(match_operand 1 "arith_reg_operand"))
15071   (set (match_operand:SI 2 "arith_reg_dest")
15072	(zero_extend:SI (match_operand:QIHI 3 "arith_reg_operand")))]
15073  "TARGET_SH1
15074   && REGNO (operands[0]) == REGNO (operands[3])
15075   && (REGNO (operands[0]) == REGNO (operands[2])
15076       || peep2_reg_dead_p (2, operands[0]))"
15077  [(set (match_dup 2) (zero_extend:SI (match_dup 1)))]
15078{
15079  operands[1] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
15080})
15081
15082;;	mov	a,b
15083;;	mov	b,a	->	< nop >
15084(define_peephole2
15085  [(set (match_operand 0 "register_operand")
15086	(match_operand 1 "register_operand"))
15087   (set (match_operand 2 "register_operand")
15088	(match_operand 3 "register_operand"))]
15089  "TARGET_SH1
15090   && REGNO (operands[0]) == REGNO (operands[3])
15091   && REGNO (operands[1]) == REGNO (operands[2])
15092   && peep2_reg_dead_p (2, operands[3])"
15093  [(const_int 0)])
15094
15095;;	mov	#3,r4
15096;;	and	r4,r1	->	mov	r1,r0
15097;;	mov	r1,r0		and	#3,r0
15098(define_code_iterator ANDIORXOR [and ior xor])
15099(define_peephole2
15100  [(set (match_operand:SI 0 "register_operand")
15101	(match_operand:SI 1 "const_logical_operand"))
15102   (set (match_operand:SI 2) (ANDIORXOR:SI (match_dup 2) (match_dup 0)))
15103   (set (reg:SI R0_REG) (match_dup 2))]
15104  "TARGET_SH1
15105   && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])"
15106  [(set (reg:SI R0_REG) (match_dup 2))
15107   (set (reg:SI R0_REG) (ANDIORXOR:SI (reg:SI R0_REG) (match_dup 1)))])
15108
15109;;	...	r2,r0		...	r2,r0
15110;;	or	r1,r0	->	or	r0,r1
15111;;	mov	r0,r1
15112;;	(r0 dead)
15113(define_code_iterator ANDIORXORPLUS [and ior xor plus])
15114(define_peephole2
15115  [(set (match_operand:SI 0 "arith_reg_dest")
15116	(ANDIORXORPLUS:SI (match_dup 0) (match_operand:SI 1 "arith_reg_dest")))
15117   (set (match_dup 1) (match_dup 0))]
15118  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
15119  [(set (match_dup 1) (ANDIORXORPLUS:SI (match_dup 1) (match_dup 0)))])
15120
15121;;	mov	r12,r0
15122;;	add	#-48,r0     ->	add	#-48,r12
15123;;	mov.l	r0,@(4,r10)	mov.l	r12,@(4,r10)
15124;;	(r12 dead)
15125(define_peephole2
15126  [(set (match_operand:SI 0 "arith_reg_dest")
15127	(match_operand:SI 1 "arith_reg_dest"))
15128   (set (match_dup 0) (plus:SI (match_dup 0)
15129			       (match_operand:SI 2 "const_int_operand")))
15130   (set (match_operand:SI 3 "general_movdst_operand") (match_dup 0))]
15131  "TARGET_SH1
15132   && peep2_reg_dead_p (2, operands[1]) && peep2_reg_dead_p (3, operands[0])"
15133  [(const_int 0)]
15134{
15135  emit_insn (gen_addsi3 (operands[1], operands[1], operands[2]));
15136  sh_peephole_emit_move_insn (operands[3], operands[1]);
15137})
15138
15139;;	mov.l	@(r0,r9),r1
15140;;	mov	r1,r0	    ->	mov	@(r0,r9),r0
15141(define_peephole2
15142  [(set (match_operand:SI 0 "arith_reg_dest")
15143	(match_operand:SI 1 "general_movsrc_operand"))
15144   (set (match_operand:SI 2 "arith_reg_dest")
15145	(match_dup 0))]
15146  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
15147  [(const_int 0)]
15148{
15149  sh_peephole_emit_move_insn (operands[2], operands[1]);
15150})
15151
15152(define_peephole2
15153  [(set (match_operand:QIHI 0 "register_operand")
15154	(match_operand:QIHI 1 "movsrc_no_disp_mem_operand"))
15155   (set (match_operand:QIHI 2 "register_operand")
15156	(match_dup 0))]
15157  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
15158  [(const_int 0)]
15159{
15160  sh_peephole_emit_move_insn (operands[2], operands[1]);
15161})
15162
15163(define_peephole2
15164  [(set (match_operand:SI 0 "arith_reg_dest")
15165	(sign_extend:SI (match_operand:QIHI 1 "movsrc_no_disp_mem_operand")))
15166   (set (match_operand:SI 2 "arith_reg_dest")
15167	(match_dup 0))]
15168  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
15169  [(const_int 0)]
15170{
15171  sh_check_add_incdec_notes (emit_insn (gen_extend<mode>si2 (operands[2],
15172		   sh_remove_overlapping_post_inc (operands[2], operands[1]))));
15173})
15174
15175;;	mov.w	@(18,r1),r0 (r0 = HImode)
15176;;	mov	r0,r1       (r0 = r1 = HImode)		mov.w	@(18,r1),r0
15177;;	...	..,r13      (r13 = SImode)	-> 	...	..,r13
15178;;	tst	r1,r13					tst	r0,r13
15179(define_peephole2
15180  [(set (match_operand 0 "arith_reg_dest")
15181	(match_operand 1 "arith_reg_dest"))
15182   (set (match_operand:SI 2 "arith_reg_dest")
15183	(match_operand:SI 3))
15184   (set (reg:SI T_REG)
15185	(eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand")
15186		       (match_operand:SI 5 "arith_reg_operand"))
15187	       (const_int 0)))]
15188  "TARGET_SH1
15189   && peep2_reg_dead_p (3, operands[0])
15190   && !reg_overlap_mentioned_p (operands[0], operands[3])
15191   && (REGNO (operands[0]) == REGNO (operands[4])
15192       || REGNO (operands[0]) == REGNO (operands[5]))
15193   && (REGNO (operands[2]) == REGNO (operands[4])
15194       || REGNO (operands[2]) == REGNO (operands[5]))"
15195  [(const_int 0)]
15196{
15197  if (REGNO (operands[1]) == REGNO (operands[2]))
15198      operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));
15199
15200  // We don't know what the new set insn will be in detail.  Just make sure
15201  // that it still can be recognized and the constraints are satisfied.
15202  rtx_insn* i = emit_insn (gen_rtx_SET (operands[2],
15203		    sh_remove_overlapping_post_inc (operands[2], operands[3])));
15204
15205  recog_data_d prev_recog_data = recog_data;
15206  bool i_invalid = insn_invalid_p (i, false); 
15207  recog_data = prev_recog_data;
15208  
15209  if (i_invalid)
15210    FAIL;
15211    
15212  sh_check_add_incdec_notes (i);
15213
15214  emit_insn (gen_tstsi_t (operands[2],
15215			  gen_rtx_REG (SImode, (REGNO (operands[1])))));
15216})
15217
15218;;	mov.w	@(18,r1),r0 (r0 = HImode)
15219;;	...	..,r13	    (r13 = SImode)		mov.w	@(18,r1),r0
15220;;	mov	r0,r1       (r0 = r1 = HImode)	->	...	..,r13
15221;;	tst	r1,r13					tst	r0,r13
15222(define_peephole2
15223  [(set (match_operand:SI 2 "arith_reg_dest")
15224	(match_operand:SI 3))
15225   (set (match_operand 0 "arith_reg_dest")
15226	(match_operand 1 "arith_reg_operand"))
15227   (set (reg:SI T_REG)
15228	(eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand")
15229		       (match_operand:SI 5 "arith_reg_operand"))
15230	       (const_int 0)))]
15231  "TARGET_SH1
15232   && peep2_reg_dead_p (3, operands[0])
15233   && !reg_overlap_mentioned_p (operands[0], operands[3])
15234   && (REGNO (operands[0]) == REGNO (operands[4])
15235       || REGNO (operands[0]) == REGNO (operands[5]))
15236   && (REGNO (operands[2]) == REGNO (operands[4])
15237       || REGNO (operands[2]) == REGNO (operands[5]))"
15238  [(const_int 0)]
15239{
15240  // We don't know what the new set insn will be in detail.  Just make sure
15241  // that it still can be recognized and the constraints are satisfied.
15242  rtx_insn* i = emit_insn (gen_rtx_SET (operands[2],
15243		    sh_remove_overlapping_post_inc (operands[2], operands[3])));
15244
15245  recog_data_d prev_recog_data = recog_data;
15246  bool i_invalid = insn_invalid_p (i, false); 
15247  recog_data = prev_recog_data;
15248  
15249  if (i_invalid)
15250    FAIL;
15251    
15252  sh_check_add_incdec_notes (i);
15253  
15254  emit_insn (gen_tstsi_t (operands[2],
15255			  gen_rtx_REG (SImode, (REGNO (operands[1])))));
15256})
15257
15258;; This is not a peephole, but it's here because it's actually supposed
15259;; to be one.  It tries to convert a sequence such as
15260;;	movt	r2	->	movt	r2
15261;;	movt	r13		mov	r2,r13
15262;; This gives the schduler a bit more freedom to hoist a following
15263;; comparison insn.  Moreover, it the reg-reg mov insn is MT group which has
15264;; better chances for parallel execution.
15265;; We can do this with a peephole2 pattern, but then the cprop_hardreg
15266;; pass will revert the change.  See also PR 64331.
15267;; Thus do it manually in one of the split passes after register allocation.
15268;; Sometimes the cprop_hardreg pass might also eliminate the reg-reg copy.
15269(define_split
15270  [(set (match_operand:SI 0 "arith_reg_dest")
15271	(match_operand:SI 1 "t_reg_operand"))]
15272  "TARGET_SH1 && reload_completed"
15273  [(set (match_dup 0) (match_dup 1))]
15274{
15275  rtx t_reg = get_t_reg_rtx ();
15276
15277  for (rtx_insn* i = prev_nonnote_insn_bb (curr_insn); i != NULL;
15278       i = prev_nonnote_insn_bb (i))
15279    {
15280      if (!INSN_P (i) || DEBUG_INSN_P (i))
15281	continue;
15282
15283      if (modified_in_p (t_reg, i) || BARRIER_P (i))
15284	FAIL;
15285
15286      if (sh_is_movt_insn (i))
15287	{
15288	  rtx r = sh_movt_set_dest (i);
15289	  if (!modified_between_p (r, i, curr_insn))
15290	    {
15291	      operands[1] = r;
15292	      break;
15293	   }
15294	}
15295    }
15296})
15297
15298(define_peephole
15299  [(set (match_operand:SI 0 "register_operand" "=r")
15300	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
15301   (set (mem:SF (match_dup 0))
15302	(match_operand:SF 2 "general_movsrc_operand" ""))]
15303  "TARGET_SH1 && REGNO (operands[0]) == 0
15304   && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
15305       || (GET_CODE (operands[2]) == SUBREG
15306	   && REGNO (SUBREG_REG (operands[2])) < 16))
15307   && reg_unused_after (operands[0], insn)"
15308  "mov.l	%2,@(%0,%1)")
15309
15310(define_peephole
15311  [(set (match_operand:SI 0 "register_operand" "=r")
15312	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
15313   (set (match_operand:SF 2 "general_movdst_operand" "")
15314
15315	(mem:SF (match_dup 0)))]
15316  "TARGET_SH1 && REGNO (operands[0]) == 0
15317   && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
15318       || (GET_CODE (operands[2]) == SUBREG
15319	   && REGNO (SUBREG_REG (operands[2])) < 16))
15320   && reg_unused_after (operands[0], insn)"
15321  "mov.l	@(%0,%1),%2")
15322
15323(define_peephole
15324  [(set (match_operand:SI 0 "register_operand" "=r")
15325	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
15326   (set (mem:SF (match_dup 0))
15327	(match_operand:SF 2 "general_movsrc_operand" ""))]
15328  "TARGET_SH2E && REGNO (operands[0]) == 0
15329   && ((REG_P (operands[2])
15330        && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
15331       || (GET_CODE (operands[2]) == SUBREG
15332	   && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
15333   && reg_unused_after (operands[0], insn)"
15334  "fmov{.s|}	%2,@(%0,%1)")
15335
15336(define_peephole
15337  [(set (match_operand:SI 0 "register_operand" "=r")
15338	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
15339   (set (match_operand:SF 2 "general_movdst_operand" "")
15340
15341	(mem:SF (match_dup 0)))]
15342  "TARGET_SH2E && REGNO (operands[0]) == 0
15343   && ((REG_P (operands[2])
15344	&& FP_OR_XD_REGISTER_P (REGNO (operands[2])))
15345       || (GET_CODE (operands[2]) == SUBREG
15346	   && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
15347   && reg_unused_after (operands[0], insn)"
15348  "fmov{.s|}	@(%0,%1),%2")
15349
15350;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
15351(define_insn "sp_switch_1"
15352  [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")]
15353    UNSPECV_SP_SWITCH_B))]
15354  "TARGET_SH1"
15355{
15356  return       "mov.l	r0,@-r15"	"\n"
15357	 "	mov.l	%0,r0"		"\n"
15358	 "	mov.l	@r0,r0"		"\n"
15359	 "	mov.l	r15,@-r0"	"\n"
15360	 "	mov	r0,r15";
15361}
15362  [(set_attr "length" "10")])
15363
15364;; Switch back to the original stack for interrupt functions with the
15365;; sp_switch attribute.
15366(define_insn "sp_switch_2"
15367  [(unspec_volatile [(const_int 0)]
15368    UNSPECV_SP_SWITCH_E)]
15369  "TARGET_SH1"
15370{
15371  return       "mov.l	@r15,r15"	"\n"
15372	 "	mov.l	@r15+,r0";
15373}
15374  [(set_attr "length" "4")])
15375
15376;; -------------------------------------------------------------------------
15377;; Integer vector moves
15378;; -------------------------------------------------------------------------
15379
15380(define_expand "movv8qi"
15381  [(set (match_operand:V8QI 0 "general_movdst_operand" "")
15382	(match_operand:V8QI 1 "general_movsrc_operand" ""))]
15383  "TARGET_SHMEDIA"
15384{
15385  prepare_move_operands (operands, V8QImode);
15386})
15387
15388(define_insn "movv8qi_i"
15389  [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
15390	(match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15391  "TARGET_SHMEDIA
15392   && (register_operand (operands[0], V8QImode)
15393       || sh_register_operand (operands[1], V8QImode))"
15394  "@
15395	add	%1, r63, %0
15396	movi	%1, %0
15397	#
15398	ld%M1.q	%m1, %0
15399	st%M0.q	%m0, %N1"
15400  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
15401   (set_attr "length" "4,4,16,4,4")])
15402
15403(define_split
15404  [(set (match_operand:V8QI 0 "arith_reg_dest" "")
15405	(subreg:V8QI (const_int 0) 0))]
15406  "TARGET_SHMEDIA"
15407  [(set (match_dup 0)
15408	(const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
15409			    (const_int 0) (const_int 0) (const_int 0)
15410			    (const_int 0) (const_int 0)]))])
15411
15412(define_split
15413  [(set (match_operand 0 "arith_reg_dest" "")
15414	(match_operand 1 "sh_rep_vec" ""))]
15415  "TARGET_SHMEDIA && reload_completed
15416   && GET_MODE (operands[0]) == GET_MODE (operands[1])
15417   && sh_vector_mode_supported_p (GET_MODE (operands[0]))
15418   && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
15419   && (XVECEXP (operands[1], 0, 0) != const0_rtx
15420       || XVECEXP (operands[1], 0, 1) != const0_rtx)
15421   && (XVECEXP (operands[1], 0, 0) != constm1_rtx
15422       || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
15423  [(set (match_dup 0) (match_dup 1))
15424   (match_dup 2)]
15425{
15426  int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
15427  rtx elt1 = XVECEXP (operands[1], 0, 1);
15428
15429  if (unit_size > 2)
15430    operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
15431  else
15432    {
15433      if (unit_size < 2)
15434	operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
15435      operands[2] = gen_mperm_w0 (operands[0], operands[0]);
15436    }
15437  operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
15438  operands[1] = XVECEXP (operands[1], 0, 0);
15439  if (unit_size < 2)
15440    {
15441      if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
15442	operands[1]
15443	  = GEN_INT (TARGET_LITTLE_ENDIAN
15444		     ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
15445		     : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
15446      else
15447	{
15448	  operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
15449	  operands[1]
15450	    = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
15451	}
15452    }
15453})
15454
15455(define_split
15456  [(set (match_operand 0 "arith_reg_dest" "")
15457	(match_operand 1 "sh_const_vec" ""))]
15458  "TARGET_SHMEDIA && reload_completed
15459   && GET_MODE (operands[0]) == GET_MODE (operands[1])
15460   && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
15461  [(set (match_dup 0) (match_dup 1))]
15462{
15463  rtx v = operands[1];
15464  machine_mode new_mode
15465    = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
15466
15467  operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
15468  operands[1]
15469    = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
15470})
15471
15472(define_expand "movv2hi"
15473  [(set (match_operand:V2HI 0 "general_movdst_operand" "")
15474	(match_operand:V2HI 1 "general_movsrc_operand" ""))]
15475  "TARGET_SHMEDIA"
15476{
15477  prepare_move_operands (operands, V2HImode);
15478})
15479
15480(define_insn "movv2hi_i"
15481  [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
15482	(match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15483  "TARGET_SHMEDIA
15484   && (register_operand (operands[0], V2HImode)
15485       || sh_register_operand (operands[1], V2HImode))"
15486  "@
15487	add.l	%1, r63, %0
15488	movi	%1, %0
15489	#
15490	ld%M1.l	%m1, %0
15491	st%M0.l	%m0, %N1"
15492  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
15493   (set_attr "length" "4,4,16,4,4")
15494   (set (attr "highpart")
15495	(cond [(match_test "sh_contains_memref_p (insn)")
15496	       (const_string "user")]
15497	      (const_string "ignore")))])
15498
15499(define_expand "movv4hi"
15500  [(set (match_operand:V4HI 0 "general_movdst_operand" "")
15501	(match_operand:V4HI 1 "general_movsrc_operand" ""))]
15502  "TARGET_SHMEDIA"
15503{
15504  prepare_move_operands (operands, V4HImode);
15505})
15506
15507(define_insn "movv4hi_i"
15508  [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
15509	(match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15510  "TARGET_SHMEDIA
15511   && (register_operand (operands[0], V4HImode)
15512       || sh_register_operand (operands[1], V4HImode))"
15513  "@
15514	add	%1, r63, %0
15515	movi	%1, %0
15516	#
15517	ld%M1.q	%m1, %0
15518	st%M0.q	%m0, %N1"
15519  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
15520   (set_attr "length" "4,4,16,4,4")
15521   (set_attr "highpart" "depend")])
15522
15523(define_expand "movv2si"
15524  [(set (match_operand:V2SI 0 "general_movdst_operand" "")
15525	(match_operand:V2SI 1 "general_movsrc_operand" ""))]
15526  "TARGET_SHMEDIA"
15527{
15528  prepare_move_operands (operands, V2SImode);
15529})
15530
15531(define_insn "movv2si_i"
15532  [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
15533	(match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15534  "TARGET_SHMEDIA
15535   && (register_operand (operands[0], V2SImode)
15536       || sh_register_operand (operands[1], V2SImode))"
15537  "@
15538	add	%1, r63, %0
15539	#
15540	#
15541	ld%M1.q	%m1, %0
15542	st%M0.q	%m0, %N1"
15543  [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
15544   (set_attr "length" "4,4,16,4,4")
15545   (set_attr "highpart" "depend")])
15546
15547;; -------------------------------------------------------------------------
15548;; Multimedia Intrinsics
15549;; -------------------------------------------------------------------------
15550
15551(define_insn "absv2si2"
15552  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15553	(abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
15554  "TARGET_SHMEDIA"
15555  "mabs.l	%1, %0"
15556  [(set_attr "type" "mcmp_media")
15557   (set_attr "highpart" "depend")])
15558
15559(define_insn "absv4hi2"
15560  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15561	(abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
15562  "TARGET_SHMEDIA"
15563  "mabs.w	%1, %0"
15564  [(set_attr "type" "mcmp_media")
15565   (set_attr "highpart" "depend")])
15566
15567(define_insn "addv2si3"
15568  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15569	(plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
15570		   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15571  "TARGET_SHMEDIA"
15572  "madd.l	%1, %2, %0"
15573  [(set_attr "type" "arith_media")
15574   (set_attr "highpart" "depend")])
15575
15576(define_insn "addv4hi3"
15577  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15578	(plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
15579		   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15580  "TARGET_SHMEDIA"
15581  "madd.w	%1, %2, %0"
15582  [(set_attr "type" "arith_media")
15583   (set_attr "highpart" "depend")])
15584
15585(define_insn_and_split "addv2hi3"
15586  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
15587	(plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
15588		   (match_operand:V2HI 2 "extend_reg_operand" "r")))]
15589  "TARGET_SHMEDIA"
15590  "#"
15591  "TARGET_SHMEDIA"
15592  [(const_int 0)]
15593{
15594  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
15595  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
15596  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
15597  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
15598  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
15599
15600  emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
15601  emit_insn (gen_truncdisi2 (si_dst, di_dst));
15602  DONE;
15603}
15604  [(set_attr "highpart" "must_split")])
15605
15606(define_insn "ssaddv2si3"
15607  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15608	(ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
15609		      (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15610  "TARGET_SHMEDIA"
15611  "madds.l	%1, %2, %0"
15612  [(set_attr "type" "mcmp_media")
15613   (set_attr "highpart" "depend")])
15614
15615(define_insn "usaddv8qi3"
15616  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15617	(us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
15618		      (match_operand:V8QI 2 "arith_reg_operand" "r")))]
15619  "TARGET_SHMEDIA"
15620  "madds.ub	%1, %2, %0"
15621  [(set_attr "type" "mcmp_media")
15622   (set_attr "highpart" "depend")])
15623
15624(define_insn "ssaddv4hi3"
15625  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15626	(ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
15627		      (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15628  "TARGET_SHMEDIA"
15629  "madds.w	%1, %2, %0"
15630  [(set_attr "type" "mcmp_media")
15631   (set_attr "highpart" "depend")])
15632
15633(define_insn "negcmpeqv8qi"
15634  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15635	(neg:V8QI (eq:V8QI
15636		    (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
15637		    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
15638  "TARGET_SHMEDIA"
15639  "mcmpeq.b	%N1, %N2, %0"
15640  [(set_attr "type" "mcmp_media")
15641   (set_attr "highpart" "depend")])
15642
15643(define_insn "negcmpeqv2si"
15644  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15645	(neg:V2SI (eq:V2SI
15646		    (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
15647		    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
15648  "TARGET_SHMEDIA"
15649  "mcmpeq.l	%N1, %N2, %0"
15650  [(set_attr "type" "mcmp_media")
15651   (set_attr "highpart" "depend")])
15652
15653(define_insn "negcmpeqv4hi"
15654  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15655	(neg:V4HI (eq:V4HI
15656		    (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
15657		    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15658  "TARGET_SHMEDIA"
15659  "mcmpeq.w	%N1, %N2, %0"
15660  [(set_attr "type" "mcmp_media")
15661   (set_attr "highpart" "depend")])
15662
15663(define_insn "negcmpgtuv8qi"
15664  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15665	(neg:V8QI (gtu:V8QI
15666		    (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
15667		    (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
15668  "TARGET_SHMEDIA"
15669  "mcmpgt.ub	%N1, %N2, %0"
15670  [(set_attr "type" "mcmp_media")
15671   (set_attr "highpart" "depend")])
15672
15673(define_insn "negcmpgtv2si"
15674  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15675	(neg:V2SI (gt:V2SI
15676		    (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
15677		    (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
15678  "TARGET_SHMEDIA"
15679  "mcmpgt.l	%N1, %N2, %0"
15680  [(set_attr "type" "mcmp_media")
15681   (set_attr "highpart" "depend")])
15682
15683(define_insn "negcmpgtv4hi"
15684  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15685	(neg:V4HI (gt:V4HI
15686		    (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
15687		    (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15688  "TARGET_SHMEDIA"
15689  "mcmpgt.w	%N1, %N2, %0"
15690  [(set_attr "type" "mcmp_media")
15691   (set_attr "highpart" "depend")])
15692
15693(define_insn "mcmv"
15694  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15695	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15696			(match_operand:DI 2 "arith_reg_operand" "r"))
15697		(and:DI (match_operand:DI 3 "arith_reg_operand" "0")
15698			(not:DI (match_dup 2)))))]
15699  "TARGET_SHMEDIA"
15700  "mcmv	%N1, %2, %0"
15701  [(set_attr "type" "arith_media")
15702   (set_attr "highpart" "depend")])
15703
15704(define_insn "mcnvs_lw"
15705  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15706	(vec_concat:V4HI
15707	 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
15708	 (ss_truncate:V2HI
15709	   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
15710  "TARGET_SHMEDIA"
15711  "mcnvs.lw	%N1, %N2, %0"
15712  [(set_attr "type" "mcmp_media")])
15713
15714(define_insn "mcnvs_wb"
15715  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15716	(vec_concat:V8QI
15717	 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
15718	 (ss_truncate:V4QI
15719	   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15720  "TARGET_SHMEDIA"
15721  "mcnvs.wb	%N1, %N2, %0"
15722  [(set_attr "type" "mcmp_media")])
15723
15724(define_insn "mcnvs_wub"
15725  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15726	(vec_concat:V8QI
15727	 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
15728	 (us_truncate:V4QI
15729	   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15730  "TARGET_SHMEDIA"
15731  "mcnvs.wub	%N1, %N2, %0"
15732  [(set_attr "type" "mcmp_media")])
15733
15734(define_insn "mextr_rl"
15735  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15736	(ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15737			     (match_operand:HI 3 "mextr_bit_offset" "i"))
15738		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15739			   (match_operand:HI 4 "mextr_bit_offset" "i"))))]
15740  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
15741{
15742  static char templ[21];
15743  sprintf (templ, "mextr%d	%%N1, %%N2, %%0",
15744	   (int) INTVAL (operands[3]) >> 3);
15745  return templ;
15746}
15747  [(set_attr "type" "arith_media")])
15748
15749(define_insn "*mextr_lr"
15750  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15751	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15752			   (match_operand:HI 3 "mextr_bit_offset" "i"))
15753		(lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15754			     (match_operand:HI 4 "mextr_bit_offset" "i"))))]
15755  "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
15756{
15757  static char templ[21];
15758  sprintf (templ, "mextr%d	%%N2, %%N1, %%0",
15759	   (int) INTVAL (operands[4]) >> 3);
15760  return templ;
15761}
15762  [(set_attr "type" "arith_media")])
15763
15764; mextrN can be modelled with vec_select / vec_concat, but the selection
15765; vector then varies depending on endianness.
15766(define_expand "mextr1"
15767  [(match_operand:DI 0 "arith_reg_dest" "")
15768   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15769   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15770  "TARGET_SHMEDIA"
15771{
15772  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15773			   GEN_INT (1 * 8), GEN_INT (7 * 8)));
15774  DONE;
15775})
15776
15777(define_expand "mextr2"
15778  [(match_operand:DI 0 "arith_reg_dest" "")
15779   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15780   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15781  "TARGET_SHMEDIA"
15782{
15783  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15784			   GEN_INT (2 * 8), GEN_INT (6 * 8)));
15785  DONE;
15786})
15787
15788(define_expand "mextr3"
15789  [(match_operand:DI 0 "arith_reg_dest" "")
15790   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15791   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15792  "TARGET_SHMEDIA"
15793{
15794  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15795			   GEN_INT (3 * 8), GEN_INT (5 * 8)));
15796  DONE;
15797})
15798
15799(define_expand "mextr4"
15800  [(match_operand:DI 0 "arith_reg_dest" "")
15801   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15802   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15803  "TARGET_SHMEDIA"
15804{
15805  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15806			   GEN_INT (4 * 8), GEN_INT (4 * 8)));
15807  DONE;
15808})
15809
15810(define_expand "mextr5"
15811  [(match_operand:DI 0 "arith_reg_dest" "")
15812   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15813   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15814  "TARGET_SHMEDIA"
15815{
15816  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15817			   GEN_INT (5 * 8), GEN_INT (3 * 8)));
15818  DONE;
15819})
15820
15821(define_expand "mextr6"
15822  [(match_operand:DI 0 "arith_reg_dest" "")
15823   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15824   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15825  "TARGET_SHMEDIA"
15826{
15827  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15828			   GEN_INT (6 * 8), GEN_INT (2 * 8)));
15829  DONE;
15830})
15831
15832(define_expand "mextr7"
15833  [(match_operand:DI 0 "arith_reg_dest" "")
15834   (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15835   (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15836  "TARGET_SHMEDIA"
15837{
15838  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15839			   GEN_INT (7 * 8), GEN_INT (1 * 8)));
15840  DONE;
15841})
15842
15843(define_expand "mmacfx_wl"
15844  [(match_operand:V2SI 0 "arith_reg_dest" "")
15845   (match_operand:V2HI 1 "extend_reg_operand" "")
15846   (match_operand:V2HI 2 "extend_reg_operand" "")
15847   (match_operand:V2SI 3 "arith_reg_operand" "")]
15848  "TARGET_SHMEDIA"
15849{
15850  emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
15851			      operands[1], operands[2]));
15852  DONE;
15853})
15854
15855;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
15856;; is depend
15857(define_insn "mmacfx_wl_i"
15858  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15859	(ss_plus:V2SI
15860	 (match_operand:V2SI 1 "arith_reg_operand" "0")
15861	 (ss_truncate:V2SI
15862	  (ashift:V2DI
15863	   (sign_extend:V2DI
15864	    (mult:V2SI
15865	     (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
15866	     (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
15867	   (const_int 1)))))]
15868  "TARGET_SHMEDIA"
15869  "mmacfx.wl	%2, %3, %0"
15870  [(set_attr "type" "mac_media")
15871   (set_attr "highpart" "depend")])
15872
15873(define_expand "mmacnfx_wl"
15874  [(match_operand:V2SI 0 "arith_reg_dest" "")
15875   (match_operand:V2HI 1 "extend_reg_operand" "")
15876   (match_operand:V2HI 2 "extend_reg_operand" "")
15877   (match_operand:V2SI 3 "arith_reg_operand" "")]
15878  "TARGET_SHMEDIA"
15879{
15880  emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
15881			       operands[1], operands[2]));
15882  DONE;
15883})
15884
15885(define_insn "mmacnfx_wl_i"
15886  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15887	(ss_minus:V2SI
15888	 (match_operand:V2SI 1 "arith_reg_operand" "0")
15889	 (ss_truncate:V2SI
15890	  (ashift:V2DI
15891	   (sign_extend:V2DI
15892	    (mult:V2SI
15893	     (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
15894	     (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
15895	   (const_int 1)))))]
15896  "TARGET_SHMEDIA"
15897  "mmacnfx.wl	%2, %3, %0"
15898  [(set_attr "type" "mac_media")
15899   (set_attr "highpart" "depend")])
15900
15901(define_insn "mulv2si3"
15902  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15903	(mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15904		   (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15905  "TARGET_SHMEDIA"
15906  "mmul.l	%1, %2, %0"
15907  [(set_attr "type" "d2mpy_media")
15908   (set_attr "highpart" "depend")])
15909
15910(define_insn "mulv4hi3"
15911  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15912	(mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15913		   (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15914  "TARGET_SHMEDIA"
15915  "mmul.w	%1, %2, %0"
15916  [(set_attr "type" "dmpy_media")
15917   (set_attr "highpart" "depend")])
15918
15919(define_insn "mmulfx_l"
15920  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15921	(ss_truncate:V2SI
15922	 (ashiftrt:V2DI
15923	  (mult:V2DI
15924	   (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
15925	   (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
15926	  (const_int 31))))]
15927  "TARGET_SHMEDIA"
15928  "mmulfx.l	%1, %2, %0"
15929  [(set_attr "type" "d2mpy_media")
15930   (set_attr "highpart" "depend")])
15931
15932(define_insn "mmulfx_w"
15933  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15934	(ss_truncate:V4HI
15935	 (ashiftrt:V4SI
15936	  (mult:V4SI
15937	   (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15938	   (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15939	  (const_int 15))))]
15940  "TARGET_SHMEDIA"
15941  "mmulfx.w	%1, %2, %0"
15942  [(set_attr "type" "dmpy_media")
15943   (set_attr "highpart" "depend")])
15944
15945(define_insn "mmulfxrp_w"
15946  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15947	(ss_truncate:V4HI
15948	 (ashiftrt:V4SI
15949	  (plus:V4SI
15950	   (mult:V4SI
15951	    (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15952	    (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15953	   (const_int 16384))
15954	  (const_int 15))))]
15955  "TARGET_SHMEDIA"
15956  "mmulfxrp.w	%1, %2, %0"
15957  [(set_attr "type" "dmpy_media")
15958   (set_attr "highpart" "depend")])
15959
15960
15961(define_expand "mmulhi_wl"
15962  [(match_operand:V2SI 0 "arith_reg_dest" "")
15963   (match_operand:V4HI 1 "arith_reg_operand" "")
15964   (match_operand:V4HI 2 "arith_reg_operand" "")]
15965  "TARGET_SHMEDIA"
15966{
15967  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
15968	     (operands[0], operands[1], operands[2]));
15969  DONE;
15970})
15971
15972(define_expand "mmullo_wl"
15973  [(match_operand:V2SI 0 "arith_reg_dest" "")
15974   (match_operand:V4HI 1 "arith_reg_operand" "")
15975   (match_operand:V4HI 2 "arith_reg_operand" "")]
15976  "TARGET_SHMEDIA"
15977{
15978  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
15979	     (operands[0], operands[1], operands[2]));
15980  DONE;
15981})
15982
15983(define_insn "mmul23_wl"
15984  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15985	(vec_select:V2SI
15986	 (mult:V4SI
15987	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15988	  (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15989	 (parallel [(const_int 2) (const_int 3)])))]
15990  "TARGET_SHMEDIA"
15991{
15992  return (TARGET_LITTLE_ENDIAN
15993	  ? "mmulhi.wl	%1, %2, %0"
15994	  : "mmullo.wl	%1, %2, %0");
15995}
15996  [(set_attr "type" "dmpy_media")
15997   (set (attr "highpart")
15998	(cond [(eq_attr "endian" "big") (const_string "ignore")]
15999	 (const_string "user")))])
16000
16001(define_insn "mmul01_wl"
16002  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16003	(vec_select:V2SI
16004	 (mult:V4SI
16005	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
16006	  (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
16007	 (parallel [(const_int 0) (const_int 1)])))]
16008  "TARGET_SHMEDIA"
16009{
16010  return (TARGET_LITTLE_ENDIAN
16011	  ? "mmullo.wl	%1, %2, %0"
16012	  : "mmulhi.wl	%1, %2, %0");
16013}
16014  [(set_attr "type" "dmpy_media")
16015   (set (attr "highpart")
16016	(cond [(eq_attr "endian" "little") (const_string "ignore")]
16017	 (const_string "user")))])
16018
16019
16020(define_expand "mmulsum_wq"
16021  [(match_operand:DI 0 "arith_reg_dest" "")
16022   (match_operand:V4HI 1 "arith_reg_operand" "")
16023   (match_operand:V4HI 2 "arith_reg_operand" "")
16024   (match_operand:DI 3 "arith_reg_operand" "")]
16025  "TARGET_SHMEDIA"
16026{
16027  emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
16028			       operands[1], operands[2]));
16029  DONE;
16030})
16031
16032(define_insn "mmulsum_wq_i"
16033  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16034	(plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
16035	 (plus:DI
16036	  (plus:DI
16037	   (vec_select:DI
16038	    (mult:V4DI
16039	     (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
16040	     (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
16041	    (parallel [(const_int 0)]))
16042	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
16043				     (sign_extend:V4DI (match_dup 3)))
16044			  (parallel [(const_int 1)])))
16045	  (plus:DI
16046	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
16047				     (sign_extend:V4DI (match_dup 3)))
16048			  (parallel [(const_int 2)]))
16049	   (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
16050				     (sign_extend:V4DI (match_dup 3)))
16051			  (parallel [(const_int 3)]))))))]
16052  "TARGET_SHMEDIA"
16053  "mmulsum.wq	%2, %3, %0"
16054  [(set_attr "type" "mac_media")])
16055
16056(define_expand "mperm_w"
16057  [(match_operand:V4HI 0 "arith_reg_dest" "=r")
16058   (match_operand:V4HI 1 "arith_reg_operand" "r")
16059   (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
16060  "TARGET_SHMEDIA"
16061{
16062  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
16063	     (operands[0], operands[1], operands[2]));
16064  DONE;
16065})
16066
16067; This use of vec_select isn't exactly correct according to rtl.texi
16068; (because not constant), but it seems a straightforward extension.
16069(define_insn "mperm_w_little"
16070  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16071	(vec_select:V4HI
16072	 (match_operand:V4HI 1 "arith_reg_operand" "r")
16073	 (parallel
16074	  [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
16075			    (const_int 2) (const_int 0))
16076	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
16077	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
16078	   (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
16079  "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
16080  "mperm.w	%1, %N2, %0"
16081  [(set_attr "type" "arith_media")])
16082
16083(define_insn "mperm_w_big"
16084  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16085	(vec_select:V4HI
16086	 (match_operand:V4HI 1 "arith_reg_operand" "r")
16087	 (parallel
16088	  [(zero_extract:QI (not:QI (match_operand:QI 2
16089				     "extend_reg_or_0_operand" "rZ"))
16090			    (const_int 2) (const_int 0))
16091	   (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
16092	   (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
16093	   (zero_extract:QI (not:QI (match_dup 2))
16094			    (const_int 2) (const_int 6))])))]
16095  "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
16096  "mperm.w	%1, %N2, %0"
16097  [(set_attr "type" "arith_media")])
16098
16099(define_insn "mperm_w0"
16100  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16101	(vec_duplicate:V4HI (truncate:HI (match_operand 1
16102					  "trunc_hi_operand" "r"))))]
16103  "TARGET_SHMEDIA"
16104  "mperm.w	%1, r63, %0"
16105  [(set_attr "type" "arith_media")
16106   (set_attr "highpart" "ignore")])
16107
16108(define_expand "msad_ubq"
16109  [(match_operand:DI 0 "arith_reg_dest" "")
16110   (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
16111   (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
16112   (match_operand:DI 3 "arith_reg_operand" "")]
16113  "TARGET_SHMEDIA"
16114{
16115  emit_insn (gen_msad_ubq_i (operands[0], operands[3],
16116			     operands[1], operands[2]));
16117  DONE;
16118})
16119
16120(define_insn "msad_ubq_i"
16121  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16122	(plus:DI
16123	 (plus:DI
16124	  (plus:DI
16125	   (plus:DI
16126	    (match_operand:DI 1 "arith_reg_operand" "0")
16127	    (abs:DI (vec_select:DI
16128		     (minus:V8DI
16129		      (zero_extend:V8DI
16130		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
16131		      (zero_extend:V8DI
16132		       (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
16133		     (parallel [(const_int 0)]))))
16134	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
16135					      (zero_extend:V8DI (match_dup 3)))
16136				  (parallel [(const_int 1)]))))
16137	  (plus:DI
16138	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
16139					      (zero_extend:V8DI (match_dup 3)))
16140				  (parallel [(const_int 2)])))
16141	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
16142					      (zero_extend:V8DI (match_dup 3)))
16143				  (parallel [(const_int 3)])))))
16144	 (plus:DI
16145	  (plus:DI
16146	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
16147					      (zero_extend:V8DI (match_dup 3)))
16148				  (parallel [(const_int 4)])))
16149	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
16150					      (zero_extend:V8DI (match_dup 3)))
16151				  (parallel [(const_int 5)]))))
16152	  (plus:DI
16153	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
16154					      (zero_extend:V8DI (match_dup 3)))
16155				  (parallel [(const_int 6)])))
16156	   (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
16157					      (zero_extend:V8DI (match_dup 3)))
16158				  (parallel [(const_int 7)])))))))]
16159  "TARGET_SHMEDIA"
16160  "msad.ubq	%N2, %N3, %0"
16161  [(set_attr "type" "mac_media")])
16162
16163(define_insn "mshalds_l"
16164  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16165	(ss_truncate:V2SI
16166	 (ashift:V2DI
16167	  (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
16168	  (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
16169		  (const_int 31)))))]
16170  "TARGET_SHMEDIA"
16171  "mshalds.l	%1, %2, %0"
16172  [(set_attr "type" "mcmp_media")
16173   (set_attr "highpart" "depend")])
16174
16175(define_insn "mshalds_w"
16176  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16177	(ss_truncate:V4HI
16178	 (ashift:V4SI
16179	  (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
16180	  (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
16181		  (const_int 15)))))]
16182  "TARGET_SHMEDIA"
16183  "mshalds.w	%1, %2, %0"
16184  [(set_attr "type" "mcmp_media")
16185   (set_attr "highpart" "depend")])
16186
16187(define_insn "ashrv2si3"
16188  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16189	(ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
16190		       (match_operand:DI 2 "arith_reg_operand" "r")))]
16191  "TARGET_SHMEDIA"
16192  "mshard.l	%1, %2, %0"
16193  [(set_attr "type" "arith_media")
16194   (set_attr "highpart" "depend")])
16195
16196(define_insn "ashrv4hi3"
16197  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16198	(ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
16199		       (match_operand:DI 2 "arith_reg_operand" "r")))]
16200  "TARGET_SHMEDIA"
16201  "mshard.w	%1, %2, %0"
16202  [(set_attr "type" "arith_media")
16203   (set_attr "highpart" "depend")])
16204
16205(define_insn "mshards_q"
16206  [(set (match_operand:HI 0 "arith_reg_dest" "=r")
16207	(ss_truncate:HI
16208	 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
16209		      (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
16210  "TARGET_SHMEDIA"
16211  "mshards.q	%1, %N2, %0"
16212  [(set_attr "type" "mcmp_media")])
16213
16214(define_expand "mshfhi_b"
16215  [(match_operand:V8QI 0 "arith_reg_dest" "")
16216   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
16217   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
16218  "TARGET_SHMEDIA"
16219{
16220  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
16221	     (operands[0], operands[1], operands[2]));
16222  DONE;
16223})
16224
16225(define_expand "mshflo_b"
16226  [(match_operand:V8QI 0 "arith_reg_dest" "")
16227   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
16228   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
16229  "TARGET_SHMEDIA"
16230{
16231  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
16232	     (operands[0], operands[1], operands[2]));
16233  DONE;
16234})
16235
16236(define_insn "mshf4_b"
16237  [(set
16238    (match_operand:V8QI 0 "arith_reg_dest" "=r")
16239    (vec_select:V8QI
16240     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
16241		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
16242     (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
16243		(const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
16244  "TARGET_SHMEDIA"
16245{
16246  return (TARGET_LITTLE_ENDIAN
16247	  ? "mshfhi.b	%N1, %N2, %0"
16248	  : "mshflo.b	%N1, %N2, %0");
16249}
16250  [(set_attr "type" "arith_media")
16251   (set (attr "highpart")
16252	(cond [(eq_attr "endian" "big") (const_string "ignore")]
16253	 (const_string "user")))])
16254
16255(define_insn "mshf0_b"
16256  [(set
16257    (match_operand:V8QI 0 "arith_reg_dest" "=r")
16258    (vec_select:V8QI
16259     (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
16260		       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
16261     (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
16262		(const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
16263  "TARGET_SHMEDIA"
16264{
16265  return (TARGET_LITTLE_ENDIAN
16266	  ? "mshflo.b	%N1, %N2, %0"
16267	  : "mshfhi.b	%N1, %N2, %0");
16268}
16269  [(set_attr "type" "arith_media")
16270   (set (attr "highpart")
16271	(cond [(eq_attr "endian" "little") (const_string "ignore")]
16272	 (const_string "user")))])
16273
16274(define_expand "mshfhi_l"
16275  [(match_operand:V2SI 0 "arith_reg_dest" "")
16276   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16277   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
16278  "TARGET_SHMEDIA"
16279{
16280  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
16281	     (operands[0], operands[1], operands[2]));
16282  DONE;
16283})
16284
16285(define_expand "mshflo_l"
16286  [(match_operand:V2SI 0 "arith_reg_dest" "")
16287   (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16288   (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
16289  "TARGET_SHMEDIA"
16290{
16291  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
16292	     (operands[0], operands[1], operands[2]));
16293  DONE;
16294})
16295
16296(define_insn "mshf4_l"
16297  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16298	(vec_select:V2SI
16299	 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16300			  (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
16301	 (parallel [(const_int 1) (const_int 3)])))]
16302  "TARGET_SHMEDIA"
16303{
16304  return (TARGET_LITTLE_ENDIAN
16305	  ? "mshfhi.l	%N1, %N2, %0"
16306	  : "mshflo.l	%N1, %N2, %0");
16307}
16308  [(set_attr "type" "arith_media")
16309   (set (attr "highpart")
16310	(cond [(eq_attr "endian" "big") (const_string "ignore")]
16311	 (const_string "user")))])
16312
16313(define_insn "mshf0_l"
16314  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16315	(vec_select:V2SI
16316	 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16317			  (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
16318	 (parallel [(const_int 0) (const_int 2)])))]
16319  "TARGET_SHMEDIA"
16320{
16321  return (TARGET_LITTLE_ENDIAN
16322	  ? "mshflo.l	%N1, %N2, %0"
16323	  : "mshfhi.l	%N1, %N2, %0");
16324}
16325  [(set_attr "type" "arith_media")
16326   (set (attr "highpart")
16327	(cond [(eq_attr "endian" "little") (const_string "ignore")]
16328	 (const_string "user")))])
16329
16330(define_expand "mshfhi_w"
16331  [(match_operand:V4HI 0 "arith_reg_dest" "")
16332   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16333   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
16334  "TARGET_SHMEDIA"
16335{
16336  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
16337	     (operands[0], operands[1], operands[2]));
16338  DONE;
16339})
16340
16341(define_expand "mshflo_w"
16342  [(match_operand:V4HI 0 "arith_reg_dest" "")
16343   (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16344   (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
16345  "TARGET_SHMEDIA"
16346{
16347  emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
16348	     (operands[0], operands[1], operands[2]));
16349  DONE;
16350})
16351
16352(define_insn "mshf4_w"
16353  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16354	(vec_select:V4HI
16355	 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16356			  (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
16357	 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
16358  "TARGET_SHMEDIA"
16359{
16360  return (TARGET_LITTLE_ENDIAN
16361	  ? "mshfhi.w	%N1, %N2, %0"
16362	  : "mshflo.w	%N1, %N2, %0");
16363}
16364  [(set_attr "type" "arith_media")
16365   (set (attr "highpart")
16366	(cond [(eq_attr "endian" "big") (const_string "ignore")]
16367	 (const_string "user")))])
16368
16369(define_insn "mshf0_w"
16370  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16371	(vec_select:V4HI
16372	 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16373			  (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
16374	 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
16375  "TARGET_SHMEDIA"
16376{
16377  return (TARGET_LITTLE_ENDIAN
16378	  ? "mshflo.w	%N1, %N2, %0"
16379	  : "mshfhi.w	%N1, %N2, %0");
16380}
16381  [(set_attr "type" "arith_media")
16382   (set (attr "highpart")
16383	(cond [(eq_attr "endian" "little") (const_string "ignore")]
16384	 (const_string "user")))])
16385
16386(define_insn "mshflo_w_x"
16387  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16388	(vec_select:V4HI
16389	 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
16390			  (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
16391	 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
16392  "TARGET_SHMEDIA"
16393  "mshflo.w	%N1, %N2, %0"
16394  [(set_attr "type" "arith_media")
16395   (set_attr "highpart" "ignore")])
16396
16397;; These are useful to expand ANDs and as combiner patterns.
16398(define_insn_and_split "mshfhi_l_di"
16399  [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
16400	(ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
16401			     (const_int 32))
16402		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
16403			(const_int -4294967296))))]
16404  "TARGET_SHMEDIA"
16405  "@
16406	mshfhi.l	%N1, %N2, %0
16407	#"
16408  "TARGET_SHMEDIA && reload_completed
16409   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
16410  [(set (match_dup 3) (match_dup 4))
16411   (set (match_dup 5) (match_dup 6))]
16412{
16413  operands[3] = gen_lowpart (SImode, operands[0]);
16414  operands[4] = gen_highpart (SImode, operands[1]);
16415  operands[5] = gen_highpart (SImode, operands[0]);
16416  operands[6] = gen_highpart (SImode, operands[2]);
16417}
16418  [(set_attr "type" "arith_media")])
16419
16420(define_insn "*mshfhi_l_di_rev"
16421  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16422	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16423			(const_int -4294967296))
16424		(lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16425			     (const_int 32))))]
16426  "TARGET_SHMEDIA"
16427  "mshfhi.l	%N2, %N1, %0"
16428  [(set_attr "type" "arith_media")])
16429
16430(define_split
16431  [(set (match_operand:DI 0 "arith_reg_dest" "")
16432	(ior:DI (zero_extend:DI (match_operand:SI 1
16433					      "extend_reg_or_0_operand" ""))
16434		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
16435			(const_int -4294967296))))
16436   (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
16437  "TARGET_SHMEDIA"
16438  [(const_int 0)]
16439{
16440  emit_insn (gen_ashldi3_media (operands[3],
16441				simplify_gen_subreg (DImode, operands[1],
16442						     SImode, 0),
16443				GEN_INT (32)));
16444  emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
16445  DONE;
16446})
16447
16448(define_insn "mshflo_l_di"
16449  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16450	(ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16451			(const_int 4294967295))
16452		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16453			   (const_int 32))))]
16454
16455  "TARGET_SHMEDIA"
16456  "mshflo.l	%N1, %N2, %0"
16457  [(set_attr "type" "arith_media")
16458   (set_attr "highpart" "ignore")])
16459
16460(define_insn "*mshflo_l_di_rev"
16461  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16462	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16463			   (const_int 32))
16464		(and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16465			(const_int 4294967295))))]
16466
16467  "TARGET_SHMEDIA"
16468  "mshflo.l	%N2, %N1, %0"
16469  [(set_attr "type" "arith_media")
16470   (set_attr "highpart" "ignore")])
16471
16472;; Combiner pattern for trampoline initialization.
16473(define_insn_and_split "*double_shori"
16474  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16475	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
16476			   (const_int 32))
16477		(match_operand:DI 2 "const_int_operand" "n")))]
16478  "TARGET_SHMEDIA
16479   && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
16480  "#"
16481  "rtx_equal_p (operands[0], operands[1])"
16482  [(const_int 0)]
16483{
16484  HOST_WIDE_INT v = INTVAL (operands[2]);
16485
16486  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
16487  emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
16488  DONE;
16489}
16490  [(set_attr "highpart" "ignore")])
16491
16492(define_insn "*mshflo_l_di_x"
16493  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16494	(ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
16495				 "rZ"))
16496		(ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16497			   (const_int 32))))]
16498  "TARGET_SHMEDIA"
16499  "mshflo.l	%N1, %N2, %0"
16500  [(set_attr "type" "arith_media")
16501   (set_attr "highpart" "ignore")])
16502
16503(define_insn_and_split "concat_v2sf"
16504  [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
16505;;	(vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
16506	(vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
16507			 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
16508  "TARGET_SHMEDIA"
16509  "@
16510	mshflo.l	%N1, %N2, %0
16511	#
16512	#"
16513  "TARGET_SHMEDIA && reload_completed
16514   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
16515  [(set (match_dup 3) (match_dup 1))
16516   (set (match_dup 4) (match_dup 2))]
16517{
16518  operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
16519  operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
16520}
16521  [(set_attr "type" "arith_media")
16522   (set_attr "highpart" "ignore")])
16523
16524(define_insn "*mshflo_l_di_x_rev"
16525  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16526	(ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16527			   (const_int 32))
16528		(zero_extend:DI
16529		  (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
16530  "TARGET_SHMEDIA"
16531  "mshflo.l	%N2, %N1, %0"
16532  [(set_attr "type" "arith_media")
16533   (set_attr "highpart" "ignore")])
16534
16535(define_insn "ashlv2si3"
16536  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16537	(ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
16538		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16539  "TARGET_SHMEDIA"
16540  "mshlld.l	%1, %2, %0"
16541  [(set_attr "type" "arith_media")
16542   (set_attr "highpart" "depend")])
16543
16544(define_split
16545  [(set (match_operand 0 "any_register_operand" "")
16546	(match_operator 3 "shift_operator"
16547	  [(match_operand 1 "any_register_operand" "")
16548	   (match_operand 2 "shift_count_reg_operand" "")]))]
16549  "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
16550  [(set (match_dup 0) (match_dup 3))]
16551{
16552  rtx count = operands[2];
16553  machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
16554
16555  while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
16556	 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
16557	 || GET_CODE (count) == TRUNCATE)
16558    count = XEXP (count, 0);
16559  inner_mode = GET_MODE (count);
16560  count = simplify_gen_subreg (outer_mode, count, inner_mode,
16561			       subreg_lowpart_offset (outer_mode, inner_mode));
16562  operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
16563				operands[1], count);
16564})
16565
16566(define_insn "ashlv4hi3"
16567  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16568	(ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
16569		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16570  "TARGET_SHMEDIA"
16571  "mshlld.w	%1, %2, %0"
16572  [(set_attr "type" "arith_media")
16573   (set_attr "highpart" "depend")])
16574
16575(define_insn "lshrv2si3"
16576  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16577	(lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
16578		     (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16579  "TARGET_SHMEDIA"
16580  "mshlrd.l	%1, %2, %0"
16581  [(set_attr "type" "arith_media")
16582   (set_attr "highpart" "depend")])
16583
16584(define_insn "lshrv4hi3"
16585  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16586	(lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
16587		       (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16588  "TARGET_SHMEDIA"
16589  "mshlrd.w	%1, %2, %0"
16590  [(set_attr "type" "arith_media")
16591   (set_attr "highpart" "depend")])
16592
16593(define_insn "subv2si3"
16594  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16595	(minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16596		    (match_operand:V2SI 2 "arith_reg_operand" "r")))]
16597  "TARGET_SHMEDIA"
16598  "msub.l	%N1, %2, %0"
16599  [(set_attr "type" "arith_media")
16600   (set_attr "highpart" "depend")])
16601
16602(define_insn "subv4hi3"
16603  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16604	(minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16605		    (match_operand:V4HI 2 "arith_reg_operand" "r")))]
16606  "TARGET_SHMEDIA"
16607  "msub.w	%N1, %2, %0"
16608  [(set_attr "type" "arith_media")
16609   (set_attr "highpart" "depend")])
16610
16611(define_insn_and_split "subv2hi3"
16612  [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
16613	(minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
16614		   (match_operand:V2HI 2 "arith_reg_operand" "r")))]
16615  "TARGET_SHMEDIA"
16616  "#"
16617  "TARGET_SHMEDIA"
16618  [(const_int 0)]
16619{
16620  rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
16621  rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
16622  rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
16623  rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
16624  rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
16625
16626  emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
16627  emit_insn (gen_truncdisi2 (si_dst, di_dst));
16628  DONE;
16629}
16630  [(set_attr "highpart" "must_split")])
16631
16632(define_insn "sssubv2si3"
16633  [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16634	(ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16635		       (match_operand:V2SI 2 "arith_reg_operand" "r")))]
16636  "TARGET_SHMEDIA"
16637  "msubs.l	%N1, %2, %0"
16638  [(set_attr "type" "mcmp_media")
16639   (set_attr "highpart" "depend")])
16640
16641(define_insn "ussubv8qi3"
16642  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
16643	(us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
16644		       (match_operand:V8QI 2 "arith_reg_operand" "r")))]
16645  "TARGET_SHMEDIA"
16646  "msubs.ub	%N1, %2, %0"
16647  [(set_attr "type" "mcmp_media")
16648   (set_attr "highpart" "depend")])
16649
16650(define_insn "sssubv4hi3"
16651  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16652	(ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16653		       (match_operand:V4HI 2 "arith_reg_operand" "r")))]
16654  "TARGET_SHMEDIA"
16655  "msubs.w	%N1, %2, %0"
16656  [(set_attr "type" "mcmp_media")
16657   (set_attr "highpart" "depend")])
16658
16659;; -------------------------------------------------------------------------
16660;; Floating Point Intrinsics
16661;; -------------------------------------------------------------------------
16662
16663(define_insn "fcosa_s"
16664  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16665	(unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
16666		   UNSPEC_FCOSA))]
16667  "TARGET_SHMEDIA"
16668  "fcosa.s	%1, %0"
16669  [(set_attr "type" "atrans_media")])
16670
16671(define_insn "fsina_s"
16672  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16673	(unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
16674		   UNSPEC_FSINA))]
16675  "TARGET_SHMEDIA"
16676  "fsina.s	%1, %0"
16677  [(set_attr "type" "atrans_media")])
16678
16679(define_insn "fipr"
16680  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16681	(plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
16682						    "fp_arith_reg_operand" "f")
16683						   (match_operand:V4SF 2
16684						    "fp_arith_reg_operand" "f"))
16685					 (parallel [(const_int 0)]))
16686			  (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
16687					 (parallel [(const_int 1)])))
16688		 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
16689					 (parallel [(const_int 2)]))
16690			  (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
16691					 (parallel [(const_int 3)])))))]
16692  "TARGET_SHMEDIA"
16693  "fipr.s	%1, %2, %0"
16694  [(set_attr "type" "fparith_media")])
16695
16696(define_insn "fsrra_s"
16697  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16698	(unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
16699		   UNSPEC_FSRRA))]
16700  "TARGET_SHMEDIA"
16701  "fsrra.s	%1, %0"
16702  [(set_attr "type" "atrans_media")])
16703
16704(define_insn "ftrv"
16705  [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
16706	(plus:V4SF
16707	 (plus:V4SF
16708	  (mult:V4SF
16709	   (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
16710			    (parallel [(const_int 0) (const_int 5)
16711				       (const_int 10) (const_int 15)]))
16712	   (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
16713	  (mult:V4SF
16714	   (vec_select:V4SF (match_dup 1)
16715			    (parallel [(const_int 4) (const_int 9)
16716				       (const_int 14) (const_int 3)]))
16717	   (vec_select:V4SF (match_dup 2)
16718			    (parallel [(const_int 1) (const_int 2)
16719				       (const_int 3) (const_int 0)]))))
16720	 (plus:V4SF
16721	  (mult:V4SF
16722	   (vec_select:V4SF (match_dup 1)
16723			    (parallel [(const_int 8) (const_int 13)
16724				       (const_int 2) (const_int 7)]))
16725	   (vec_select:V4SF (match_dup 2)
16726			    (parallel [(const_int 2) (const_int 3)
16727				       (const_int 0) (const_int 1)])))
16728	  (mult:V4SF
16729	   (vec_select:V4SF (match_dup 1)
16730			    (parallel [(const_int 12) (const_int 1)
16731				       (const_int 6) (const_int 11)]))
16732	   (vec_select:V4SF (match_dup 2)
16733			    (parallel [(const_int 3) (const_int 0)
16734				       (const_int 1) (const_int 2)]))))))]
16735  "TARGET_SHMEDIA"
16736  "ftrv.s %1, %2, %0"
16737  [(set_attr "type" "fparith_media")])
16738
16739(define_insn "ldhi_l"
16740  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16741	(zero_extract:SI
16742	 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
16743				  (const_int 3))
16744			  (const_int -3)))
16745	 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
16746	 (const_int 0)))]
16747  "TARGET_SHMEDIA32"
16748  "ldhi.l	%U1, %0"
16749  [(set_attr "type" "load_media")])
16750
16751(define_insn "ldhi_q"
16752  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16753	(zero_extract:DI
16754	 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
16755				  (const_int 7))
16756			  (const_int -7)))
16757	 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
16758	 (const_int 0)))]
16759  "TARGET_SHMEDIA32"
16760  "ldhi.q	%U1, %0"
16761  [(set_attr "type" "load_media")])
16762
16763(define_insn_and_split "*ldhi_q_comb0"
16764  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16765	(zero_extract:DI
16766	 (mem:DI (plus:SI (ior:SI (plus:SI
16767				    (match_operand:SI 1 "register_operand" "r")
16768				    (match_operand:SI 2 "ua_offset" "I06"))
16769				  (const_int 7))
16770			  (const_int -7)))
16771	 (plus:SI (and:SI (match_dup 1) (const_int 7))
16772		  (const_int 1))
16773	 (const_int 0)))]
16774  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
16775  "#"
16776  ""
16777  [(pc)]
16778{
16779  emit_insn (gen_ldhi_q (operands[0],
16780			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16781  DONE;
16782})
16783
16784(define_insn_and_split "*ldhi_q_comb1"
16785  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16786	(zero_extract:DI
16787	 (mem:DI (plus:SI (ior:SI (plus:SI
16788				    (match_operand:SI 1 "register_operand" "r")
16789				    (match_operand:SI 2 "ua_offset" "I06"))
16790				  (const_int 7))
16791			  (const_int -7)))
16792	 (plus:SI (and:SI (plus:SI (match_dup 1)
16793				   (match_operand:SI 3 "ua_offset" "I06"))
16794			  (const_int 7))
16795		  (const_int 1))
16796	 (const_int 0)))]
16797  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
16798   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
16799  "#"
16800  ""
16801  [(pc)]
16802{
16803  emit_insn (gen_ldhi_q (operands[0],
16804			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16805  DONE;
16806})
16807
16808(define_insn "ldlo_l"
16809  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16810	(zero_extract:SI
16811	 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
16812			 (const_int -4)))
16813	 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
16814	 (and:SI (match_dup 1) (const_int 3))))]
16815  "TARGET_SHMEDIA32"
16816  "ldlo.l	%U1, %0"
16817  [(set_attr "type" "load_media")])
16818
16819(define_insn "ldlo_q"
16820  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16821	(zero_extract:DI
16822	 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
16823			 (const_int -8)))
16824	 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
16825	 (and:SI (match_dup 1) (const_int 7))))]
16826  "TARGET_SHMEDIA32"
16827  "ldlo.q	%U1, %0"
16828  [(set_attr "type" "load_media")])
16829
16830(define_insn_and_split "*ldlo_q_comb0"
16831  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16832	(zero_extract:DI
16833	 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
16834				  (match_operand:SI 2 "ua_offset" "I06"))
16835			 (const_int -8)))
16836	 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
16837	 (and:SI (match_dup 1) (const_int 7))))]
16838  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
16839  "#"
16840  ""
16841  [(pc)]
16842{
16843  emit_insn (gen_ldlo_q (operands[0],
16844			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16845  DONE;
16846})
16847
16848(define_insn_and_split "*ldlo_q_comb1"
16849  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16850	(zero_extract:DI
16851	 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
16852				  (match_operand:SI 2 "ua_offset" "I06"))
16853			 (const_int -8)))
16854	 (minus:SI (const_int 8)
16855		   (and:SI (plus:SI (match_dup 1)
16856				    (match_operand:SI 3 "ua_offset" "I06"))
16857			   (const_int 7)))
16858	 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
16859  "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
16860   && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
16861  "#"
16862  ""
16863  [(pc)]
16864{
16865  emit_insn (gen_ldlo_q (operands[0],
16866			 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16867  DONE;
16868})
16869
16870(define_insn "sthi_l"
16871  [(set (zero_extract:SI
16872	 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
16873				  (const_int 3))
16874			  (const_int -3)))
16875	 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
16876	 (const_int 0))
16877	(match_operand:SI 1 "arith_reg_operand" "r"))]
16878  "TARGET_SHMEDIA32"
16879  "sthi.l	%U0, %1"
16880  [(set_attr "type" "ustore_media")])
16881
16882;; All unaligned stores are considered to be 'narrow' because they typically
16883;; operate on less that a quadword, and when they operate on a full quadword,
16884;; the vanilla store high / store low sequence will cause a stall if not
16885;; scheduled apart.
16886(define_insn "sthi_q"
16887  [(set (zero_extract:DI
16888	 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
16889				  (const_int 7))
16890			  (const_int -7)))
16891	 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
16892	 (const_int 0))
16893	(match_operand:DI 1 "arith_reg_operand" "r"))]
16894  "TARGET_SHMEDIA32"
16895  "sthi.q	%U0, %1"
16896  [(set_attr "type" "ustore_media")])
16897
16898(define_insn_and_split "*sthi_q_comb0"
16899  [(set (zero_extract:DI
16900	 (mem:DI (plus:SI (ior:SI (plus:SI
16901				    (match_operand:SI 0 "register_operand" "r")
16902				    (match_operand:SI 1 "ua_offset" "I06"))
16903				  (const_int 7))
16904			  (const_int -7)))
16905	 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
16906	 (const_int 0))
16907	(match_operand:DI 2 "arith_reg_operand" "r"))]
16908  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
16909  "#"
16910  ""
16911  [(pc)]
16912{
16913  emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16914			 operands[2]));
16915  DONE;
16916})
16917
16918(define_insn_and_split "*sthi_q_comb1"
16919  [(set (zero_extract:DI
16920	 (mem:DI (plus:SI (ior:SI (plus:SI
16921				    (match_operand:SI 0 "register_operand" "r")
16922				    (match_operand:SI 1 "ua_offset" "I06"))
16923				  (const_int 7))
16924			  (const_int -7)))
16925	 (plus:SI (and:SI (plus:SI (match_dup 0)
16926				   (match_operand:SI 2 "ua_offset" "I06"))
16927			  (const_int 7))
16928		  (const_int 1))
16929	 (const_int 0))
16930	(match_operand:DI 3 "arith_reg_operand" "r"))]
16931  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
16932   && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
16933  "#"
16934  ""
16935  [(pc)]
16936{
16937  emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16938			 operands[3]));
16939  DONE;
16940})
16941
16942;; This is highpart user because the address is used as full 64 bit.
16943(define_insn "stlo_l"
16944  [(set (zero_extract:SI
16945	 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
16946			 (const_int -4)))
16947	 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
16948	 (and:SI (match_dup 0) (const_int 3)))
16949	(match_operand:SI 1 "arith_reg_operand" "r"))]
16950  "TARGET_SHMEDIA32"
16951  "stlo.l	%U0, %1"
16952  [(set_attr "type" "ustore_media")])
16953
16954(define_insn "stlo_q"
16955  [(set (zero_extract:DI
16956	 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
16957			 (const_int -8)))
16958	 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
16959	 (and:SI (match_dup 0) (const_int 7)))
16960	(match_operand:DI 1 "arith_reg_operand" "r"))]
16961  "TARGET_SHMEDIA32"
16962  "stlo.q	%U0, %1"
16963  [(set_attr "type" "ustore_media")])
16964
16965(define_insn_and_split "*stlo_q_comb0"
16966  [(set (zero_extract:DI
16967	 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
16968				  (match_operand:SI 1 "ua_offset" "I06"))
16969			 (const_int -8)))
16970	 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
16971	 (and:SI (match_dup 0) (const_int 7)))
16972	(match_operand:DI 2 "arith_reg_operand" "r"))]
16973  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
16974  "#"
16975  ""
16976  [(pc)]
16977{
16978  emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16979			 operands[2]));
16980  DONE;
16981})
16982
16983(define_insn_and_split "*stlo_q_comb1"
16984  [(set (zero_extract:DI
16985	 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
16986				  (match_operand:SI 1 "ua_offset" "I06"))
16987			 (const_int -8)))
16988	 (minus:SI (const_int 8)
16989		   (and:SI (plus:SI (match_dup 0)
16990				    (match_operand:SI 2 "ua_offset" "I06"))
16991			   (const_int 7)))
16992	 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
16993	(match_operand:DI 3 "arith_reg_operand" "r"))]
16994  "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
16995  "#"
16996  ""
16997  [(pc)]
16998{
16999  emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
17000			 operands[3]));
17001   DONE;
17002})
17003
17004(define_insn "ldhi_l64"
17005  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
17006	(zero_extract:SI
17007	 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
17008				  (const_int 3))
17009			  (const_int -3)))
17010	 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
17011	 (const_int 0)))]
17012  "TARGET_SHMEDIA64"
17013  "ldhi.l	%U1, %0"
17014  [(set_attr "type" "load_media")])
17015
17016(define_insn "ldhi_q64"
17017  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
17018	(zero_extract:DI
17019	 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
17020				  (const_int 7))
17021			  (const_int -7)))
17022	 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
17023	 (const_int 0)))]
17024  "TARGET_SHMEDIA64"
17025  "ldhi.q	%U1, %0"
17026  [(set_attr "type" "load_media")])
17027
17028(define_insn "ldlo_l64"
17029  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
17030	(zero_extract:SI
17031	 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
17032			 (const_int -4)))
17033	 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
17034	 (and:DI (match_dup 1) (const_int 3))))]
17035  "TARGET_SHMEDIA64"
17036  "ldlo.l	%U1, %0"
17037  [(set_attr "type" "load_media")])
17038
17039(define_insn "ldlo_q64"
17040  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
17041	(zero_extract:DI
17042	 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
17043			 (const_int -8)))
17044	 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
17045	 (and:DI (match_dup 1) (const_int 7))))]
17046  "TARGET_SHMEDIA64"
17047  "ldlo.q	%U1, %0"
17048  [(set_attr "type" "load_media")])
17049
17050(define_insn "sthi_l64"
17051  [(set (zero_extract:SI
17052	 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
17053				  (const_int 3))
17054			  (const_int -3)))
17055	 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
17056	 (const_int 0))
17057	(match_operand:SI 1 "arith_reg_operand" "r"))]
17058  "TARGET_SHMEDIA64"
17059  "sthi.l	%U0, %1"
17060  [(set_attr "type" "ustore_media")])
17061
17062(define_insn "sthi_q64"
17063  [(set (zero_extract:DI
17064	 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
17065				  (const_int 7))
17066			  (const_int -7)))
17067	 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
17068	 (const_int 0))
17069	(match_operand:DI 1 "arith_reg_operand" "r"))]
17070  "TARGET_SHMEDIA64"
17071  "sthi.q	%U0, %1"
17072  [(set_attr "type" "ustore_media")])
17073
17074(define_insn "stlo_l64"
17075  [(set (zero_extract:SI
17076	 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
17077			 (const_int -4)))
17078	 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
17079	 (and:DI (match_dup 0) (const_int 3)))
17080	(match_operand:SI 1 "arith_reg_operand" "r"))]
17081  "TARGET_SHMEDIA64"
17082  "stlo.l	%U0, %1"
17083  [(set_attr "type" "ustore_media")])
17084
17085(define_insn "stlo_q64"
17086  [(set (zero_extract:DI
17087	 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
17088			 (const_int -8)))
17089	 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
17090	 (and:DI (match_dup 0) (const_int 7)))
17091	(match_operand:DI 1 "arith_reg_operand" "r"))]
17092  "TARGET_SHMEDIA64"
17093  "stlo.q	%U0, %1"
17094  [(set_attr "type" "ustore_media")])
17095
17096(define_insn "nsb"
17097  [(set (match_operand:QI 0 "arith_reg_dest" "=r")
17098	(unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
17099		   UNSPEC_NSB))]
17100  "TARGET_SHMEDIA"
17101  "nsb	%1, %0"
17102  [(set_attr "type" "arith_media")])
17103
17104(define_insn "nsbsi"
17105  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
17106	(zero_extend:SI
17107	 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
17108		    UNSPEC_NSB)))]
17109  "TARGET_SHMEDIA"
17110  "nsb	%1, %0"
17111  [(set_attr "type" "arith_media")])
17112
17113(define_insn "nsbdi"
17114  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
17115	(zero_extend:DI
17116	 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
17117		    UNSPEC_NSB)))]
17118  "TARGET_SHMEDIA"
17119  "nsb	%1, %0"
17120  [(set_attr "type" "arith_media")])
17121
17122(define_expand "ffsdi2"
17123  [(set (match_operand:DI 0 "arith_reg_dest" "")
17124	(ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
17125  "TARGET_SHMEDIA"
17126{
17127  rtx scratch = gen_reg_rtx (DImode);
17128  rtx last;
17129
17130  emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
17131  emit_insn (gen_xordi3 (scratch, operands[1], scratch));
17132  emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
17133  emit_insn (gen_nsbdi (scratch, scratch));
17134  emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
17135  emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
17136  last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
17137  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
17138
17139  DONE;
17140})
17141
17142(define_expand "ffssi2"
17143  [(set (match_operand:SI 0 "arith_reg_dest" "")
17144	(ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
17145  "TARGET_SHMEDIA"
17146{
17147  rtx scratch = gen_reg_rtx (SImode);
17148  rtx discratch = gen_reg_rtx (DImode);
17149  rtx last;
17150
17151  emit_insn (gen_adddi3 (discratch,
17152			 simplify_gen_subreg (DImode, operands[1], SImode, 0),
17153			 constm1_rtx));
17154  emit_insn (gen_andcdi3 (discratch,
17155			  simplify_gen_subreg (DImode, operands[1], SImode, 0),
17156			  discratch));
17157  emit_insn (gen_nsbsi (scratch, discratch));
17158  last = emit_insn (gen_subsi3 (operands[0],
17159				force_reg (SImode, GEN_INT (63)), scratch));
17160  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
17161
17162  DONE;
17163})
17164
17165(define_insn "byterev"
17166  [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
17167	(vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
17168			 (parallel [(const_int 7) (const_int 6) (const_int 5)
17169				    (const_int 4) (const_int 3) (const_int 2)
17170				    (const_int 1) (const_int 0)])))]
17171  "TARGET_SHMEDIA"
17172  "byterev	%1, %0"
17173  [(set_attr "type" "arith_media")])
17174
17175;; In user mode, the "pref" instruction will raise a RADDERR exception
17176;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
17177;; implementation of __builtin_prefetch for VxWorks RTPs.
17178(define_expand "prefetch"
17179  [(prefetch (match_operand 0 "address_operand" "")
17180	     (match_operand:SI 1 "const_int_operand" "")
17181	     (match_operand:SI 2 "const_int_operand" ""))]
17182  "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
17183   && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
17184
17185(define_insn "*prefetch"
17186  [(prefetch (match_operand:SI 0 "register_operand" "r")
17187	     (match_operand:SI 1 "const_int_operand" "n")
17188	     (match_operand:SI 2 "const_int_operand" "n"))]
17189  "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
17190  "pref	@%0"
17191  [(set_attr "type" "other")])
17192
17193(define_insn "*prefetch_media"
17194  [(prefetch (match_operand:QI 0 "address_operand" "p")
17195	     (match_operand:SI 1 "const_int_operand" "n")
17196	     (match_operand:SI 2 "const_int_operand" "n"))]
17197  "TARGET_SHMEDIA"
17198{
17199  operands[0] = gen_rtx_MEM (QImode, operands[0]);
17200  output_asm_insn ("ld%M0.b	%m0,r63", operands);
17201  return "";
17202}
17203  [(set_attr "type" "other")])
17204
17205(define_insn "alloco_i"
17206  [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
17207	(unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
17208  "TARGET_SHMEDIA32"
17209{
17210  rtx xops[2];
17211
17212  if (GET_CODE (operands[0]) == PLUS)
17213    {
17214      xops[0] = XEXP (operands[0], 0);
17215      xops[1] = XEXP (operands[0], 1);
17216    }
17217  else
17218    {
17219      xops[0] = operands[0];
17220      xops[1] = const0_rtx;
17221    }
17222  output_asm_insn ("alloco	%0, %1", xops);
17223  return "";
17224}
17225  [(set_attr "type" "other")])
17226
17227(define_split
17228  [(set (match_operand 0 "any_register_operand" "")
17229	(match_operand 1 "" ""))]
17230  "TARGET_SHMEDIA && reload_completed"
17231  [(set (match_dup 0) (match_dup 1))]
17232{
17233  if (!shmedia_cleanup_truncate (operands[1]))
17234    FAIL;
17235})
17236
17237;; -------------------------------------------------------------------------
17238;; Stack Protector Patterns
17239;; -------------------------------------------------------------------------
17240
17241(define_expand "stack_protect_set"
17242  [(set (match_operand 0 "memory_operand" "")
17243	(match_operand 1 "memory_operand" ""))]
17244  ""
17245{
17246  if (TARGET_SHMEDIA)
17247    {
17248      if (TARGET_SHMEDIA64)
17249	emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
17250      else
17251	emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
17252    }
17253  else
17254    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
17255
17256  DONE;
17257})
17258
17259(define_insn "stack_protect_set_si"
17260  [(set (match_operand:SI 0 "memory_operand" "=m")
17261	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
17262   (set (match_scratch:SI 2 "=&r") (const_int 0))]
17263  "!TARGET_SHMEDIA"
17264{
17265  return       "mov.l	%1,%2"	"\n"
17266	 "	mov.l	%2,%0"	"\n"
17267	 "	mov	#0,%2";
17268}
17269  [(set_attr "type" "other")
17270   (set_attr "length" "6")])
17271
17272(define_insn "stack_protect_set_si_media"
17273  [(set (match_operand:SI 0 "memory_operand" "=m")
17274	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
17275   (set (match_scratch:SI 2 "=&r") (const_int 0))]
17276  "TARGET_SHMEDIA"
17277{
17278  return       "ld%M1.l	%m1,%2"	"\n"
17279	 "	st%M0.l	%m0,%2"	"\n"
17280	 "	movi	0,%2";
17281}
17282  [(set_attr "type" "other")
17283   (set_attr "length" "12")])
17284
17285(define_insn "stack_protect_set_di_media"
17286  [(set (match_operand:DI 0 "memory_operand" "=m")
17287	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
17288   (set (match_scratch:DI 2 "=&r") (const_int 0))]
17289  "TARGET_SHMEDIA64"
17290{
17291  return       "ld%M1.q	%m1,%2"	"\n"
17292	 "	st%M0.q	%m0,%2"	"\n"
17293	 "	movi	0,%2";
17294}
17295  [(set_attr "type" "other")
17296   (set_attr "length" "12")])
17297
17298(define_expand "stack_protect_test"
17299  [(match_operand 0 "memory_operand" "")
17300   (match_operand 1 "memory_operand" "")
17301   (match_operand 2 "" "")]
17302  ""
17303{
17304  if (TARGET_SHMEDIA)
17305    {
17306      rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
17307      rtx test;
17308
17309      test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
17310      if (TARGET_SHMEDIA64)
17311	{
17312	  emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
17313						      operands[1]));
17314	  emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
17315	}
17316      else
17317	{
17318	  emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
17319						      operands[1]));
17320	  emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
17321	}
17322    }
17323  else
17324    {
17325      emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
17326      emit_jump_insn (gen_branch_true (operands[2]));
17327    }
17328
17329  DONE;
17330})
17331
17332(define_insn "stack_protect_test_si"
17333  [(set (reg:SI T_REG)
17334	(unspec:SI [(match_operand:SI 0 "memory_operand" "m")
17335		    (match_operand:SI 1 "memory_operand" "m")]
17336		   UNSPEC_SP_TEST))
17337  (set (match_scratch:SI 2 "=&r") (const_int 0))
17338  (set (match_scratch:SI 3 "=&r") (const_int 0))]
17339  "!TARGET_SHMEDIA"
17340{
17341  return       "mov.l	%0,%2"	"\n"
17342	 "	mov.l	%1,%3"	"\n"
17343	 "	cmp/eq	%2,%3"	"\n"
17344	 "	mov	#0,%2"	"\n"
17345	 "	mov	#0,%3";
17346}
17347  [(set_attr "type" "other")
17348   (set_attr "length" "10")])
17349
17350(define_insn "stack_protect_test_si_media"
17351  [(set (match_operand:SI 0 "register_operand" "=&r")
17352	(unspec:SI [(match_operand:SI 1 "memory_operand" "m")
17353		    (match_operand:SI 2 "memory_operand" "m")]
17354		   UNSPEC_SP_TEST))
17355  (set (match_scratch:SI 3 "=&r") (const_int 0))]
17356  "TARGET_SHMEDIA"
17357{
17358  return       "ld%M1.l	%m1,%0"		"\n"
17359	 "	ld%M2.l	%m2,%3"		"\n"
17360	 "	cmpeq	%0,%3,%0"	"\n"
17361	 "	movi	0,%3";
17362}
17363  [(set_attr "type" "other")
17364   (set_attr "length" "16")])
17365
17366(define_insn "stack_protect_test_di_media"
17367  [(set (match_operand:DI 0 "register_operand" "=&r")
17368	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")
17369		    (match_operand:DI 2 "memory_operand" "m")]
17370		   UNSPEC_SP_TEST))
17371  (set (match_scratch:DI 3 "=&r") (const_int 0))]
17372  "TARGET_SHMEDIA64"
17373{
17374  return       "ld%M1.q	%m1,%0"		"\n"
17375	 "	ld%M2.q	%m2,%3"		"\n"
17376	 "	cmpeq	%0,%3,%0"	"\n"
17377	 "	movi	0,%3";
17378}
17379  [(set_attr "type" "other")
17380   (set_attr "length" "16")])
17381
17382;; -------------------------------------------------------------------------
17383;; Atomic operations
17384;; -------------------------------------------------------------------------
17385
17386(include "sync.md")
17387