]> git.ipfire.org Git - people/ms/gcc.git/blame - gcc/config/sh/sh.md
Update copyright years in gcc/
[people/ms/gcc.git] / gcc / config / sh / sh.md
CommitLineData
c8f0269d 1;;- Machine description for Renesas / SuperH SH.
d1e082c2 2;; Copyright (C) 1993-2013 Free Software Foundation, Inc.
51aea58d
JW
3;; Contributed by Steve Chamberlain (sac@cygnus.com).
4;; Improved by Jim Wilson (wilson@cygnus.com).
bc45ade3 5
7ec022b2 6;; This file is part of GCC.
bc45ade3 7
7ec022b2 8;; GCC is free software; you can redistribute it and/or modify
bc45ade3 9;; it under the terms of the GNU General Public License as published by
2f83c7d6 10;; the Free Software Foundation; either version 3, or (at your option)
bc45ade3
SC
11;; any later version.
12
7ec022b2 13;; GCC is distributed in the hope that it will be useful,
bc45ade3
SC
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
2f83c7d6
NC
19;; along with GCC; see the file COPYING3. If not see
20;; <http://www.gnu.org/licenses/>.
bc45ade3 21
bc45ade3 22
d0aae509
RK
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
ffae286a
JW
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
51bd623f
JW
31;; ??? The MAC.W and MAC.L instructions are not supported. There is no
32;; way to generate them.
33
ffae286a
JW
34;; ??? The cmp/str instruction is not supported. Perhaps it can be used
35;; for a str* inline function.
36
4ed4cb9a
JR
37;; BSR is not generated by the compiler proper, but when relaxing, it
38;; generates .uses pseudo-ops that allow linker relaxation to create
39;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c
40
0d7e008e
SC
41;; Special constraints for SH machine description:
42;;
07a45e5c
JW
43;; t -- T
44;; x -- mac
45;; l -- pr
0d7e008e
SC
46;; z -- r0
47;;
48;; Special formats used for outputting SH instructions:
49;;
50;; %. -- print a .s if insn needs delay slot
51aea58d 51;; %@ -- print rte/rts if is/isn't an interrupt function
0d7e008e 52;; %# -- output a nop if there is nothing to put in the delay slot
0d7e008e 53;; %O -- print a constant without the #
51aea58d
JW
54;; %R -- print the lsw reg of a double
55;; %S -- print the msw reg of a double
56;; %T -- print next word of a double REG or MEM
0d7e008e
SC
57;;
58;; Special predicates:
59;;
60;; arith_operand -- operand is valid source for arithmetic op
61;; arith_reg_operand -- operand is valid register for arithmetic op
0d7e008e
SC
62;; general_movdst_operand -- operand is valid move destination
63;; general_movsrc_operand -- operand is valid move source
64;; logical_operand -- operand is valid source for logical op
4773afa4
AO
65
66;; -------------------------------------------------------------------------
67;; Constants
68;; -------------------------------------------------------------------------
69
70(define_constants [
fa5322fa
AO
71 (AP_REG 145)
72 (PR_REG 146)
73 (T_REG 147)
74 (GBR_REG 144)
75 (MACH_REG 148)
76 (MACL_REG 149)
77 (FPUL_REG 150)
78 (RAP_REG 152)
4773afa4 79
fa5322fa 80 (FPSCR_REG 151)
4773afa4
AO
81
82 (PIC_REG 12)
83 (FP_REG 14)
84 (SP_REG 15)
85
fa5322fa
AO
86 (PR_MEDIA_REG 18)
87 (T_MEDIA_REG 19)
88
4773afa4
AO
89 (R0_REG 0)
90 (R1_REG 1)
91 (R2_REG 2)
92 (R3_REG 3)
93 (R4_REG 4)
94 (R5_REG 5)
95 (R6_REG 6)
fa5322fa
AO
96 (R7_REG 7)
97 (R8_REG 8)
98 (R9_REG 9)
99 (R10_REG 10)
9e96203d
R
100 (R20_REG 20)
101 (R21_REG 21)
102 (R22_REG 22)
103 (R23_REG 23)
fa5322fa
AO
104
105 (DR0_REG 64)
106 (DR2_REG 66)
107 (DR4_REG 68)
9e96203d 108 (FR23_REG 87)
4773afa4 109
fa5322fa
AO
110 (TR0_REG 128)
111 (TR1_REG 129)
112 (TR2_REG 130)
4773afa4 113
fa5322fa 114 (XD0_REG 136)
4773afa4
AO
115
116 ;; These are used with unspec.
fa5322fa 117 (UNSPEC_COMPACT_ARGS 0)
4773afa4
AO
118 (UNSPEC_MOVA 1)
119 (UNSPEC_CASESI 2)
fa5322fa 120 (UNSPEC_DATALABEL 3)
4773afa4
AO
121 (UNSPEC_BBR 4)
122 (UNSPEC_SFUNC 5)
123 (UNSPEC_PIC 6)
124 (UNSPEC_GOT 7)
125 (UNSPEC_GOTOFF 8)
126 (UNSPEC_PLT 9)
2d01e445 127 (UNSPEC_CALLER 10)
fa5322fa 128 (UNSPEC_GOTPLT 11)
4773afa4 129 (UNSPEC_ICACHE 12)
c1b92d09
R
130 (UNSPEC_INIT_TRAMP 13)
131 (UNSPEC_FCOSA 14)
132 (UNSPEC_FSRRA 15)
133 (UNSPEC_FSINA 16)
134 (UNSPEC_NSB 17)
135 (UNSPEC_ALLOCO 18)
463f02cd
KK
136 (UNSPEC_TLSGD 20)
137 (UNSPEC_TLSLDM 21)
138 (UNSPEC_TLSIE 22)
139 (UNSPEC_DTPOFF 23)
140 (UNSPEC_GOTTPOFF 24)
141 (UNSPEC_TPOFF 25)
7d73a2ba 142 (UNSPEC_RA 26)
73a4d10b
R
143 (UNSPEC_DIV_INV_M0 30)
144 (UNSPEC_DIV_INV_M1 31)
145 (UNSPEC_DIV_INV_M2 32)
146 (UNSPEC_DIV_INV_M3 33)
147 (UNSPEC_DIV_INV20 34)
62bf45a5 148 (UNSPEC_DIV_INV_TABLE 37)
73a4d10b
R
149 (UNSPEC_ASHIFTRT 35)
150 (UNSPEC_THUNK 36)
af178daf 151 (UNSPEC_CHKADD 38)
50b69666
KK
152 (UNSPEC_SP_SET 40)
153 (UNSPEC_SP_TEST 41)
85144c5c 154 (UNSPEC_MOVUA 42)
4773afa4 155
dc3ba671
RS
156 ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
157 ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
158 (UNSPEC_EXTRACT_S16 43)
159 (UNSPEC_EXTRACT_U16 44)
160
161 ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
162 (UNSPEC_SYMOFF 45)
163
164 ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
165 (UNSPEC_PCREL_SYMOFF 46)
166
4773afa4
AO
167 ;; These are used with unspec_volatile.
168 (UNSPECV_BLOCKAGE 0)
b927e8c7 169 (UNSPECV_ALIGN 1)
4773afa4
AO
170 (UNSPECV_CONST2 2)
171 (UNSPECV_CONST4 4)
172 (UNSPECV_CONST8 6)
b91455de 173 (UNSPECV_WINDOW_END 10)
4773afa4 174 (UNSPECV_CONST_END 11)
6fb5fa3c 175 (UNSPECV_EH_RETURN 12)
7d11d296 176 (UNSPECV_GBR 13)
73774972 177])
4773afa4 178
bc45ade3
SC
179;; -------------------------------------------------------------------------
180;; Attributes
181;; -------------------------------------------------------------------------
182
eeb531d5 183;; Target CPU.
b9654711 184
1245df60 185(define_attr "cpu"
157371cf 186 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
07a45e5c 187 (const (symbol_ref "sh_cpu_attr")))
961c4780 188
1245df60
R
189(define_attr "endian" "big,little"
190 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
191 (const_string "little") (const_string "big"))))
192
d64264ff
R
193;; Indicate if the default fpu mode is single precision.
194(define_attr "fpu_single" "yes,no"
195 (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
196 (const_string "yes") (const_string "no"))))
197
225e4f43
R
198(define_attr "fmovd" "yes,no"
199 (const (if_then_else (symbol_ref "TARGET_FMOVD")
200 (const_string "yes") (const_string "no"))))
2ad65b0e
SC
201;; pipeline model
202(define_attr "pipe_model" "sh1,sh4,sh5media"
203 (const
204 (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
205 (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
206 (const_string "sh1"))))
225e4f43 207
0d7e008e
SC
208;; cbranch conditional branch instructions
209;; jump unconditional jumps
210;; arith ordinary arithmetic
956d6950 211;; arith3 a compound insn that behaves similarly to a sequence of
1245df60
R
212;; three insns of type arith
213;; arith3b like above, but might end with a redirected branch
0d7e008e 214;; load from memory
1245df60 215;; load_si Likewise, SImode variant for general register.
c49439f1 216;; fload Likewise, but load to fp register.
0d7e008e 217;; store to memory
78d310c2 218;; fstore floating point register to memory
c49439f1 219;; move general purpose register to register
3b962ea0 220;; movi8 8-bit immediate to general purpose register
c49439f1 221;; mt_group other sh4 mt instructions
1245df60 222;; fmove register to register, floating point
51bd623f
JW
223;; smpy word precision integer multiply
224;; dmpy longword or doublelongword precision integer multiply
0d7e008e 225;; return rts
ffae286a 226;; pload load of pr reg, which can't be put into delay slot of rts
99e87c10 227;; prset copy register to pr reg, ditto
ffae286a 228;; pstore store of pr reg, which can't be put into delay slot of jsr
99e87c10 229;; prget copy pr to register, ditto
22e1ebf1 230;; pcload pc relative load of constant value
c49439f1 231;; pcfload Likewise, but load to fp register.
1245df60 232;; pcload_si Likewise, SImode variant for general register.
0d7e008e
SC
233;; rte return from exception
234;; sfunc special function call with known used registers
ffae286a 235;; call function call
c1aef54d 236;; fp floating point
78d310c2 237;; fpscr_toggle toggle a bit in the fpscr
c1aef54d 238;; fdiv floating point divide (or square root)
c49439f1
R
239;; gp_fpul move from general purpose register to fpul
240;; fpul_gp move from fpul to general purpose register
241;; mac_gp move from mac[lh] to general purpose register
78d310c2
R
242;; gp_mac move from general purpose register to mac[lh]
243;; mac_mem move from mac[lh] to memory
244;; mem_mac move from memory to mac[lh]
245;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
c49439f1 246;; ftrc_s fix_truncsfsi2_i4
225e4f43 247;; dfdiv double precision floating point divide (or square root)
c49439f1 248;; cwb ic_invalidate_line_i
312209c6
AO
249;; movua SH4a unaligned load
250;; fsrra square root reciprocal approximate
251;; fsca sine and cosine approximate
73774972 252;; tls_load load TLS related address
2ad65b0e
SC
253;; arith_media SHmedia arithmetic, logical, and shift instructions
254;; cbranch_media SHmedia conditional branch instructions
255;; cmp_media SHmedia compare instructions
256;; dfdiv_media SHmedia double precision divide and square root
257;; dfmul_media SHmedia double precision multiply instruction
258;; dfparith_media SHmedia double precision floating point arithmetic
259;; dfpconv_media SHmedia double precision floating point conversions
260;; dmpy_media SHmedia longword multiply
261;; fcmp_media SHmedia floating point compare instructions
262;; fdiv_media SHmedia single precision divide and square root
263;; fload_media SHmedia floating point register load instructions
264;; fmove_media SHmedia floating point register moves (inc. fabs and fneg)
265;; fparith_media SHmedia single precision floating point arithmetic
266;; fpconv_media SHmedia single precision floating point conversions
267;; fstore_media SHmedia floating point register store instructions
268;; gettr_media SHmedia gettr instruction
825db093 269;; invalidate_line_media SHmedia invalidate_line sequence
2ad65b0e
SC
270;; jump_media SHmedia unconditional branch instructions
271;; load_media SHmedia general register load instructions
272;; pt_media SHmedia pt instruction (expanded by assembler)
273;; ptabs_media SHmedia ptabs instruction
274;; store_media SHmedia general register store instructions
275;; mcmp_media SHmedia multimedia compare, absolute, saturating ops
276;; mac_media SHmedia mac-style fixed point operations
3b962ea0 277;; d2mpy_media SHmedia: two 32-bit integer multiplies
73a4d10b 278;; atrans_media SHmedia approximate transcendental functions
2ad65b0e 279;; ustore_media SHmedia unaligned stores
4dff12bf 280;; nil no-op move, will be deleted.
0d7e008e 281
07a45e5c 282(define_attr "type"
78d310c2 283 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other"
bc45ade3
SC
284 (const_string "other"))
285
fae15c93 286;; We define a new attribute namely "insn_class".We use
c49439f1 287;; this for the DFA based pipeline description.
fae15c93
VM
288;;
289;; mt_group SH4 "mt" group instructions.
290;;
c49439f1
R
291;; ex_group SH4 "ex" group instructions.
292;;
293;; ls_group SH4 "ls" group instructions.
fae15c93 294;;
fae15c93
VM
295
296(define_attr "insn_class"
c49439f1
R
297 "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
298 (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
78d310c2
R
299 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
300 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
c49439f1 301 (eq_attr "type" "cbranch,jump") (const_string "br_group")
78d310c2 302 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
c49439f1 303 (const_string "fe_group")
78d310c2 304 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,gp_mac,mac_mem,mem_mac") (const_string "co_group")]
c49439f1
R
305 (const_string "none")))
306;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
307;; so these do not belong in an insn group, although they are modeled
308;; with their own define_insn_reservations.
fae15c93 309
d64264ff
R
310;; Indicate what precision must be selected in fpscr for this insn, if any.
311
312(define_attr "fp_mode" "single,double,none" (const_string "none"))
313
73774972
EC
314;; Indicate if the fpu mode is set by this instruction
315;; "unknown" must have the value as "none" in fp_mode, and means
316;; that the instruction/abi has left the processor in an unknown
317;; state.
318;; "none" means that nothing has changed and no mode is set.
319;; This attribute is only used for the Renesas ABI.
320(define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
321
07a45e5c 322; If a conditional branch destination is within -252..258 bytes away
bc45ade3 323; from the instruction it can be 2 bytes long. Something in the
22e1ebf1 324; range -4090..4100 bytes can be 6 bytes long. All other conditional
1245df60
R
325; branches are initially assumed to be 16 bytes long.
326; In machine_dependent_reorg, we split all branches that are longer than
327; 2 bytes.
bc45ade3 328
536fe39c 329;; The maximum range used for SImode constant pool entries is 1018. A final
33f7f353
JR
330;; instruction can add 8 bytes while only being 4 bytes in size, thus we
331;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch
332;; instruction around the pool table, 2 bytes of alignment before the table,
333;; and 30 bytes of alignment after the table. That gives a maximum total
334;; pool size of 1058 bytes.
335;; Worst case code/pool content size ratio is 1:2 (using asms).
336;; Thus, in the worst case, there is one instruction in front of a maximum
337;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
338;; code. For the last n bytes of code, there are 2n + 36 bytes of pool.
339;; If we have a forward branch, the initial table will be put after the
340;; unconditional branch.
341;;
342;; ??? We could do much better by keeping track of the actual pcloads within
343;; the branch range and in the pcload range in front of the branch range.
344
345;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
346;; inside an le.
347(define_attr "short_cbranch_p" "no,yes"
68ed2b9c 348 (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
33f7f353
JR
349 (const_string "no")
350 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
351 (const_string "yes")
68ed2b9c 352 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
33f7f353
JR
353 (const_string "no")
354 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
355 (const_string "yes")
356 ] (const_string "no")))
357
358(define_attr "med_branch_p" "no,yes"
359 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
360 (const_int 1988))
361 (const_string "yes")
68ed2b9c 362 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
33f7f353
JR
363 (const_string "no")
364 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
365 (const_int 8186))
366 (const_string "yes")
367 ] (const_string "no")))
368
369(define_attr "med_cbranch_p" "no,yes"
370 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
371 (const_int 1986))
372 (const_string "yes")
68ed2b9c 373 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
33f7f353
JR
374 (const_string "no")
375 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
376 (const_int 8184))
377 (const_string "yes")
378 ] (const_string "no")))
379
380(define_attr "braf_branch_p" "no,yes"
68ed2b9c 381 (cond [(match_test "! TARGET_SH2")
33f7f353
JR
382 (const_string "no")
383 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
384 (const_int 20660))
385 (const_string "yes")
68ed2b9c 386 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
33f7f353
JR
387 (const_string "no")
388 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
389 (const_int 65530))
390 (const_string "yes")
391 ] (const_string "no")))
392
393(define_attr "braf_cbranch_p" "no,yes"
68ed2b9c 394 (cond [(match_test "! TARGET_SH2")
33f7f353
JR
395 (const_string "no")
396 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
397 (const_int 20658))
398 (const_string "yes")
68ed2b9c 399 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
33f7f353
JR
400 (const_string "no")
401 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
402 (const_int 65528))
403 (const_string "yes")
404 ] (const_string "no")))
405
22e1ebf1 406; An unconditional jump in the range -4092..4098 can be 2 bytes long.
1245df60
R
407; For wider ranges, we need a combination of a code and a data part.
408; If we can get a scratch register for a long range jump, the code
409; part can be 4 bytes long; otherwise, it must be 8 bytes long.
410; If the jump is in the range -32764..32770, the data part can be 2 bytes
411; long; otherwise, it must be 6 bytes long.
bc45ade3
SC
412
413; All other instructions are two bytes long by default.
414
33f7f353
JR
415;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
416;; but getattrtab doesn't understand this.
07a45e5c 417(define_attr "length" ""
bc45ade3 418 (cond [(eq_attr "type" "cbranch")
33f7f353 419 (cond [(eq_attr "short_cbranch_p" "yes")
1245df60 420 (const_int 2)
33f7f353 421 (eq_attr "med_cbranch_p" "yes")
1245df60 422 (const_int 6)
33f7f353 423 (eq_attr "braf_cbranch_p" "yes")
1245df60 424 (const_int 12)
33f7f353
JR
425;; ??? using pc is not computed transitively.
426 (ne (match_dup 0) (match_dup 0))
427 (const_int 14)
68ed2b9c 428 (match_test "flag_pic")
e6dfd05f 429 (const_int 24)
1245df60 430 ] (const_int 16))
bc45ade3 431 (eq_attr "type" "jump")
33f7f353 432 (cond [(eq_attr "med_branch_p" "yes")
1245df60 433 (const_int 2)
68ed2b9c
RS
434 (and (match_test "prev_nonnote_insn (insn)")
435 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))") (symbol_ref "INSN"))
436 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))") (symbol_ref "code_for_indirect_jump_scratch"))))
c0311627
R
437 (cond [(eq_attr "braf_branch_p" "yes")
438 (const_int 6)
68ed2b9c 439 (not (match_test "flag_pic"))
c0311627 440 (const_int 10)
68ed2b9c 441 (match_test "TARGET_SH2")
c0311627 442 (const_int 10)] (const_int 18))
33f7f353 443 (eq_attr "braf_branch_p" "yes")
1245df60 444 (const_int 10)
33f7f353
JR
445;; ??? using pc is not computed transitively.
446 (ne (match_dup 0) (match_dup 0))
1245df60 447 (const_int 12)
68ed2b9c 448 (match_test "flag_pic")
e6dfd05f 449 (const_int 22)
1245df60 450 ] (const_int 14))
2ad65b0e 451 (eq_attr "type" "pt_media")
68ed2b9c 452 (if_then_else (match_test "TARGET_SHMEDIA64")
fa5322fa 453 (const_int 20) (const_int 12))
73a4d10b 454 (and (eq_attr "type" "jump_media")
68ed2b9c 455 (match_test "TARGET_SH5_CUT2_WORKAROUND"))
73a4d10b 456 (const_int 8)
68ed2b9c 457 ] (if_then_else (match_test "TARGET_SHMEDIA")
fa5322fa
AO
458 (const_int 4)
459 (const_int 2))))
b9654711 460
2de7ffa7 461;; DFA descriptions for the pipelines
2ad65b0e 462
2de7ffa7
PB
463(include "sh1.md")
464(include "shmedia.md")
465(include "sh4.md")
2ad65b0e 466
7fa4bf9b 467(include "iterators.md")
73a4d10b 468(include "predicates.md")
32a7ab3d 469(include "constraints.md")
73a4d10b 470
2de7ffa7 471;; Definitions for filling delay slots
bc45ade3 472
51bd623f
JW
473(define_attr "needs_delay_slot" "yes,no" (const_string "no"))
474
5c7cafa8 475(define_attr "banked" "yes,no"
68ed2b9c 476 (cond [(match_test "sh_loads_bankedreg_p (insn)")
5c7cafa8
CB
477 (const_string "yes")]
478 (const_string "no")))
479
225e4f43
R
480;; ??? This should be (nil) instead of (const_int 0)
481(define_attr "hit_stack" "yes,no"
68ed2b9c 482 (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
225e4f43
R
483 (const_string "no")]
484 (const_string "yes")))
51bd623f
JW
485
486(define_attr "interrupt_function" "no,yes"
552ecbd9 487 (const (symbol_ref "current_function_interrupt")))
51bd623f 488
07a45e5c 489(define_attr "in_delay_slot" "yes,no"
51bd623f 490 (cond [(eq_attr "type" "cbranch") (const_string "no")
1245df60 491 (eq_attr "type" "pcload,pcload_si") (const_string "no")
51bd623f
JW
492 (eq_attr "needs_delay_slot" "yes") (const_string "no")
493 (eq_attr "length" "2") (const_string "yes")
494 ] (const_string "no")))
495
c608a684
R
496(define_attr "cond_delay_slot" "yes,no"
497 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
498 ] (const_string "no")))
499
0603a39d
R
500(define_attr "is_sfunc" ""
501 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
502
2ad65b0e
SC
503(define_attr "is_mac_media" ""
504 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
505
c49439f1
R
506(define_attr "branch_zero" "yes,no"
507 (cond [(eq_attr "type" "!cbranch") (const_string "no")
508 (ne (symbol_ref "(next_active_insn (insn)\
509 == (prev_active_insn\
510 (XEXP (SET_SRC (PATTERN (insn)), 1))))\
511 && get_attr_length (next_active_insn (insn)) == 2")
512 (const_int 0))
513 (const_string "yes")]
514 (const_string "no")))
515
516;; SH4 Double-precision computation with double-precision result -
517;; the two halves are ready at different times.
518(define_attr "dfp_comp" "yes,no"
78d310c2 519 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
c49439f1
R
520 (const_string "no")))
521
522;; Insns for which the latency of a preceding fp insn is decreased by one.
523(define_attr "late_fp_use" "yes,no" (const_string "no"))
524;; And feeding insns for which this relevant.
525(define_attr "any_fp_comp" "yes,no"
78d310c2 526 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
c49439f1
R
527 (const_string "yes")]
528 (const_string "no")))
529
530(define_attr "any_int_load" "yes,no"
531 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
532 (const_string "yes")]
533 (const_string "no")))
534
73a4d10b
R
535(define_attr "highpart" "user, ignore, extend, depend, must_split"
536 (const_string "user"))
537
51bd623f 538(define_delay
0d7e008e 539 (eq_attr "needs_delay_slot" "yes")
b9654711
SC
540 [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
541
ffae286a
JW
542;; Since a normal return (rts) implicitly uses the PR register,
543;; we can't allow PR register loads in an rts delay slot.
fd90d92c
OE
544;; On the SH1* and SH2*, the rte instruction reads the return pc from the
545;; stack, and thus we can't put a pop instruction in its delay slot.
546;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
547;; pop instruction can go in the delay slot, unless it references a banked
548;; register (the register bank is switched by rte).
07a45e5c 549(define_delay
961c4780 550 (eq_attr "type" "return")
07a45e5c 551 [(and (eq_attr "in_delay_slot" "yes")
ffae286a 552 (ior (and (eq_attr "interrupt_function" "no")
99e87c10 553 (eq_attr "type" "!pload,prset"))
ffae286a 554 (and (eq_attr "interrupt_function" "yes")
fd90d92c
OE
555 (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
556 (eq_attr "banked" "no"))))
557 (nil) (nil)])
ffae286a
JW
558
559;; Since a call implicitly uses the PR register, we can't allow
560;; a PR register store in a jsr delay slot.
561
562(define_delay
563 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
564 [(and (eq_attr "in_delay_slot" "yes")
99e87c10 565 (eq_attr "type" "!pstore,prget")) (nil) (nil)])
ffae286a
JW
566
567;; Say that we have annulled true branches, since this gives smaller and
568;; faster code when branches are predicted as not taken.
569
68fe56fc
R
570;; ??? The non-annulled condition should really be "in_delay_slot",
571;; but insns that can be filled in non-annulled get priority over insns
572;; that can only be filled in anulled.
573
07a45e5c
JW
574(define_delay
575 (and (eq_attr "type" "cbranch")
68ed2b9c 576 (match_test "TARGET_SH2"))
3a8699c7 577 ;; SH2e has a hardware bug that pretty much prohibits the use of
073a8998 578 ;; annulled delay slots.
68fe56fc 579 [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
73a4d10b 580 (not (eq_attr "cpu" "sh2e"))) (nil)])
bc45ade3
SC
581\f
582;; -------------------------------------------------------------------------
583;; SImode signed integer comparisons
584;; -------------------------------------------------------------------------
585
6ff9d294
OE
586;; Various patterns to generate the TST #imm, R0 instruction.
587;; Although this adds some pressure on the R0 register, it can potentially
588;; result in faster code, even if the operand has to be moved to R0 first.
589;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group
590;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0
591;; is an EX group instruction but still can be executed in parallel with the
592;; MT group MOV Rm, Rn instruction.
593
594;; Usual TST #imm, R0 patterns for SI, HI and QI
595;; This is usually used for bit patterns other than contiguous bits
596;; and single bits.
597
598(define_insn "tstsi_t"
4773afa4 599 [(set (reg:SI T_REG)
6ff9d294 600 (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
bcd9e00d 601 (match_operand:SI 1 "logical_operand" "K08,r"))
51bd623f 602 (const_int 0)))]
fa5322fa 603 "TARGET_SH1"
fae15c93 604 "tst %1,%0"
c49439f1 605 [(set_attr "type" "mt_group")])
0d7e008e 606
6ff9d294
OE
607(define_insn "tsthi_t"
608 [(set (reg:SI T_REG)
609 (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
610 (match_operand 1 "const_int_operand")) 0)
611 (const_int 0)))]
612 "TARGET_SH1
613 && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
614 "tst %1,%0"
615 [(set_attr "type" "mt_group")])
616
617(define_insn "tstqi_t"
618 [(set (reg:SI T_REG)
619 (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
620 (match_operand 1 "const_int_operand")) 0)
621 (const_int 0)))]
622 "TARGET_SH1
623 && (CONST_OK_FOR_K08 (INTVAL (operands[1]))
624 || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
625{
626 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
627 return "tst %1,%0";
628}
629 [(set_attr "type" "mt_group")])
630
631;; Test low QI subreg against zero.
073a8998 632;; This avoids unnecessary zero extension before the test.
6ff9d294 633
197ddd06 634(define_insn "*tstqi_t_zero"
6ff9d294
OE
635 [(set (reg:SI T_REG)
636 (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
637 "TARGET_SH1"
638 "tst #255,%0"
639 [(set_attr "type" "mt_group")])
640
197ddd06
OE
641;; This pattern might be risky because it also tests the upper bits and not
642;; only the subreg. However, it seems that combine will get to this only
643;; when testing sign/zero extended values. In this case the extended upper
644;; bits do not matter.
645(define_insn "*tst<mode>_t_zero"
646 [(set (reg:SI T_REG)
647 (eq:SI
648 (subreg:QIHI
649 (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
650 (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_le>)
651 (const_int 0)))]
652 "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
653 "tst %0,%1"
654 [(set_attr "type" "mt_group")])
655
656(define_insn "*tst<mode>_t_zero"
657 [(set (reg:SI T_REG)
658 (eq:SI
659 (subreg:QIHI
660 (and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
661 (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_be>)
662 (const_int 0)))]
663 "TARGET_SH1 && !TARGET_LITTLE_ENDIAN"
664 "tst %0,%1"
665 [(set_attr "type" "mt_group")])
666
6ff9d294
OE
667;; Extract LSB, negate and store in T bit.
668
669(define_insn "tstsi_t_and_not"
670 [(set (reg:SI T_REG)
671 (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
672 (const_int 1)))]
673 "TARGET_SH1"
674 "tst #1,%0"
675 [(set_attr "type" "mt_group")])
676
677;; Extract contiguous bits and compare them against zero.
678
679(define_insn "tstsi_t_zero_extract_eq"
680 [(set (reg:SI T_REG)
681 (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z")
682 (match_operand:SI 1 "const_int_operand")
683 (match_operand:SI 2 "const_int_operand"))
684 (const_int 0)))]
685 "TARGET_SH1
686 && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
687{
688 operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
689 return "tst %1,%0";
690}
691 [(set_attr "type" "mt_group")])
692
693;; This split is required when testing bits in a QI subreg.
694
695(define_split
696 [(set (reg:SI T_REG)
697 (eq:SI (if_then_else:SI (zero_extract:SI
698 (match_operand 0 "logical_operand" "")
699 (match_operand 1 "const_int_operand")
700 (match_operand 2 "const_int_operand"))
701 (match_operand 3 "const_int_operand")
702 (const_int 0))
703 (const_int 0)))]
704 "TARGET_SH1
705 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
706 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
707 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
708 (const_int 0)))]
6ff9d294
OE
709{
710 if (GET_MODE (operands[0]) == QImode)
711 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
d9241861 712})
6ff9d294
OE
713
714;; Extract single bit, negate and store it in the T bit.
715;; Not used for SH4A.
716
717(define_insn "tstsi_t_zero_extract_xor"
718 [(set (reg:SI T_REG)
719 (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
720 (match_operand:SI 3 "const_int_operand"))
721 (match_operand:SI 1 "const_int_operand")
722 (match_operand:SI 2 "const_int_operand")))]
723 "TARGET_SH1
724 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
725 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
726 "tst %3,%0"
727 [(set_attr "type" "mt_group")])
728
729;; Extract single bit, negate and store it in the T bit.
730;; Used for SH4A little endian.
731
732(define_insn "tstsi_t_zero_extract_subreg_xor_little"
733 [(set (reg:SI T_REG)
734 (zero_extract:SI
735 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
736 (match_operand:SI 3 "const_int_operand")) 0)
737 (match_operand:SI 1 "const_int_operand")
738 (match_operand:SI 2 "const_int_operand")))]
739 "TARGET_SH1 && TARGET_LITTLE_ENDIAN
740 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
741 == (INTVAL (operands[3]) & 255)
742 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
743{
744 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
745 return "tst %3,%0";
746}
747 [(set_attr "type" "mt_group")])
748
749;; Extract single bit, negate and store it in the T bit.
750;; Used for SH4A big endian.
751
752(define_insn "tstsi_t_zero_extract_subreg_xor_big"
753 [(set (reg:SI T_REG)
754 (zero_extract:SI
755 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
756 (match_operand:SI 3 "const_int_operand")) 3)
757 (match_operand:SI 1 "const_int_operand")
758 (match_operand:SI 2 "const_int_operand")))]
759 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
760 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
761 == (INTVAL (operands[3]) & 255)
762 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
763{
764 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
765 return "tst %3,%0";
766}
767 [(set_attr "type" "mt_group")])
768
0d7e008e 769(define_insn "cmpeqsi_t"
4773afa4
AO
770 [(set (reg:SI T_REG)
771 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
735cb76e 772 (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
fa5322fa 773 "TARGET_SH1"
0d7e008e 774 "@
51bd623f 775 tst %0,%0
0d7e008e 776 cmp/eq %1,%0
fae15c93 777 cmp/eq %1,%0"
c49439f1 778 [(set_attr "type" "mt_group")])
bc45ade3 779
eb11dba2
OE
780;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
781;; pattern by itself. What this actually does is:
782;; x == 0: (1 >> 0-0) & 1 = 1
783;; x != 0: (1 >> 0-x) & 1 = 0
784;; Without this the test pr51244-8.c fails on SH2A and SH4A.
785(define_insn_and_split "*cmpeqsi_t"
786 [(set (reg:SI T_REG)
787 (and:SI (lshiftrt:SI
788 (const_int 1)
789 (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
790 (const_int 1)))]
791 "TARGET_SH1"
792 "#"
793 "&& 1"
794 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
795
bc45ade3 796(define_insn "cmpgtsi_t"
4773afa4
AO
797 [(set (reg:SI T_REG)
798 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
eb11dba2 799 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
fa5322fa 800 "TARGET_SH1"
0d7e008e 801 "@
eb11dba2
OE
802 cmp/pl %0
803 cmp/gt %1,%0"
c49439f1 804 [(set_attr "type" "mt_group")])
bc45ade3
SC
805
806(define_insn "cmpgesi_t"
4773afa4
AO
807 [(set (reg:SI T_REG)
808 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
eb11dba2 809 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
fa5322fa 810 "TARGET_SH1"
0d7e008e 811 "@
eb11dba2
OE
812 cmp/pz %0
813 cmp/ge %1,%0"
c49439f1 814 [(set_attr "type" "mt_group")])
fae15c93 815
ef812306
OE
816;; FIXME: This is actually wrong. There is no way to literally move a
817;; general reg to t reg. Luckily, it seems that this pattern will be only
818;; used when the general reg is known be either '0' or '1' during combine.
819;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
820;; Due to interactions with other patterns, combine fails to pick the latter
821;; and invert the dependent logic.
822(define_insn "*negtstsi"
823 [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
824 "TARGET_SH1"
825 "cmp/pl %0"
826 [(set_attr "type" "mt_group")])
827
669d4d70
OE
828;; Some integer sign comparison patterns can be realized with the div0s insn.
829;; div0s Rm,Rn T = (Rm >> 31) ^ (Rn >> 31)
830(define_insn "cmp_div0s_0"
831 [(set (reg:SI T_REG)
832 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
833 (match_operand:SI 1 "arith_reg_operand" "r"))
834 (const_int 31)))]
835 "TARGET_SH1"
836 "div0s %0,%1"
837 [(set_attr "type" "arith")])
838
839(define_insn "cmp_div0s_1"
840 [(set (reg:SI T_REG)
841 (lt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
842 (match_operand:SI 1 "arith_reg_operand" "r"))
843 (const_int 0)))]
844 "TARGET_SH1"
845 "div0s %0,%1"
846 [(set_attr "type" "arith")])
847
848(define_insn_and_split "*cmp_div0s_0"
849 [(set (match_operand:SI 0 "arith_reg_dest" "")
850 (lshiftrt:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
851 (match_operand:SI 2 "arith_reg_operand" ""))
852 (const_int 31)))
853 (clobber (reg:SI T_REG))]
854 "TARGET_SH1"
855 "#"
856 "&& 1"
857 [(set (reg:SI T_REG)
858 (lshiftrt:SI (xor:SI (match_dup 1) (match_dup 2)) (const_int 31)))
859 (set (match_dup 0) (reg:SI T_REG))])
860
861(define_insn_and_split "*cmp_div0s_1"
862 [(set (match_operand:SI 0 "arith_reg_dest" "")
693445c9
OE
863 (ge:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
864 (match_operand:SI 2 "arith_reg_operand" ""))
865 (const_int 0)))
669d4d70
OE
866 (clobber (reg:SI T_REG))]
867 "TARGET_SH1"
868 "#"
869 "&& can_create_pseudo_p ()"
870 [(const_int 0)]
871;; We have to go through the movnegt expander here which will handle the
872;; SH2A vs non-SH2A cases.
873{
874 emit_insn (gen_cmp_div0s_1 (operands[1], operands[2]));
875 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
876 DONE;
877})
878
879(define_insn_and_split "*cmp_div0s_1"
880 [(set (reg:SI T_REG)
693445c9
OE
881 (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
882 (match_operand:SI 1 "arith_reg_operand" ""))
883 (const_int 0)))]
669d4d70
OE
884 "TARGET_SH1"
885 "#"
886 "&& can_create_pseudo_p ()"
887 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
888 (const_int 0)))
889 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
890
891
78d310c2
R
892;; -------------------------------------------------------------------------
893;; SImode compare and branch
894;; -------------------------------------------------------------------------
895
896(define_expand "cbranchsi4"
897 [(set (pc)
898 (if_then_else (match_operator 0 "comparison_operator"
899 [(match_operand:SI 1 "arith_operand" "")
900 (match_operand:SI 2 "arith_operand" "")])
901 (label_ref (match_operand 3 "" ""))
902 (pc)))
903 (clobber (reg:SI T_REG))]
f90b7a5a 904 ""
d9241861
OE
905{
906 if (TARGET_SHMEDIA)
907 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
908 operands[2], operands[3]));
d9241861 909 else
ff596ca1
OE
910 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
911
d9241861
OE
912 DONE;
913})
78d310c2 914
eb11dba2
OE
915;; Combine patterns to invert compare and branch operations for which we
916;; don't have actual comparison insns. These patterns are used in cases
917;; which appear after the initial cbranchsi expansion, which also does
918;; some condition inversion.
919
920(define_split
921 [(set (pc)
922 (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
923 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
924 (label_ref (match_operand 2))
925 (pc)))
926 (clobber (reg:SI T_REG))]
927 "TARGET_SH1"
928 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
929 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
930 (label_ref (match_dup 2))
931 (pc)))])
932
933;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
934;; and SH2A combine fails to simplify this pattern by itself.
935;; What this actually does is:
936;; x == 0: (1 >> 0-0) & 1 = 1
937;; x != 0: (1 >> 0-x) & 1 = 0
938;; Without this the test pr51244-8.c fails on SH2A and SH4A.
939(define_split
940 [(set (pc)
941 (if_then_else
942 (eq (and:SI (lshiftrt:SI
943 (const_int 1)
944 (neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
945 (const_int 1))
946 (const_int 0))
947 (label_ref (match_operand 2))
948 (pc)))
949 (clobber (reg:SI T_REG))]
950 "TARGET_SH1"
951 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
952 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
953 (label_ref (match_dup 2))
954 (pc)))])
955
7fa4bf9b 956;; FIXME: These could probably use code iterators for the compare op.
eb11dba2
OE
957(define_split
958 [(set (pc)
959 (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
960 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
961 (label_ref (match_operand 2))
962 (pc)))
963 (clobber (reg:SI T_REG))]
964 "TARGET_SH1"
965 [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
966 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
967 (label_ref (match_dup 2))
968 (pc)))])
969
970(define_split
971 [(set (pc)
972 (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
973 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
974 (label_ref (match_operand 2))
975 (pc)))
976 (clobber (reg:SI T_REG))]
977 "TARGET_SH1"
978 [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
979 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
980 (label_ref (match_dup 2))
981 (pc)))])
982
983(define_split
984 [(set (pc)
985 (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
986 (match_operand:SI 1 "arith_reg_operand" ""))
987 (label_ref (match_operand 2))
988 (pc)))
989 (clobber (reg:SI T_REG))]
990 "TARGET_SH1"
991 [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
992 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
993 (label_ref (match_dup 2))
994 (pc)))])
995
996(define_split
997 [(set (pc)
998 (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
999 (match_operand:SI 1 "arith_reg_operand" ""))
1000 (label_ref (match_operand 2))
1001 (pc)))
1002 (clobber (reg:SI T_REG))]
1003 "TARGET_SH1"
1004 [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
1005 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1006 (label_ref (match_dup 2))
1007 (pc)))])
1008
669d4d70
OE
1009;; Compare and branch combine patterns for div0s comparisons.
1010(define_insn_and_split "*cbranch_div0s"
1011 [(set (pc)
1012 (if_then_else (lt (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1013 (match_operand:SI 1 "arith_reg_operand" ""))
1014 (const_int 0))
1015 (label_ref (match_operand 2))
1016 (pc)))
1017 (clobber (reg:SI T_REG))]
1018 "TARGET_SH1"
1019 "#"
1020 "&& 1"
1021 [(set (reg:SI T_REG)
1022 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1023 (set (pc)
1024 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1025 (label_ref (match_dup 2))
1026 (pc)))])
1027
1028(define_insn_and_split "*cbranch_div0s"
1029 [(set (pc)
693445c9
OE
1030 (if_then_else (ge (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1031 (match_operand:SI 1 "arith_reg_operand" ""))
1032 (const_int 0))
669d4d70
OE
1033 (label_ref (match_operand 2))
1034 (pc)))
1035 (clobber (reg:SI T_REG))]
1036 "TARGET_SH1"
1037 "#"
1038 "&& 1"
1039 [(set (reg:SI T_REG)
1040 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1041 (set (pc)
1042 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1043 (label_ref (match_dup 2))
1044 (pc)))])
1045
1046;; Conditional move combine pattern for div0s comparisons.
1047;; This is used when TARGET_PRETEND_CMOVE is in effect.
1048(define_insn_and_split "*movsicc_div0s"
1049 [(set (match_operand:SI 0 "arith_reg_dest" "")
1050 (if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
1051 (match_operand:SI 2 "arith_reg_operand" ""))
1052 (const_int 0))
1053 (match_operand:SI 3 "arith_reg_operand" "")
1054 (match_operand:SI 4 "general_movsrc_operand" "")))
1055 (clobber (reg:SI T_REG))]
1056 "TARGET_PRETEND_CMOVE"
1057 "#"
1058 "&& 1"
1059 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1060 (const_int 0)))
1061 (set (match_dup 0)
1062 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1063 (match_dup 4)
1064 (match_dup 3)))])
1065
bc45ade3
SC
1066;; -------------------------------------------------------------------------
1067;; SImode unsigned integer comparisons
1068;; -------------------------------------------------------------------------
1069
b07c4372
OE
1070;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1071;; However, especially when optimizations are off (e.g. -O0) such comparisons
1072;; might remain and we have to handle them. If the '>= 0' case wasn't
1073;; handled here, something else would just load a '0' into the second operand
1074;; and do the comparison. We can do slightly better by just setting the
1075;; T bit to '1'.
78d310c2 1076(define_insn_and_split "cmpgeusi_t"
4773afa4
AO
1077 [(set (reg:SI T_REG)
1078 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
b07c4372 1079 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
fa5322fa 1080 "TARGET_SH1"
fae15c93 1081 "cmp/hs %1,%0"
b07c4372 1082 "&& satisfies_constraint_Z (operands[1])"
eb11dba2
OE
1083 [(set (reg:SI T_REG) (const_int 1))]
1084 ""
1085 [(set_attr "type" "mt_group")])
bc45ade3
SC
1086
1087(define_insn "cmpgtusi_t"
4773afa4
AO
1088 [(set (reg:SI T_REG)
1089 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1090 (match_operand:SI 1 "arith_reg_operand" "r")))]
fa5322fa 1091 "TARGET_SH1"
fae15c93 1092 "cmp/hi %1,%0"
eb11dba2 1093 [(set_attr "type" "mt_group")])
bc45ade3 1094
bc45ade3
SC
1095\f
1096;; -------------------------------------------------------------------------
78d310c2 1097;; DImode compare and branch
1245df60
R
1098;; -------------------------------------------------------------------------
1099
78d310c2
R
1100
1101;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1102;; Therefore, we aim to have a set of three branches that go straight to the
1103;; destination, i.e. only one of them is taken at any one time.
1104;; This mechanism should also be slightly better for the sh4-200.
1105
1106(define_expand "cbranchdi4"
1107 [(set (pc)
1108 (if_then_else (match_operator 0 "comparison_operator"
1109 [(match_operand:DI 1 "arith_operand" "")
1110 (match_operand:DI 2 "arith_operand" "")])
1111 (label_ref (match_operand 3 "" ""))
1112 (pc)))
1113 (clobber (match_dup 4))
1114 (clobber (reg:SI T_REG))]
f90b7a5a 1115 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
78d310c2
R
1116{
1117 enum rtx_code comparison;
1118
f90b7a5a
PB
1119 if (TARGET_SHMEDIA)
1120 {
1121 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1122 operands[2], operands[3]));
1123 DONE;
1124 }
1125
1126 else if (!TARGET_CBRANCHDI4)
78d310c2 1127 {
f90b7a5a
PB
1128 sh_emit_compare_and_branch (operands, DImode);
1129 DONE;
1130 }
1131
1132 else
1133 {
c3537723
KK
1134 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1135 DONE;
1136
f90b7a5a
PB
1137 comparison = prepare_cbranch_operands (operands, DImode,
1138 LAST_AND_UNUSED_RTX_CODE);
1139 if (comparison != GET_CODE (operands[0]))
1140 operands[0]
1141 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1142 operands[4] = gen_rtx_SCRATCH (SImode);
78d310c2 1143 }
d9241861 1144})
78d310c2
R
1145
1146(define_insn_and_split "cbranchdi4_i"
1147 [(set (pc)
1148 (if_then_else (match_operator 0 "comparison_operator"
1149 [(match_operand:DI 1 "arith_operand" "r,r")
f90b7a5a 1150 (match_operand:DI 2 "arith_operand" "rN,I08")])
78d310c2
R
1151 (label_ref (match_operand 3 "" ""))
1152 (pc)))
1153 (clobber (match_scratch:SI 4 "=X,&r"))
1154 (clobber (reg:SI T_REG))]
1155 "TARGET_CBRANCHDI4"
1156 "#"
1157 "&& reload_completed"
1158 [(pc)]
78d310c2
R
1159{
1160 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1161 FAIL;
1162 DONE;
d9241861 1163})
78d310c2
R
1164
1165;; -------------------------------------------------------------------------
1166;; DImode signed integer comparisons
1167;; -------------------------------------------------------------------------
1245df60
R
1168
1169(define_insn ""
4773afa4 1170 [(set (reg:SI T_REG)
1245df60
R
1171 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1172 (match_operand:DI 1 "arith_operand" "r"))
1173 (const_int 0)))]
fa5322fa 1174 "TARGET_SH1"
6b45f126
OE
1175{
1176 return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1177 insn, operands);
1178}
1245df60
R
1179 [(set_attr "length" "6")
1180 (set_attr "type" "arith3b")])
1181
1182(define_insn "cmpeqdi_t"
4773afa4
AO
1183 [(set (reg:SI T_REG)
1184 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1185 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
fa5322fa 1186 "TARGET_SH1"
35ed5a70
OE
1187{
1188 static const char* alt[] =
1189 {
1190 "tst %S0,%S0" "\n"
1191 " bf 0f" "\n"
1192 " tst %R0,%R0" "\n"
1193 "0:",
1194
1195 "cmp/eq %S1,%S0" "\n"
1196 " bf 0f" "\n"
1197 " cmp/eq %R1,%R0" "\n"
1198 "0:"
1199 };
1200 return alt[which_alternative];
1201}
1245df60
R
1202 [(set_attr "length" "6")
1203 (set_attr "type" "arith3b")])
1204
1987b7bc 1205(define_split
4773afa4 1206 [(set (reg:SI T_REG)
e69d1422
R
1207 (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1208 (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
712646d0
R
1209;; If we applied this split when not optimizing, it would only be
1210;; applied during the machine-dependent reorg, when no new basic blocks
1211;; may be created.
fa5322fa 1212 "TARGET_SH1 && reload_completed && optimize"
4773afa4
AO
1213 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1214 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
712646d0
R
1215 (label_ref (match_dup 6))
1216 (pc)))
4773afa4 1217 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
712646d0 1218 (match_dup 6)]
1987b7bc 1219{
32ed5fcc
OE
1220 operands[2] = gen_highpart (SImode, operands[0]);
1221 operands[3] = operands[1] == const0_rtx
1222 ? const0_rtx
1223 : gen_highpart (SImode, operands[1]);
1987b7bc
R
1224 operands[4] = gen_lowpart (SImode, operands[0]);
1225 operands[5] = gen_lowpart (SImode, operands[1]);
712646d0 1226 operands[6] = gen_label_rtx ();
d9241861 1227})
1987b7bc 1228
1245df60 1229(define_insn "cmpgtdi_t"
4773afa4
AO
1230 [(set (reg:SI T_REG)
1231 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1232 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1245df60 1233 "TARGET_SH2"
35ed5a70
OE
1234{
1235 static const char* alt[] =
1236 {
1237 "cmp/eq %S1,%S0" "\n"
1238 " bf{.|/}s 0f" "\n"
1239 " cmp/gt %S1,%S0" "\n"
1240 " cmp/hi %R1,%R0" "\n"
1241 "0:",
1242
1243 "tst %S0,%S0" "\n"
1244 " bf{.|/}s 0f" "\n"
1245 " cmp/pl %S0" "\n"
1246 " cmp/hi %S0,%R0" "\n"
1247 "0:"
1248 };
1249 return alt[which_alternative];
1250}
1245df60
R
1251 [(set_attr "length" "8")
1252 (set_attr "type" "arith3")])
1253
1254(define_insn "cmpgedi_t"
4773afa4
AO
1255 [(set (reg:SI T_REG)
1256 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1257 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1245df60 1258 "TARGET_SH2"
35ed5a70
OE
1259{
1260 static const char* alt[] =
1261 {
1262 "cmp/eq %S1,%S0" "\n"
1263 " bf{.|/}s 0f" "\n"
1264 " cmp/ge %S1,%S0" "\n"
1265 " cmp/hs %R1,%R0" "\n"
1266 "0:",
1267
1268 "cmp/pz %S0"
1269 };
1270 return alt[which_alternative];
1271}
1245df60 1272 [(set_attr "length" "8,2")
c49439f1 1273 (set_attr "type" "arith3,mt_group")])
1245df60
R
1274\f
1275;; -------------------------------------------------------------------------
1276;; DImode unsigned integer comparisons
1277;; -------------------------------------------------------------------------
1278
1279(define_insn "cmpgeudi_t"
4773afa4
AO
1280 [(set (reg:SI T_REG)
1281 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1282 (match_operand:DI 1 "arith_reg_operand" "r")))]
1245df60 1283 "TARGET_SH2"
35ed5a70
OE
1284{
1285 return "cmp/eq %S1,%S0" "\n"
1286 " bf{.|/}s 0f" "\n"
1287 " cmp/hs %S1,%S0" "\n"
1288 " cmp/hs %R1,%R0" "\n"
1289 "0:";
1290}
1245df60
R
1291 [(set_attr "length" "8")
1292 (set_attr "type" "arith3")])
1293
1294(define_insn "cmpgtudi_t"
4773afa4
AO
1295 [(set (reg:SI T_REG)
1296 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1297 (match_operand:DI 1 "arith_reg_operand" "r")))]
1245df60 1298 "TARGET_SH2"
35ed5a70
OE
1299{
1300 return "cmp/eq %S1,%S0" "\n"
1301 " bf{.|/}s 0f" "\n"
1302 " cmp/hi %S1,%S0" "\n"
1303 " cmp/hi %R1,%R0" "\n"
1304 "0:";
1305}
1245df60
R
1306 [(set_attr "length" "8")
1307 (set_attr "type" "arith3")])
1308
73a4d10b 1309(define_insn "cmpeqsi_media"
73a4d10b
R
1310 [(set (match_operand:SI 0 "register_operand" "=r")
1311 (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1312 (match_operand:SI 2 "cmp_operand" "Nr")))]
1313 "TARGET_SHMEDIA"
1314 "cmpeq %1, %N2, %0"
1315 [(set_attr "type" "cmp_media")])
1316
537426e7 1317(define_insn "cmpeqdi_media"
73a4d10b
R
1318 [(set (match_operand:SI 0 "register_operand" "=r")
1319 (eq:SI (match_operand:DI 1 "register_operand" "%r")
1320 (match_operand:DI 2 "cmp_operand" "Nr")))]
1321 "TARGET_SHMEDIA"
1322 "cmpeq %1, %N2, %0"
1323 [(set_attr "type" "cmp_media")])
1324
537426e7 1325(define_insn "cmpgtsi_media"
73a4d10b
R
1326 [(set (match_operand:SI 0 "register_operand" "=r")
1327 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1328 (match_operand:SI 2 "cmp_operand" "rN")))]
1329 "TARGET_SHMEDIA"
1330 "cmpgt %N1, %N2, %0"
1331 [(set_attr "type" "cmp_media")])
1332
537426e7 1333(define_insn "cmpgtdi_media"
73a4d10b
R
1334 [(set (match_operand:SI 0 "register_operand" "=r")
1335 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1336 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1337 "TARGET_SHMEDIA"
1338 "cmpgt %N1, %N2, %0"
1339 [(set_attr "type" "cmp_media")])
1340
537426e7 1341(define_insn "cmpgtusi_media"
73a4d10b
R
1342 [(set (match_operand:SI 0 "register_operand" "=r")
1343 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1344 (match_operand:SI 2 "cmp_operand" "rN")))]
1345 "TARGET_SHMEDIA"
1346 "cmpgtu %N1, %N2, %0"
1347 [(set_attr "type" "cmp_media")])
1348
537426e7 1349(define_insn "cmpgtudi_media"
73a4d10b
R
1350 [(set (match_operand:SI 0 "register_operand" "=r")
1351 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1352 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1353 "TARGET_SHMEDIA"
1354 "cmpgtu %N1, %N2, %0"
1355 [(set_attr "type" "cmp_media")])
1356
35ed5a70 1357; This pattern is for combine.
73a4d10b
R
1358(define_insn "*cmpne0sisi_media"
1359 [(set (match_operand:SI 0 "register_operand" "=r")
1360 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1361 "TARGET_SHMEDIA"
1362 "cmpgtu %1,r63,%0"
1363 [(set_attr "type" "cmp_media")])
1364
fa5322fa
AO
1365;; -------------------------------------------------------------------------
1366;; Conditional move instructions
1367;; -------------------------------------------------------------------------
1368
1369;; The insn names may seem reversed, but note that cmveq performs the move
1370;; if op1 == 0, and cmvne does it if op1 != 0.
1371
1372(define_insn "movdicc_false"
b6d33983
R
1373 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1374 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
fa5322fa 1375 (const_int 0))
b6d33983
R
1376 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1377 (match_operand:DI 3 "arith_reg_operand" "0")))]
fa5322fa 1378 "TARGET_SHMEDIA"
b6d33983
R
1379 "cmveq %1, %N2, %0"
1380 [(set_attr "type" "arith_media")])
fa5322fa
AO
1381
1382(define_insn "movdicc_true"
b6d33983
R
1383 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1384 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
fa5322fa 1385 (const_int 0))
b6d33983
R
1386 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1387 (match_operand:DI 3 "arith_reg_operand" "0")))]
fa5322fa 1388 "TARGET_SHMEDIA"
b6d33983
R
1389 "cmvne %1, %N2, %0"
1390 [(set_attr "type" "arith_media")])
fa5322fa 1391
73a4d10b
R
1392(define_peephole2
1393 [(set (match_operand:DI 0 "arith_reg_dest" "")
1394 (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1395 [(match_operand:DI 1 "arith_reg_operand" "")
1396 (const_int 0)])
1397 (match_operand:DI 2 "arith_reg_dest" "")
1398 (match_dup 0)))
1399 (set (match_dup 2) (match_dup 0))]
1400 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1401 [(set (match_dup 2)
1402 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
73a4d10b
R
1403{
1404 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1405 VOIDmode, operands[1], CONST0_RTX (DImode));
d9241861 1406})
73a4d10b
R
1407
1408(define_peephole2
1409 [(set (match_operand:DI 0 "general_movdst_operand" "")
1410 (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1411 (set (match_operand:DI 2 "arith_reg_dest" "")
1412 (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1413 [(match_operand:DI 3 "arith_reg_operand" "")
1414 (const_int 0)])
1415 (match_dup 0)
1416 (match_dup 2)))]
1417 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1418 [(set (match_dup 2)
1419 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1420 "")
1421
fa5322fa
AO
1422(define_expand "movdicc"
1423 [(set (match_operand:DI 0 "register_operand" "")
1424 (if_then_else:DI (match_operand 1 "comparison_operator" "")
1425 (match_operand:DI 2 "register_operand" "")
1426 (match_operand:DI 3 "register_operand" "")))]
1427 "TARGET_SHMEDIA"
fa5322fa
AO
1428{
1429 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
f90b7a5a
PB
1430 && GET_MODE (XEXP (operands[1], 0)) == DImode
1431 && XEXP (operands[1], 1) == const0_rtx)
1432 ;
fa5322fa
AO
1433 else
1434 {
b3a13419 1435 if (!can_create_pseudo_p ())
fa5322fa
AO
1436 FAIL;
1437
f90b7a5a
PB
1438 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1439 GET_CODE (operands[1]),
1440 XEXP (operands[1], 0),
1441 XEXP (operands[1], 1));
1442 if (!operands[1])
1443 FAIL;
fa5322fa 1444 }
d9241861 1445})
73a4d10b
R
1446
1447;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1448;; SImode to DImode.
1449(define_insn "movsicc_false"
1450 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1451 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1452 (const_int 0))
1453 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1454 (match_operand:SI 3 "arith_reg_operand" "0")))]
1455 "TARGET_SHMEDIA"
1456 "cmveq %1, %N2, %0"
1457 [(set_attr "type" "arith_media")])
1458
1459(define_insn "movsicc_true"
1460 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1461 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1462 (const_int 0))
1463 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1464 (match_operand:SI 3 "arith_reg_operand" "0")))]
1465 "TARGET_SHMEDIA"
1466 "cmvne %1, %N2, %0"
1467 [(set_attr "type" "arith_media")])
1468
1469(define_peephole2
1470 [(set (match_operand:SI 0 "arith_reg_dest" "")
1471 (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1472 [(match_operand:SI 1 "arith_reg_operand" "")
1473 (const_int 0)])
1474 (match_operand:SI 2 "arith_reg_dest" "")
1475 (match_dup 0)))
1476 (set (match_dup 2) (match_dup 0))]
1477 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1478 [(set (match_dup 2)
1479 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
73a4d10b
R
1480{
1481 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1482 VOIDmode, operands[1], CONST0_RTX (SImode));
d9241861 1483})
73a4d10b
R
1484
1485(define_peephole2
1486 [(set (match_operand:SI 0 "general_movdst_operand" "")
1487 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1488 (set (match_operand:SI 2 "arith_reg_dest" "")
1489 (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1490 [(match_operand:SI 3 "arith_reg_operand" "")
1491 (const_int 0)])
1492 (match_dup 0)
1493 (match_dup 2)))]
1494 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
f3536097 1495 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
73a4d10b
R
1496 [(set (match_dup 2)
1497 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
73a4d10b
R
1498{
1499 replace_rtx (operands[4], operands[0], operands[1]);
d9241861 1500})
73a4d10b
R
1501
1502(define_peephole2
1503 [(set (match_operand 0 "any_register_operand" "")
1504 (match_operand 1 "any_register_operand" ""))
1505 (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1506 (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1507 "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1508 <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1509 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
904b6a0e
KK
1510 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1511 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
73a4d10b
R
1512 && ! reg_overlap_mentioned_p (operands[0], operands[3])
1513 && ! reg_overlap_mentioned_p (operands[2], operands[0])
1514 && ! reg_overlap_mentioned_p (operands[0], operands[1])
1515 && (REGNO_REG_CLASS (REGNO (operands[0]))
1516 == REGNO_REG_CLASS (REGNO (operands[2])))
1517 && (REGNO_REG_CLASS (REGNO (operands[1]))
1518 == REGNO_REG_CLASS (REGNO (operands[0])))"
1519 [(set (match_dup 0) (match_dup 3))
1520 (set (match_dup 4) (match_dup 5))]
73a4d10b 1521{
058e97ec 1522 rtx set1, set2, insn2;
73a4d10b
R
1523 rtx replacements[4];
1524
0fa2e4df 1525 /* We want to replace occurrences of operands[0] with operands[1] and
73a4d10b 1526 operands[2] with operands[0] in operands[4]/operands[5].
30dc60c7 1527 Doing just two replace_rtx calls naively would result in the second
73a4d10b
R
1528 replacement undoing all that the first did if operands[1] and operands[2]
1529 are identical, so we must do this simultaneously. */
1530 replacements[0] = operands[0];
1531 replacements[1] = operands[1];
1532 replacements[2] = operands[2];
1533 replacements[3] = operands[0];
1534 if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1535 || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1536 || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1537 FAIL;
1538
1539 operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1540 replace_n_hard_rtx (operands[4], replacements, 2, 1);
1541 operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1542 /* The operands array is aliased to recog_data.operand, which gets
1543 clobbered by extract_insn, so finish with it now. */
1544 set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1545 set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1546 /* ??? The last insn might be a jump insn, but the generic peephole2 code
1547 always uses emit_insn. */
1548 /* Check that we don't violate matching constraints or earlyclobbers. */
1549 extract_insn (emit_insn (set1));
1550 if (! constrain_operands (1))
1551 goto failure;
058e97ec
VM
1552 insn2 = emit (set2);
1553 if (GET_CODE (insn2) == BARRIER)
1554 goto failure;
1555 extract_insn (insn2);
73a4d10b
R
1556 if (! constrain_operands (1))
1557 {
1558 rtx tmp;
1559 failure:
1560 tmp = replacements[0];
1561 replacements[0] = replacements[1];
1562 replacements[1] = tmp;
1563 tmp = replacements[2];
1564 replacements[2] = replacements[3];
1565 replacements[3] = tmp;
1566 replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1567 replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1568 replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1569 FAIL;
1570 }
1571 DONE;
d9241861 1572})
73a4d10b
R
1573
1574;; The register allocator is rather clumsy in handling multi-way conditional
1575;; moves, so allow the combiner to make them, and we split them up after
1576;; reload. */
1577(define_insn_and_split "*movsicc_umin"
1578 [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1579 (umin:SI (if_then_else:SI
1580 (eq (match_operand:SI 1 "arith_reg_operand" "r")
1581 (const_int 0))
1582 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1583 (match_operand:SI 3 "register_operand" "0"))
1584 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1585 (clobber (match_scratch:SI 5 "=&r"))]
b3a13419 1586 "TARGET_SHMEDIA && !can_create_pseudo_p ()"
73a4d10b
R
1587 "#"
1588 "TARGET_SHMEDIA && reload_completed"
1589 [(pc)]
73a4d10b
R
1590{
1591 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1592 operands[3]));
537426e7 1593 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
73a4d10b
R
1594 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1595 operands[0]));
1596 DONE;
d9241861 1597})
73a4d10b 1598
25e651ca
AS
1599(define_insn "*movsicc_t_false"
1600 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1601 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1602 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1603 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1604 "TARGET_PRETEND_CMOVE
1605 && (arith_reg_operand (operands[1], SImode)
1606 || (immediate_operand (operands[1], SImode)
32a7ab3d 1607 && satisfies_constraint_I08 (operands[1])))"
35ed5a70
OE
1608{
1609 return "bt 0f" "\n"
1610 " mov %1,%0" "\n"
1611 "0:";
1612}
25e651ca
AS
1613 [(set_attr "type" "mt_group,arith") ;; poor approximation
1614 (set_attr "length" "4")])
1615
1616(define_insn "*movsicc_t_true"
1617 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1618 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1619 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1620 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1621 "TARGET_PRETEND_CMOVE
1622 && (arith_reg_operand (operands[1], SImode)
1623 || (immediate_operand (operands[1], SImode)
32a7ab3d 1624 && satisfies_constraint_I08 (operands[1])))"
35ed5a70
OE
1625{
1626 return "bf 0f" "\n"
1627 " mov %1,%0" "\n"
1628 "0:";
1629}
25e651ca
AS
1630 [(set_attr "type" "mt_group,arith") ;; poor approximation
1631 (set_attr "length" "4")])
1632
73a4d10b 1633(define_expand "movsicc"
25e651ca 1634 [(set (match_operand:SI 0 "arith_reg_dest" "")
73a4d10b 1635 (if_then_else:SI (match_operand 1 "comparison_operator" "")
25e651ca
AS
1636 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1637 (match_operand:SI 3 "arith_reg_operand" "")))]
1638 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
73a4d10b
R
1639{
1640 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
f90b7a5a 1641 && GET_MODE (XEXP (operands[1], 0)) == SImode
25e651ca 1642 && (TARGET_SHMEDIA
f90b7a5a
PB
1643 || (REG_P (XEXP (operands[1], 0))
1644 && REGNO (XEXP (operands[1], 0)) == T_REG))
1645 && XEXP (operands[1], 1) == const0_rtx)
1646 ;
1647
25e651ca
AS
1648 else if (TARGET_PRETEND_CMOVE)
1649 {
1650 enum rtx_code code = GET_CODE (operands[1]);
1651 enum rtx_code new_code = code;
f90b7a5a
PB
1652 rtx op0 = XEXP (operands[1], 0);
1653 rtx op1 = XEXP (operands[1], 1);
25e651ca
AS
1654
1655 if (! currently_expanding_to_rtl)
1656 FAIL;
1657 switch (code)
1658 {
1659 case LT: case LE: case LEU: case LTU:
f90b7a5a 1660 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
25e651ca
AS
1661 break;
1662 case NE:
1663 new_code = reverse_condition (code);
1664 break;
1665 case EQ: case GT: case GE: case GEU: case GTU:
1666 break;
1667 default:
1668 FAIL;
1669 }
f90b7a5a 1670 sh_emit_scc_to_t (new_code, op0, op1);
25e651ca 1671 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
f90b7a5a 1672 gen_rtx_REG (SImode, T_REG), const0_rtx);
25e651ca 1673 }
73a4d10b
R
1674 else
1675 {
b3a13419 1676 if (!can_create_pseudo_p ())
73a4d10b
R
1677 FAIL;
1678
f90b7a5a
PB
1679 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1680 GET_CODE (operands[1]),
1681 XEXP (operands[1], 0),
1682 XEXP (operands[1], 1));
1683 if (!operands[1])
1684 FAIL;
73a4d10b 1685 }
d9241861 1686})
73a4d10b
R
1687
1688(define_expand "movqicc"
1689 [(set (match_operand:QI 0 "register_operand" "")
1690 (if_then_else:QI (match_operand 1 "comparison_operator" "")
1691 (match_operand:QI 2 "register_operand" "")
1692 (match_operand:QI 3 "register_operand" "")))]
1693 "TARGET_SHMEDIA"
73a4d10b
R
1694{
1695 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1696 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1697 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1698 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1699 DONE;
d9241861 1700})
1245df60
R
1701\f
1702;; -------------------------------------------------------------------------
bc45ade3
SC
1703;; Addition instructions
1704;; -------------------------------------------------------------------------
1705
fa5322fa
AO
1706(define_expand "adddi3"
1707 [(set (match_operand:DI 0 "arith_reg_operand" "")
1708 (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1709 (match_operand:DI 2 "arith_operand" "")))]
1710 ""
fa5322fa
AO
1711{
1712 if (TARGET_SH1)
1713 {
b3a13419 1714 if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
fa5322fa
AO
1715 FAIL;
1716 operands[2] = force_reg (DImode, operands[2]);
1717 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1718 DONE;
1719 }
d9241861 1720})
0d7e008e 1721
fa5322fa 1722(define_insn "*adddi3_media"
73a4d10b 1723 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
fa5322fa 1724 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
735cb76e 1725 (match_operand:DI 2 "arith_operand" "r,I10")))]
fa5322fa
AO
1726 "TARGET_SHMEDIA"
1727 "@
1728 add %1, %2, %0
2ad65b0e
SC
1729 addi %1, %2, %0"
1730 [(set_attr "type" "arith_media")])
fa5322fa 1731
73a4d10b
R
1732(define_insn "*adddisi3_media"
1733 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1734 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1735 (match_operand:DI 2 "arith_operand" "r,I10")))]
1736 "TARGET_SHMEDIA"
1737 "@
1738 add.l %1, %2, %0
1739 addi.l %1, %2, %0"
1740 [(set_attr "type" "arith_media")
1741 (set_attr "highpart" "ignore")])
1742
b6d33983 1743(define_insn "adddi3z_media"
73a4d10b 1744 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
fa5322fa 1745 (zero_extend:DI
b6d33983
R
1746 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1747 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
fa5322fa 1748 "TARGET_SHMEDIA"
b6d33983 1749 "addz.l %1, %N2, %0"
73a4d10b
R
1750 [(set_attr "type" "arith_media")
1751 (set_attr "highpart" "ignore")])
52702ae1 1752
ee04b091 1753(define_insn_and_split "adddi3_compact"
73a4d10b 1754 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
07a45e5c
JW
1755 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1756 (match_operand:DI 2 "arith_reg_operand" "r")))
4773afa4 1757 (clobber (reg:SI T_REG))]
fa5322fa 1758 "TARGET_SH1"
1245df60 1759 "#"
ee04b091 1760 "&& reload_completed"
1245df60 1761 [(const_int 0)]
1245df60 1762{
32ed5fcc
OE
1763 rtx high0 = gen_highpart (SImode, operands[0]);
1764 rtx high2 = gen_highpart (SImode, operands[2]);
1765 rtx low0 = gen_lowpart (SImode, operands[0]);
1766
1245df60
R
1767 emit_insn (gen_clrt ());
1768 emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
dad6fafd 1769 emit_insn (gen_addc (high0, high0, high2));
1245df60 1770 DONE;
d9241861 1771})
1245df60
R
1772
1773(define_insn "addc"
73a4d10b 1774 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
0c66c562 1775 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1245df60 1776 (match_operand:SI 2 "arith_reg_operand" "r"))
4773afa4
AO
1777 (reg:SI T_REG)))
1778 (set (reg:SI T_REG)
1245df60 1779 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
fa5322fa 1780 "TARGET_SH1"
1245df60 1781 "addc %2,%0"
c49439f1 1782 [(set_attr "type" "arith")])
1245df60 1783
0c66c562
OE
1784;; A simplified version of the addc insn, where the exact value of the
1785;; T bit doesn't matter. This is easier for combine to pick up.
1786;; We allow a reg or 0 for one of the operands in order to be able to
1787;; do 'reg + T' sequences. Reload will load the constant 0 into the reg
1788;; as needed.
1789(define_insn "*addc"
1790 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1791 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1792 (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1793 (match_operand:SI 3 "t_reg_operand" "")))
1794 (clobber (reg:SI T_REG))]
1795 "TARGET_SH1"
1796 "addc %2,%0"
1797 [(set_attr "type" "arith")])
1798
1799;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
1800;; better, if the sett insn can be done early.
1801(define_insn_and_split "*addc"
1802 [(set (match_operand:SI 0 "arith_reg_dest" "")
1803 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
1804 (match_operand:SI 2 "arith_reg_operand" ""))
1805 (const_int 1)))
1806 (clobber (reg:SI T_REG))]
1807 "TARGET_SH1"
1808 "#"
1809 "&& 1"
1810 [(set (reg:SI T_REG) (const_int 1))
1811 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
1812 (reg:SI T_REG)))
1813 (clobber (reg:SI T_REG))])])
1814
8b75f550
OE
1815;; Left shifts by one are usually done with an add insn to avoid T_REG
1816;; clobbers. Thus addc can also be used to do something like '(x << 1) + 1'.
1817(define_insn_and_split "*addc"
1818 [(set (match_operand:SI 0 "arith_reg_dest")
1819 (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
1820 (const_int 2))
1821 (const_int 1)))
1822 (clobber (reg:SI T_REG))]
1823 "TARGET_SH1"
1824 "#"
1825 "&& 1"
1826 [(set (reg:SI T_REG) (const_int 1))
1827 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
1828 (reg:SI T_REG)))
1829 (clobber (reg:SI T_REG))])])
1830
0c66c562
OE
1831;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1832;; matched. Split this up into a simple sub add sequence, as this will save
1833;; us one sett insn.
1834(define_insn_and_split "*minus_plus_one"
1835 [(set (match_operand:SI 0 "arith_reg_dest" "")
1836 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1837 (match_operand:SI 2 "arith_reg_operand" ""))
1838 (const_int 1)))]
1839 "TARGET_SH1"
1840 "#"
1841 "&& 1"
1842 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1843 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
1844
1845;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
1846;; If the 0 constant can be CSE-ed, this becomes a one instruction
1847;; operation, as opposed to sequences such as
1848;; movt r2
1849;; add r2,r3
1850;;
1851;; Even if the constant is not CSE-ed, a sequence such as
1852;; mov #0,r2
1853;; addc r2,r3
1854;; can be scheduled much better since the load of the constant can be
1855;; done earlier, before any comparison insns that store the result in
1856;; the T bit.
1857(define_insn_and_split "*addc"
1858 [(set (match_operand:SI 0 "arith_reg_dest" "")
1859 (plus:SI (match_operand:SI 1 "t_reg_operand" "")
1860 (match_operand:SI 2 "arith_reg_operand" "")))
1861 (clobber (reg:SI T_REG))]
1862 "TARGET_SH1"
1863 "#"
1864 "&& 1"
1865 [(parallel [(set (match_dup 0)
1866 (plus:SI (plus:SI (match_dup 2) (const_int 0))
1867 (match_dup 1)))
1868 (clobber (reg:SI T_REG))])])
1869
fa5322fa
AO
1870(define_expand "addsi3"
1871 [(set (match_operand:SI 0 "arith_reg_operand" "")
1872 (plus:SI (match_operand:SI 1 "arith_operand" "")
1873 (match_operand:SI 2 "arith_operand" "")))]
1874 ""
fa5322fa
AO
1875{
1876 if (TARGET_SHMEDIA)
1877 operands[1] = force_reg (SImode, operands[1]);
d9241861 1878})
fa5322fa
AO
1879
1880(define_insn "addsi3_media"
73a4d10b 1881 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
b6d33983 1882 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
735cb76e 1883 (match_operand:SI 2 "arith_operand" "r,I10")))]
fa5322fa
AO
1884 "TARGET_SHMEDIA"
1885 "@
1886 add.l %1, %2, %0
b6d33983 1887 addi.l %1, %2, %0"
73a4d10b
R
1888 [(set_attr "type" "arith_media")
1889 (set_attr "highpart" "ignore")])
1890
1891(define_insn "addsidi3_media"
1892 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1893 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1894 "%r,r")
1895 (match_operand:SI 2 "arith_operand"
1896 "r,I10"))))]
1897 "TARGET_SHMEDIA"
1898 "@
1899 add.l %1, %2, %0
1900 addi.l %1, %2, %0"
1901 [(set_attr "type" "arith_media")
1902 (set_attr "highpart" "ignore")])
52702ae1 1903
fa5322fa 1904(define_insn "*addsi3_compact"
73a4d10b 1905 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
51bd623f 1906 (plus:SI (match_operand:SI 1 "arith_operand" "%0")
735cb76e 1907 (match_operand:SI 2 "arith_operand" "rI08")))]
fa5322fa 1908 "TARGET_SH1"
bc45ade3 1909 "add %2,%0"
c49439f1 1910 [(set_attr "type" "arith")])
fae15c93 1911
bc45ade3
SC
1912;; -------------------------------------------------------------------------
1913;; Subtraction instructions
1914;; -------------------------------------------------------------------------
1915
fa5322fa
AO
1916(define_expand "subdi3"
1917 [(set (match_operand:DI 0 "arith_reg_operand" "")
52702ae1 1918 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
fa5322fa
AO
1919 (match_operand:DI 2 "arith_reg_operand" "")))]
1920 ""
fa5322fa
AO
1921{
1922 if (TARGET_SH1)
1923 {
52702ae1 1924 operands[1] = force_reg (DImode, operands[1]);
fa5322fa
AO
1925 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1926 DONE;
1927 }
d9241861 1928})
52702ae1 1929
fa5322fa 1930(define_insn "*subdi3_media"
73a4d10b 1931 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
52702ae1 1932 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
fa5322fa
AO
1933 (match_operand:DI 2 "arith_reg_operand" "r")))]
1934 "TARGET_SHMEDIA"
2ad65b0e
SC
1935 "sub %N1, %2, %0"
1936 [(set_attr "type" "arith_media")])
73a4d10b
R
1937
1938(define_insn "subdisi3_media"
1939 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1940 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1941 (match_operand:DI 2 "arith_reg_operand" "r")))]
1942 "TARGET_SHMEDIA"
1943 "sub.l %N1, %2, %0"
1944 [(set_attr "type" "arith_media")
1945 (set_attr "highpart" "ignore")])
52702ae1 1946
ee04b091 1947(define_insn_and_split "subdi3_compact"
73a4d10b 1948 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
07a45e5c
JW
1949 (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1950 (match_operand:DI 2 "arith_reg_operand" "r")))
4773afa4 1951 (clobber (reg:SI T_REG))]
fa5322fa 1952 "TARGET_SH1"
1245df60 1953 "#"
ee04b091 1954 "&& reload_completed"
1245df60 1955 [(const_int 0)]
1245df60 1956{
32ed5fcc
OE
1957 rtx high0 = gen_highpart (SImode, operands[0]);
1958 rtx high2 = gen_highpart (SImode, operands[2]);
1959 rtx low0 = gen_lowpart (SImode, operands[0]);
1960
1245df60
R
1961 emit_insn (gen_clrt ());
1962 emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
dad6fafd 1963 emit_insn (gen_subc (high0, high0, high2));
1245df60 1964 DONE;
d9241861 1965})
1245df60
R
1966
1967(define_insn "subc"
73a4d10b 1968 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1245df60
R
1969 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1970 (match_operand:SI 2 "arith_reg_operand" "r"))
4773afa4
AO
1971 (reg:SI T_REG)))
1972 (set (reg:SI T_REG)
3db1b434
R
1973 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1974 (reg:SI T_REG))
1975 (match_dup 1)))]
fa5322fa 1976 "TARGET_SH1"
1245df60 1977 "subc %2,%0"
c49439f1 1978 [(set_attr "type" "arith")])
1245df60 1979
0c66c562
OE
1980;; A simplified version of the subc insn, where the exact value of the
1981;; T bit doesn't matter. This is easier for combine to pick up.
1982;; We allow a reg or 0 for one of the operands in order to be able to
1983;; do 'reg - T' sequences. Reload will load the constant 0 into the reg
1984;; as needed.
1985(define_insn "*subc"
1986 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1987 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1988 (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1989 (match_operand:SI 3 "t_reg_operand" "")))
1990 (clobber (reg:SI T_REG))]
1991 "TARGET_SH1"
1992 "subc %2,%0"
1993 [(set_attr "type" "arith")])
1994
1995;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
1996;; better, if the sett insn can be done early.
1997;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
1998(define_insn_and_split "*subc"
1999 [(set (match_operand:SI 0 "arith_reg_dest" "")
2000 (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
2001 (match_operand:SI 2 "arith_reg_operand" "")))
2002 (clobber (reg:SI T_REG))]
2003 "TARGET_SH1"
2004 "#"
2005 "&& 1"
2006 [(set (reg:SI T_REG) (const_int 1))
2007 (parallel [(set (match_dup 0)
2008 (minus:SI (minus:SI (match_dup 2) (match_dup 1))
2009 (reg:SI T_REG)))
2010 (clobber (reg:SI T_REG))])])
2011
2012;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
2013;; If the 0 constant can be CSE-ed, this becomes a one instruction
2014;; operation, as opposed to sequences such as
2015;; movt r2
2016;; sub r2,r3
2017;;
2018;; Even if the constant is not CSE-ed, a sequence such as
2019;; mov #0,r2
2020;; subc r2,r3
2021;; can be scheduled much better since the load of the constant can be
2022;; done earlier, before any comparison insns that store the result in
2023;; the T bit.
2024(define_insn_and_split "*subc"
2025 [(set (match_operand:SI 0 "arith_reg_dest" "")
2026 (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2027 (match_operand:SI 2 "t_reg_operand" "")))
2028 (clobber (reg:SI T_REG))]
2029 "TARGET_SH1"
2030 "#"
2031 "&& 1"
2032 [(parallel [(set (match_dup 0)
2033 (minus:SI (minus:SI (match_dup 1) (const_int 0))
2034 (match_dup 2)))
2035 (clobber (reg:SI T_REG))])])
2036
caca3c8a 2037(define_insn "*subsi3_internal"
73a4d10b 2038 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
0d7e008e 2039 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
ffae286a 2040 (match_operand:SI 2 "arith_reg_operand" "r")))]
fa5322fa 2041 "TARGET_SH1"
0d7e008e 2042 "sub %2,%0"
c49439f1 2043 [(set_attr "type" "arith")])
caca3c8a 2044
73a4d10b
R
2045(define_insn_and_split "*subsi3_media"
2046 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2047 (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
b6d33983 2048 (match_operand:SI 2 "extend_reg_operand" "r")))]
73a4d10b
R
2049 "TARGET_SHMEDIA
2050 && (operands[1] != constm1_rtx
2051 || (GET_CODE (operands[2]) != TRUNCATE
2052 && GET_CODE (operands[2]) != SUBREG))"
b6d33983 2053 "sub.l %N1, %2, %0"
73a4d10b
R
2054 "operands[1] == constm1_rtx"
2055 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2056 ""
2057 [(set_attr "type" "arith_media")
2058 (set_attr "highpart" "ignore")])
fa5322fa 2059
73a4d10b
R
2060(define_split
2061 [(set (match_operand:SI 0 "arith_reg_dest" "")
2062 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2063 "general_extend_operand"
2064 "") 0)) 0)))]
2065 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2066 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2067 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2068 "")
2069
2070(define_split
2071 [(set (match_operand:SI 0 "arith_reg_dest" "")
2072 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2073 "general_extend_operand"
2074 "") 0)) 3)))]
2075 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
2076 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2077 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2078 "")
caca3c8a
JW
2079;; Convert `constant - reg' to `neg rX; add rX, #const' since this
2080;; will sometimes save one instruction. Otherwise we might get
2081;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
2082;; are the same.
2083
2084(define_expand "subsi3"
2085 [(set (match_operand:SI 0 "arith_reg_operand" "")
2086 (minus:SI (match_operand:SI 1 "arith_operand" "")
2087 (match_operand:SI 2 "arith_reg_operand" "")))]
2088 ""
caca3c8a 2089{
f3536097 2090 if (TARGET_SH1 && CONST_INT_P (operands[1]))
caca3c8a
JW
2091 {
2092 emit_insn (gen_negsi2 (operands[0], operands[2]));
2093 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2094 DONE;
2095 }
fa5322fa
AO
2096 if (TARGET_SHMEDIA)
2097 {
b3a13419
ILT
2098 if (!can_create_pseudo_p ()
2099 && ! arith_reg_or_0_operand (operands[1], SImode))
fa5322fa 2100 FAIL;
73a4d10b 2101 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
b6d33983 2102 operands[1] = force_reg (SImode, operands[1]);
fa5322fa 2103 }
d9241861 2104})
bc45ade3
SC
2105\f
2106;; -------------------------------------------------------------------------
0d7e008e 2107;; Division instructions
bc45ade3
SC
2108;; -------------------------------------------------------------------------
2109
ffae286a 2110;; We take advantage of the library routines which don't clobber as many
0d7e008e
SC
2111;; registers as a normal function call would.
2112
1245df60 2113;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
956d6950 2114;; also has an effect on the register that holds the address of the sfunc.
e69d1422 2115;; To make this work, we have an extra dummy insn that shows the use
1245df60
R
2116;; of this register for reorg.
2117
2118(define_insn "use_sfunc_addr"
4773afa4 2119 [(set (reg:SI PR_REG)
e69d1422 2120 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
07d7d2f4 2121 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
1245df60
R
2122 ""
2123 [(set_attr "length" "0")])
2124
157371cf 2125(define_insn "udivsi3_sh2a"
73a4d10b 2126 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
157371cf
AO
2127 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2128 (match_operand:SI 2 "arith_reg_operand" "z")))]
2129 "TARGET_SH2A"
2130 "divu %2,%1"
98e20ffd
NC
2131 [(set_attr "type" "arith")
2132 (set_attr "in_delay_slot" "no")])
157371cf 2133
ddd5a7c1 2134;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
e96a50cc
JW
2135;; hard register 0. If we used hard register 0, then the next instruction
2136;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg
2137;; gets allocated to a stack slot that needs its address reloaded, then
2138;; there is nothing to prevent reload from using r0 to reload the address.
2139;; This reload would clobber the value in r0 we are trying to store.
2140;; If we let reload allocate r0, then this problem can never happen.
0d7e008e 2141
a512fa97 2142(define_insn "udivsi3_i1"
1245df60 2143 [(set (match_operand:SI 0 "register_operand" "=z")
4773afa4
AO
2144 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2145 (clobber (reg:SI T_REG))
2146 (clobber (reg:SI PR_REG))
2147 (clobber (reg:SI R4_REG))
1245df60 2148 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
05eb5cc3 2149 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
225e4f43
R
2150 "jsr @%1%#"
2151 [(set_attr "type" "sfunc")
2152 (set_attr "needs_delay_slot" "yes")])
2153
9e96203d
R
2154; Since shmedia-nofpu code could be linked against shcompact code, and
2155; the udivsi3 libcall has the same name, we must consider all registers
2156; clobbered that are in the union of the registers clobbered by the
2157; shmedia and the shcompact implementation. Note, if the shcompact
825db093 2158; implementation actually used shcompact code, we'd need to clobber
9e96203d 2159; also r23 and fr23.
fa5322fa
AO
2160(define_insn "udivsi3_i1_media"
2161 [(set (match_operand:SI 0 "register_operand" "=z")
2162 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2163 (clobber (reg:SI T_MEDIA_REG))
2164 (clobber (reg:SI PR_MEDIA_REG))
9e96203d
R
2165 (clobber (reg:SI R20_REG))
2166 (clobber (reg:SI R21_REG))
2167 (clobber (reg:SI R22_REG))
fa5322fa
AO
2168 (clobber (reg:DI TR0_REG))
2169 (clobber (reg:DI TR1_REG))
2170 (clobber (reg:DI TR2_REG))
1ed50f71 2171 (use (match_operand 1 "target_reg_operand" "b"))]
73a4d10b 2172 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
fa5322fa
AO
2173 "blink %1, r18"
2174 [(set_attr "type" "sfunc")
2175 (set_attr "needs_delay_slot" "yes")])
2176
2177(define_expand "udivsi3_i4_media"
b6d33983
R
2178 [(set (match_dup 3)
2179 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2180 (set (match_dup 4)
2181 (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
fa5322fa 2182 (set (match_dup 5) (float:DF (match_dup 3)))
b6d33983
R
2183 (set (match_dup 6) (float:DF (match_dup 4)))
2184 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2185 (set (match_dup 8) (fix:DI (match_dup 7)))
0ac78517
R
2186 (set (match_operand:SI 0 "register_operand" "")
2187 (truncate:SI (match_dup 8)))]
fa5322fa 2188 "TARGET_SHMEDIA_FPU"
fa5322fa 2189{
fa5322fa 2190 operands[3] = gen_reg_rtx (DImode);
b6d33983 2191 operands[4] = gen_reg_rtx (DImode);
fa5322fa
AO
2192 operands[5] = gen_reg_rtx (DFmode);
2193 operands[6] = gen_reg_rtx (DFmode);
b6d33983
R
2194 operands[7] = gen_reg_rtx (DFmode);
2195 operands[8] = gen_reg_rtx (DImode);
d9241861 2196})
fa5322fa 2197
225e4f43
R
2198(define_insn "udivsi3_i4"
2199 [(set (match_operand:SI 0 "register_operand" "=y")
4773afa4 2200 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
5f6fa212 2201 (clobber (reg:SI T_REG))
4773afa4
AO
2202 (clobber (reg:SI PR_REG))
2203 (clobber (reg:DF DR0_REG))
2204 (clobber (reg:DF DR2_REG))
2205 (clobber (reg:DF DR4_REG))
2206 (clobber (reg:SI R0_REG))
2207 (clobber (reg:SI R1_REG))
2208 (clobber (reg:SI R4_REG))
2209 (clobber (reg:SI R5_REG))
2210 (use (reg:PSI FPSCR_REG))
225e4f43
R
2211 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2212 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2213 "jsr @%1%#"
2214 [(set_attr "type" "sfunc")
d64264ff 2215 (set_attr "fp_mode" "double")
225e4f43
R
2216 (set_attr "needs_delay_slot" "yes")])
2217
2218(define_insn "udivsi3_i4_single"
2219 [(set (match_operand:SI 0 "register_operand" "=y")
4773afa4 2220 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
5f6fa212 2221 (clobber (reg:SI T_REG))
4773afa4
AO
2222 (clobber (reg:SI PR_REG))
2223 (clobber (reg:DF DR0_REG))
2224 (clobber (reg:DF DR2_REG))
2225 (clobber (reg:DF DR4_REG))
2226 (clobber (reg:SI R0_REG))
2227 (clobber (reg:SI R1_REG))
2228 (clobber (reg:SI R4_REG))
2229 (clobber (reg:SI R5_REG))
225e4f43 2230 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
fa5322fa 2231 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1245df60 2232 "jsr @%1%#"
0d7e008e 2233 [(set_attr "type" "sfunc")
0d7e008e
SC
2234 (set_attr "needs_delay_slot" "yes")])
2235
b368d6b8
R
2236(define_insn "udivsi3_i4_int"
2237 [(set (match_operand:SI 0 "register_operand" "=z")
2238 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2239 (clobber (reg:SI T_REG))
2240 (clobber (reg:SI R1_REG))
2241 (clobber (reg:SI PR_REG))
95ec2af0
KK
2242 (clobber (reg:SI MACH_REG))
2243 (clobber (reg:SI MACL_REG))
b368d6b8
R
2244 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2245 "TARGET_SH1"
2246 "jsr @%1%#"
2247 [(set_attr "type" "sfunc")
2248 (set_attr "needs_delay_slot" "yes")])
2249
2250
0d7e008e 2251(define_expand "udivsi3"
a512fa97 2252 [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
4773afa4
AO
2253 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2254 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
ffae286a 2255 (parallel [(set (match_operand:SI 0 "register_operand" "")
4773afa4
AO
2256 (udiv:SI (reg:SI R4_REG)
2257 (reg:SI R5_REG)))
2258 (clobber (reg:SI T_REG))
2259 (clobber (reg:SI PR_REG))
2260 (clobber (reg:SI R4_REG))
ffae286a 2261 (use (match_dup 3))])]
0d7e008e 2262 ""
225e4f43 2263{
ba56ed65 2264 rtx last;
a512fa97 2265
fa5322fa 2266 operands[3] = gen_reg_rtx (Pmode);
a512fa97 2267 /* Emit the move of the address to a pseudo outside of the libcall. */
b368d6b8
R
2268 if (TARGET_DIVIDE_CALL_TABLE)
2269 {
31b6f0ae
R
2270 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2271 that causes problems when the divide code is supposed to come from a
2272 separate library. Division by zero is undefined, so dividing 1 can be
2273 implemented by comparing with the divisor. */
2274 if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2275 {
f90b7a5a
PB
2276 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2277 emit_insn (gen_cstoresi4 (operands[0], test,
2278 operands[1], operands[2]));
31b6f0ae
R
2279 DONE;
2280 }
2281 else if (operands[2] == const0_rtx)
2282 {
2283 emit_move_insn (operands[0], operands[2]);
2284 DONE;
2285 }
d9241861 2286 function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
b368d6b8
R
2287 last = gen_udivsi3_i4_int (operands[0], operands[3]);
2288 }
2289 else if (TARGET_DIVIDE_CALL_FP)
225e4f43 2290 {
d9241861 2291 function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
225e4f43 2292 if (TARGET_FPU_SINGLE)
a512fa97 2293 last = gen_udivsi3_i4_single (operands[0], operands[3]);
225e4f43 2294 else
a512fa97 2295 last = gen_udivsi3_i4 (operands[0], operands[3]);
225e4f43 2296 }
fa5322fa 2297 else if (TARGET_SHMEDIA_FPU)
b6d33983
R
2298 {
2299 operands[1] = force_reg (SImode, operands[1]);
2300 operands[2] = force_reg (SImode, operands[2]);
4392ebd3
RS
2301 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2302 DONE;
b6d33983 2303 }
157371cf
AO
2304 else if (TARGET_SH2A)
2305 {
2306 operands[1] = force_reg (SImode, operands[1]);
2307 operands[2] = force_reg (SImode, operands[2]);
2308 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2309 DONE;
2310 }
fa5322fa
AO
2311 else if (TARGET_SH5)
2312 {
73a4d10b 2313 function_symbol (operands[3],
d9241861 2314 TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
73a4d10b 2315 SFUNC_STATIC);
fa5322fa
AO
2316
2317 if (TARGET_SHMEDIA)
73a4d10b 2318 last = gen_udivsi3_i1_media (operands[0], operands[3]);
fa5322fa
AO
2319 else if (TARGET_FPU_ANY)
2320 last = gen_udivsi3_i4_single (operands[0], operands[3]);
2321 else
2322 last = gen_udivsi3_i1 (operands[0], operands[3]);
2323 }
a512fa97
R
2324 else
2325 {
d9241861 2326 function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
a512fa97
R
2327 last = gen_udivsi3_i1 (operands[0], operands[3]);
2328 }
ba56ed65 2329 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
4392ebd3 2330 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
ba56ed65 2331 emit_insn (last);
a512fa97 2332 DONE;
d9241861 2333})
0d7e008e 2334
157371cf 2335(define_insn "divsi3_sh2a"
73a4d10b 2336 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
157371cf
AO
2337 (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2338 (match_operand:SI 2 "arith_reg_operand" "z")))]
2339 "TARGET_SH2A"
2340 "divs %2,%1"
98e20ffd
NC
2341 [(set_attr "type" "arith")
2342 (set_attr "in_delay_slot" "no")])
157371cf 2343
a512fa97 2344(define_insn "divsi3_i1"
1245df60 2345 [(set (match_operand:SI 0 "register_operand" "=z")
4773afa4
AO
2346 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2347 (clobber (reg:SI T_REG))
2348 (clobber (reg:SI PR_REG))
2349 (clobber (reg:SI R1_REG))
2350 (clobber (reg:SI R2_REG))
2351 (clobber (reg:SI R3_REG))
1245df60 2352 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
05eb5cc3 2353 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
225e4f43
R
2354 "jsr @%1%#"
2355 [(set_attr "type" "sfunc")
2356 (set_attr "needs_delay_slot" "yes")])
2357
fa5322fa
AO
2358(define_insn "divsi3_i1_media"
2359 [(set (match_operand:SI 0 "register_operand" "=z")
2360 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2361 (clobber (reg:SI T_MEDIA_REG))
2362 (clobber (reg:SI PR_MEDIA_REG))
2363 (clobber (reg:SI R1_REG))
9e96203d
R
2364 (clobber (reg:SI R20_REG))
2365 (clobber (reg:SI R21_REG))
73a4d10b 2366 (clobber (reg:SI TR0_REG))
1ed50f71 2367 (use (match_operand 1 "target_reg_operand" "b"))]
73a4d10b 2368 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2ad65b0e
SC
2369 "blink %1, r18"
2370 [(set_attr "type" "sfunc")])
fa5322fa 2371
73a4d10b
R
2372(define_insn "divsi3_media_2"
2373 [(set (match_operand:SI 0 "register_operand" "=z")
2374 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2375 (clobber (reg:SI T_MEDIA_REG))
2376 (clobber (reg:SI PR_MEDIA_REG))
2377 (clobber (reg:SI R1_REG))
2378 (clobber (reg:SI R21_REG))
2379 (clobber (reg:SI TR0_REG))
2380 (use (reg:SI R20_REG))
1ed50f71 2381 (use (match_operand 1 "target_reg_operand" "b"))]
73a4d10b
R
2382 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2383 "blink %1, r18"
2384 [(set_attr "type" "sfunc")])
2385
2386;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2387;; hard reg clobbers and data dependencies that we need when we want
2388;; to rematerialize the division into a call.
2389(define_insn_and_split "divsi_inv_call"
2390 [(set (match_operand:SI 0 "register_operand" "=r")
2391 (div:SI (match_operand:SI 1 "register_operand" "r")
2392 (match_operand:SI 2 "register_operand" "r")))
2393 (clobber (reg:SI R4_REG))
2394 (clobber (reg:SI R5_REG))
2395 (clobber (reg:SI T_MEDIA_REG))
2396 (clobber (reg:SI PR_MEDIA_REG))
2397 (clobber (reg:SI R1_REG))
2398 (clobber (reg:SI R21_REG))
2399 (clobber (reg:SI TR0_REG))
2400 (clobber (reg:SI R20_REG))
2401 (use (match_operand:SI 3 "register_operand" "r"))]
2402 "TARGET_SHMEDIA"
2403 "#"
fae61228 2404 "&& (reload_in_progress || reload_completed)"
73a4d10b
R
2405 [(set (match_dup 0) (match_dup 3))]
2406 ""
2407 [(set_attr "highpart" "must_split")])
2408
2409;; This is the combiner pattern for -mdiv=inv:call .
2410(define_insn_and_split "*divsi_inv_call_combine"
2411 [(set (match_operand:SI 0 "register_operand" "=z")
2412 (div:SI (match_operand:SI 1 "register_operand" "r")
2413 (match_operand:SI 2 "register_operand" "r")))
2414 (clobber (reg:SI R4_REG))
2415 (clobber (reg:SI R5_REG))
2416 (clobber (reg:SI T_MEDIA_REG))
2417 (clobber (reg:SI PR_MEDIA_REG))
2418 (clobber (reg:SI R1_REG))
2419 (clobber (reg:SI R21_REG))
2420 (clobber (reg:SI TR0_REG))
2421 (clobber (reg:SI R20_REG))
2422 (use (unspec:SI [(match_dup 1)
2423 (match_operand:SI 3 "" "")
2424 (unspec:SI [(match_operand:SI 4 "" "")
2425 (match_dup 3)
2426 (match_operand:DI 5 "" "")]
2427 UNSPEC_DIV_INV_M2)
2428 (match_operand:DI 6 "" "")
2429 (const_int 0)
2430 (const_int 0)]
2431 UNSPEC_DIV_INV_M3))]
2432 "TARGET_SHMEDIA"
2433 "#"
fae61228 2434 "&& (reload_in_progress || reload_completed)"
73a4d10b 2435 [(pc)]
73a4d10b
R
2436{
2437 const char *name = sh_divsi3_libfunc;
2438 enum sh_function_kind kind = SFUNC_GOT;
2439 rtx sym;
2440
2441 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2442 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2443 while (TARGET_DIVIDE_INV_CALL2)
2444 {
2445 rtx x = operands[3];
2446
2447 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2448 break;
2449 x = XVECEXP (x, 0, 0);
d9241861 2450 name = "__sdivsi3_2";
73a4d10b
R
2451 kind = SFUNC_STATIC;
2452 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2453 break;
2454 }
2455 sym = function_symbol (NULL, name, kind);
2456 emit_insn (gen_divsi3_media_2 (operands[0], sym));
2457 DONE;
d9241861 2458}
73a4d10b
R
2459 [(set_attr "highpart" "must_split")])
2460
fa5322fa 2461(define_expand "divsi3_i4_media"
51214775
R
2462 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2463 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2464 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
fa5322fa 2465 (set (match_operand:SI 0 "register_operand" "=r")
51214775 2466 (fix:SI (match_dup 5)))]
fa5322fa 2467 "TARGET_SHMEDIA_FPU"
fa5322fa 2468{
51214775 2469 operands[3] = gen_reg_rtx (DFmode);
fa5322fa
AO
2470 operands[4] = gen_reg_rtx (DFmode);
2471 operands[5] = gen_reg_rtx (DFmode);
d9241861 2472})
fa5322fa 2473
225e4f43
R
2474(define_insn "divsi3_i4"
2475 [(set (match_operand:SI 0 "register_operand" "=y")
4773afa4
AO
2476 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2477 (clobber (reg:SI PR_REG))
2478 (clobber (reg:DF DR0_REG))
2479 (clobber (reg:DF DR2_REG))
2480 (use (reg:PSI FPSCR_REG))
225e4f43
R
2481 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2482 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2483 "jsr @%1%#"
2484 [(set_attr "type" "sfunc")
d64264ff 2485 (set_attr "fp_mode" "double")
225e4f43
R
2486 (set_attr "needs_delay_slot" "yes")])
2487
2488(define_insn "divsi3_i4_single"
2489 [(set (match_operand:SI 0 "register_operand" "=y")
4773afa4
AO
2490 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2491 (clobber (reg:SI PR_REG))
2492 (clobber (reg:DF DR0_REG))
2493 (clobber (reg:DF DR2_REG))
2494 (clobber (reg:SI R2_REG))
225e4f43 2495 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
fa5322fa 2496 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
1245df60 2497 "jsr @%1%#"
0d7e008e 2498 [(set_attr "type" "sfunc")
0d7e008e
SC
2499 (set_attr "needs_delay_slot" "yes")])
2500
b368d6b8
R
2501(define_insn "divsi3_i4_int"
2502 [(set (match_operand:SI 0 "register_operand" "=z")
2503 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2504 (clobber (reg:SI T_REG))
2505 (clobber (reg:SI PR_REG))
2506 (clobber (reg:SI R1_REG))
95ec2af0
KK
2507 (clobber (reg:SI MACH_REG))
2508 (clobber (reg:SI MACL_REG))
b368d6b8
R
2509 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2510 "TARGET_SH1"
2511 "jsr @%1%#"
2512 [(set_attr "type" "sfunc")
2513 (set_attr "needs_delay_slot" "yes")])
2514
0d7e008e 2515(define_expand "divsi3"
a512fa97 2516 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
4773afa4
AO
2517 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2518 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
ffae286a 2519 (parallel [(set (match_operand:SI 0 "register_operand" "")
4773afa4
AO
2520 (div:SI (reg:SI R4_REG)
2521 (reg:SI R5_REG)))
2522 (clobber (reg:SI T_REG))
2523 (clobber (reg:SI PR_REG))
2524 (clobber (reg:SI R1_REG))
2525 (clobber (reg:SI R2_REG))
2526 (clobber (reg:SI R3_REG))
ffae286a 2527 (use (match_dup 3))])]
0d7e008e 2528 ""
225e4f43 2529{
ba56ed65 2530 rtx last;
a512fa97 2531
fa5322fa 2532 operands[3] = gen_reg_rtx (Pmode);
a512fa97 2533 /* Emit the move of the address to a pseudo outside of the libcall. */
b368d6b8
R
2534 if (TARGET_DIVIDE_CALL_TABLE)
2535 {
2536 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2537 last = gen_divsi3_i4_int (operands[0], operands[3]);
2538 }
2539 else if (TARGET_DIVIDE_CALL_FP)
225e4f43 2540 {
73a4d10b 2541 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
225e4f43 2542 if (TARGET_FPU_SINGLE)
a512fa97 2543 last = gen_divsi3_i4_single (operands[0], operands[3]);
225e4f43 2544 else
a512fa97 2545 last = gen_divsi3_i4 (operands[0], operands[3]);
225e4f43 2546 }
157371cf
AO
2547 else if (TARGET_SH2A)
2548 {
2549 operands[1] = force_reg (SImode, operands[1]);
2550 operands[2] = force_reg (SImode, operands[2]);
2551 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2552 DONE;
2553 }
73a4d10b
R
2554 else if (TARGET_DIVIDE_INV)
2555 {
2556 rtx dividend = operands[1];
2557 rtx divisor = operands[2];
2558 rtx tab_base;
2559 rtx nsb_res = gen_reg_rtx (DImode);
2560 rtx norm64 = gen_reg_rtx (DImode);
2561 rtx tab_ix = gen_reg_rtx (DImode);
2562 rtx norm32 = gen_reg_rtx (SImode);
2563 rtx i92 = force_reg (DImode, GEN_INT (92));
2564 rtx scratch0a = gen_reg_rtx (DImode);
2565 rtx scratch0b = gen_reg_rtx (DImode);
2566 rtx inv0 = gen_reg_rtx (SImode);
2567 rtx scratch1a = gen_reg_rtx (DImode);
2568 rtx scratch1b = gen_reg_rtx (DImode);
2569 rtx shift = gen_reg_rtx (DImode);
2570 rtx i2p27, i43;
2571 rtx inv1 = gen_reg_rtx (SImode);
2572 rtx scratch2a = gen_reg_rtx (DImode);
2573 rtx scratch2b = gen_reg_rtx (SImode);
2574 rtx inv2 = gen_reg_rtx (SImode);
2575 rtx scratch3a = gen_reg_rtx (DImode);
2576 rtx scratch3b = gen_reg_rtx (DImode);
2577 rtx scratch3c = gen_reg_rtx (DImode);
2578 rtx scratch3d = gen_reg_rtx (SImode);
2579 rtx scratch3e = gen_reg_rtx (DImode);
2580 rtx result = gen_reg_rtx (SImode);
2581
2582 if (! arith_reg_or_0_operand (dividend, SImode))
2583 dividend = force_reg (SImode, dividend);
2584 if (! arith_reg_operand (divisor, SImode))
2585 divisor = force_reg (SImode, divisor);
2586 if (flag_pic && Pmode != DImode)
2587 {
d9241861 2588 tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
73a4d10b
R
2589 tab_base = gen_datalabel_ref (tab_base);
2590 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2591 }
2592 else
2593 {
d9241861 2594 tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
73a4d10b
R
2595 tab_base = gen_datalabel_ref (tab_base);
2596 tab_base = force_reg (DImode, tab_base);
2597 }
2598 if (TARGET_DIVIDE_INV20U)
2599 i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2600 else
2601 i2p27 = GEN_INT (0);
2602 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2603 i43 = force_reg (DImode, GEN_INT (43));
2604 else
2605 i43 = GEN_INT (0);
2606 emit_insn (gen_nsbdi (nsb_res,
2607 simplify_gen_subreg (DImode, divisor, SImode, 0)));
2608 emit_insn (gen_ashldi3_media (norm64,
2609 gen_rtx_SUBREG (DImode, divisor, 0),
2610 nsb_res));
2611 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2612 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2613 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2614 inv0, scratch0a, scratch0b,
2615 scratch1a, scratch1b));
2616 emit_insn (gen_subdi3 (shift, i92, nsb_res));
2617 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2618 scratch2a));
2619 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2620 i2p27, i43,
2621 scratch3a, scratch3b, scratch3c,
2622 scratch2a, scratch2b, scratch3d, scratch3e));
2623 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2624 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2625 else if (TARGET_DIVIDE_INV_FP)
2626 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2627 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2628 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2629 gen_reg_rtx (DFmode)));
2630 else
2631 emit_move_insn (operands[0], result);
2632 DONE;
2633 }
2634 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
51214775
R
2635 {
2636 operands[1] = force_reg (SImode, operands[1]);
2637 operands[2] = force_reg (SImode, operands[2]);
4392ebd3
RS
2638 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2639 DONE;
51214775 2640 }
fa5322fa
AO
2641 else if (TARGET_SH5)
2642 {
73a4d10b
R
2643 if (TARGET_DIVIDE_CALL2)
2644 {
d9241861 2645 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
73a4d10b
R
2646 tab_base = gen_datalabel_ref (tab_base);
2647 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2648 }
2649 if (TARGET_FPU_ANY && TARGET_SH1)
2650 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2651 else if (TARGET_DIVIDE_CALL2)
d9241861 2652 function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
73a4d10b
R
2653 else
2654 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
fa5322fa
AO
2655
2656 if (TARGET_SHMEDIA)
73a4d10b
R
2657 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2658 (operands[0], operands[3]));
fa5322fa
AO
2659 else if (TARGET_FPU_ANY)
2660 last = gen_divsi3_i4_single (operands[0], operands[3]);
2661 else
2662 last = gen_divsi3_i1 (operands[0], operands[3]);
2663 }
a512fa97
R
2664 else
2665 {
73a4d10b 2666 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
a512fa97
R
2667 last = gen_divsi3_i1 (operands[0], operands[3]);
2668 }
ba56ed65 2669 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
4392ebd3 2670 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
ba56ed65 2671 emit_insn (last);
a512fa97 2672 DONE;
d9241861 2673})
73a4d10b 2674
62bf45a5
PB
2675;; operands: scratch, tab_base, tab_ix
2676;; These are unspecs because we could generate an indexed addressing mode
2677;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2678;; confuse reload. See PR27117.
2679
2680(define_insn "divsi_inv_qitable"
2681 [(set (match_operand:DI 0 "register_operand" "=r")
2682 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2683 (match_operand:DI 2 "register_operand" "r")]
2684 UNSPEC_DIV_INV_TABLE)))]
2685 "TARGET_SHMEDIA"
35ed5a70 2686 "ldx.ub %1, %2, %0"
62bf45a5
PB
2687 [(set_attr "type" "load_media")
2688 (set_attr "highpart" "user")])
2689
2690;; operands: scratch, tab_base, tab_ix
2691(define_insn "divsi_inv_hitable"
2692 [(set (match_operand:DI 0 "register_operand" "=r")
2693 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2694 (match_operand:DI 2 "register_operand" "r")]
2695 UNSPEC_DIV_INV_TABLE)))]
2696 "TARGET_SHMEDIA"
35ed5a70 2697 "ldx.w %1, %2, %0"
62bf45a5
PB
2698 [(set_attr "type" "load_media")
2699 (set_attr "highpart" "user")])
2700
73a4d10b
R
2701;; operands: inv0, tab_base, tab_ix, norm32
2702;; scratch equiv in sdivsi3_2: r19, r21
2703(define_expand "divsi_inv_m0"
2704 [(set (match_operand:SI 0 "register_operand" "=r")
2705 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2706 (match_operand:DI 2 "register_operand" "r")
2707 (match_operand:SI 3 "register_operand" "r")]
2708 UNSPEC_DIV_INV_M0))
2709 (clobber (match_operand:DI 4 "register_operand" "=r"))
2710 (clobber (match_operand:DI 5 "register_operand" "=r"))]
2711 "TARGET_SHMEDIA"
73a4d10b
R
2712{
2713/*
2714tab_base: r20
2715tab_ix: r21
2716norm32: r25
2717 ldx.ub r20, r21, r19 // u0.8
2718 shlli r21, 1, r21
2719 muls.l r25, r19, r19 // s2.38
2720 ldx.w r20, r21, r21 // s2.14
2721 shari r19, 24, r19 // truncate to s2.14
2722 sub r21, r19, r19 // some 11 bit inverse in s1.14
2723*/
2724
2725 rtx inv0 = operands[0];
2726 rtx tab_base = operands[1];
2727 rtx tab_ix = operands[2];
2728 rtx norm32 = operands[3];
2729 rtx scratch0 = operands[4];
32ed5fcc 2730 rtx scratch0_si = gen_lowpart (SImode, scratch0);
73a4d10b 2731 rtx scratch1 = operands[5];
73a4d10b 2732
62bf45a5 2733 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
73a4d10b
R
2734 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2735 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
62bf45a5 2736 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
73a4d10b
R
2737 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2738 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2739 DONE;
d9241861 2740})
73a4d10b
R
2741
2742;; operands: inv1, tab_base, tab_ix, norm32
2743(define_insn_and_split "divsi_inv_m1"
2744 [(set (match_operand:SI 0 "register_operand" "=r")
2745 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2746 (match_operand:DI 2 "register_operand" "r")
2747 (match_operand:SI 3 "register_operand" "r")]
2748 UNSPEC_DIV_INV_M1))
2749 (clobber (match_operand:SI 4 "register_operand" "=r"))
2750 (clobber (match_operand:DI 5 "register_operand" "=r"))
2751 (clobber (match_operand:DI 6 "register_operand" "=r"))
2752 (clobber (match_operand:DI 7 "register_operand" "=r"))
2753 (clobber (match_operand:DI 8 "register_operand" "=r"))]
2754 "TARGET_SHMEDIA"
2755 "#"
b3a13419 2756 "&& !can_create_pseudo_p ()"
73a4d10b 2757 [(pc)]
73a4d10b
R
2758{
2759/* inv0: r19
2760 muls.l r19, r19, r18 // u0.28
2761 muls.l r25, r18, r18 // s2.58
2762 shlli r19, 45, r0 // multiply by two and convert to s2.58
2763 sub r0, r18, r18
2764 shari r18, 28, r18 // some 18 bit inverse in s1.30
2765*/
2766
2767 rtx inv1 = operands[0];
2768 rtx tab_base = operands[1];
2769 rtx tab_ix = operands[2];
2770 rtx norm32 = operands[3];
2771 rtx inv0 = operands[4];
2772 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2773 rtx scratch0a = operands[5];
2774 rtx scratch0b = operands[6];
2775 rtx scratch0 = operands[7];
2776 rtx scratch1 = operands[8];
32ed5fcc 2777 rtx scratch1_si = gen_lowpart (SImode, scratch1);
73a4d10b
R
2778
2779 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2780 scratch0a, scratch0b));
2781 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2782 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2783 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2784 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2785 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2786 DONE;
d9241861 2787})
73a4d10b
R
2788
2789;; operands: inv2, norm32, inv1, i92
2790(define_insn_and_split "divsi_inv_m2"
2791 [(set (match_operand:SI 0 "register_operand" "=r")
2792 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2793 (match_operand:SI 2 "register_operand" "r")
2794 (match_operand:DI 3 "register_operand" "r")]
2795 UNSPEC_DIV_INV_M2))
2796 (clobber (match_operand:DI 4 "register_operand" "=r"))]
2797 "TARGET_SHMEDIA"
2798 "#"
b3a13419 2799 "&& !can_create_pseudo_p ()"
73a4d10b 2800 [(pc)]
73a4d10b
R
2801{
2802/*
2803 muls.l r18, r25, r0 // s2.60
2804 shari r0, 16, r0 // s-16.44
2805 sub
2806 muls.l r0, r18, r19 // s-16.74
2807 shari r19, 30, r19 // s-16.44
2808*/
2809 rtx inv2 = operands[0];
2810 rtx norm32 = operands[1];
2811 rtx inv1 = operands[2];
2812 rtx i92 = operands[3];
2813 rtx scratch0 = operands[4];
32ed5fcc 2814 rtx scratch0_si = gen_lowpart (SImode, scratch0);
73a4d10b
R
2815
2816 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2817 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2818 emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2819 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2820 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2821 DONE;
d9241861 2822})
73a4d10b
R
2823
2824(define_insn_and_split "divsi_inv_m3"
2825 [(set (match_operand:SI 0 "register_operand" "=r")
2826 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2827 (match_operand:SI 2 "register_operand" "r")
2828 (match_operand:SI 3 "register_operand" "r")
2829 (match_operand:DI 4 "register_operand" "r")
2830 (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2831 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2832 UNSPEC_DIV_INV_M3))
2833 (clobber (match_operand:DI 7 "register_operand" "=r"))
2834 (clobber (match_operand:DI 8 "register_operand" "=r"))
2835 (clobber (match_operand:DI 9 "register_operand" "=r"))
2836 (clobber (match_operand:DI 10 "register_operand" "=r"))
2837 (clobber (match_operand:SI 11 "register_operand" "=r"))
2838 (clobber (match_operand:SI 12 "register_operand" "=r"))
2839 (clobber (match_operand:DI 13 "register_operand" "=r"))]
2840 "TARGET_SHMEDIA"
2841 "#"
b3a13419 2842 "&& !can_create_pseudo_p ()"
73a4d10b 2843 [(pc)]
73a4d10b
R
2844{
2845/*
2846 r0: result r1: shift r4: dividend r18: inv1 r19: inv2
2847 r0: scratch0 r19: scratch1 r21: scratch2
2848
2849 muls.l r18, r4, r25 // s32.30
2850 muls.l r19, r4, r19 // s15.30
2851 shari r25, 63, r21
2852 shari r19, 14, r19 // s18.-14
2853 sub r25, r19, r0
2854 shard r0, r1, r0
2855 sub r0, r21, r0
2856*/
2857
2858 rtx result = operands[0];
2859 rtx dividend = operands[1];
2860 rtx inv1 = operands[2];
2861 rtx inv2 = operands[3];
2862 rtx shift = operands[4];
2863 rtx scratch0 = operands[7];
2864 rtx scratch1 = operands[8];
2865 rtx scratch2 = operands[9];
2866
cd9a21ca
KK
2867 if (satisfies_constraint_N (dividend))
2868 {
2869 emit_move_insn (result, dividend);
2870 DONE;
2871 }
2872
73a4d10b
R
2873 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2874 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2875 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2876 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2877 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2878 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2879 emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2880 DONE;
d9241861 2881})
73a4d10b
R
2882
2883;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2884;; inv1: tab_base, tab_ix, norm32
2885;; inv2: norm32, inv1, i92
2886(define_insn_and_split "divsi_inv_m1_3"
2887 [(set (match_operand:SI 0 "register_operand" "=r")
2888 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2889 (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2890 (match_operand:DI 3 "register_operand" "r")
2891 (match_operand:SI 4 "register_operand" "r")]
2892 UNSPEC_DIV_INV_M1)
2893 (unspec:SI [(match_dup 4)
2894 (unspec:SI [(match_dup 2)
2895 (match_dup 3)
2896 (match_dup 4)] UNSPEC_DIV_INV_M1)
2897 (match_operand:SI 5 "" "")]
2898 UNSPEC_DIV_INV_M2)
2899 (match_operand:DI 6 "register_operand" "r")
2900 (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2901 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2902 UNSPEC_DIV_INV_M3))
2903 (clobber (match_operand:DI 9 "register_operand" "=r"))
2904 (clobber (match_operand:DI 10 "register_operand" "=r"))
2905 (clobber (match_operand:DI 11 "register_operand" "=r"))
2906 (clobber (match_operand:DI 12 "register_operand" "=r"))
2907 (clobber (match_operand:SI 13 "register_operand" "=r"))
2908 (clobber (match_operand:SI 14 "register_operand" "=r"))
2909 (clobber (match_operand:DI 15 "register_operand" "=r"))]
2910 "TARGET_SHMEDIA
2911 && (TARGET_DIVIDE_INV_MINLAT
2912 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2913 "#"
b3a13419 2914 "&& !can_create_pseudo_p ()"
73a4d10b 2915 [(pc)]
73a4d10b
R
2916{
2917 rtx result = operands[0];
2918 rtx dividend = operands[1];
2919 rtx tab_base = operands[2];
2920 rtx tab_ix = operands[3];
2921 rtx norm32 = operands[4];
2922 /* rtx i92 = operands[5]; */
2923 rtx shift = operands[6];
2924 rtx i2p27 = operands[7];
2925 rtx i43 = operands[8];
2926 rtx scratch0 = operands[9];
32ed5fcc 2927 rtx scratch0_si = gen_lowpart (SImode, scratch0);
73a4d10b 2928 rtx scratch1 = operands[10];
32ed5fcc 2929 rtx scratch1_si = gen_lowpart (SImode, scratch1);
73a4d10b
R
2930 rtx scratch2 = operands[11];
2931 rtx scratch3 = operands[12];
2932 rtx scratch4 = operands[13];
2933 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2934 rtx scratch5 = operands[14];
2935 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2936 rtx scratch6 = operands[15];
2937
2938 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2939 scratch0, scratch1));
2940 /* inv0 == scratch4 */
2941 if (! TARGET_DIVIDE_INV20U)
2942 {
2943 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2944 i2p27 = scratch0;
2945 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2946 }
2947 else
2948 {
2949 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2950 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2951 }
2952 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2953 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2954 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2955 /* inv1 == scratch4 */
2956
2957 if (TARGET_DIVIDE_INV_MINLAT)
2958 {
2959 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2960 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2961 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2962 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2963 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2964 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2965 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2966 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2967 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2968 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2969 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2970 }
2971 else
2972 {
2973 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2974 /* Use separate scratch regs for nsb and sign to allow scheduling. */
2975 emit_insn (gen_nsbdi (scratch6,
2976 simplify_gen_subreg (DImode, dividend, SImode, 0)));
2977 emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2978 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2979 emit_insn (gen_divsi_inv20 (scratch2,
2980 norm32, scratch4, dividend,
2981 scratch6, scratch3, i43,
2982 /* scratch0 may be shared with i2p27. */
2983 scratch0, scratch1, scratch5,
2984 label, label, i2p27));
2985 }
2986 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2987 emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2988 DONE;
d9241861 2989})
73a4d10b
R
2990
2991(define_insn "divsi_inv20"
2992 [(set (match_operand:DI 0 "register_operand" "=&r")
2993 (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2994 (match_operand:SI 2 "register_operand" "r")
2995 (match_operand:SI 3 "register_operand" "r")
2996 (match_operand:DI 4 "register_operand" "r")
2997 (match_operand:DI 5 "register_operand" "r")
2998 (match_operand:DI 6 "register_operand" "r")
2999 (match_operand:DI 12 "register_operand" "r")
3000 (match_operand 10 "target_operand" "b")
3001 (match_operand 11 "immediate_operand" "i")]
3002 UNSPEC_DIV_INV20))
3003 (clobber (match_operand:DI 7 "register_operand" "=&r"))
3004 (clobber (match_operand:DI 8 "register_operand" "=&r"))
3005 (clobber (match_operand:SI 9 "register_operand" "=r"))]
3006 "TARGET_SHMEDIA
3007 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
73a4d10b
R
3008{
3009/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
3010 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
3011 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
3012 %10 label (tr), %11 label (imm)
3013
3014 muls.l inv1, norm32, scratch0 // s2.60
3015 muls.l inv1, dividend, result // s32.30
3016 xor i2p27, result_sign, round_scratch
3017 bge/u dividend_nsb, i43, tr.. (label)
3018 shari scratch0, 16, scratch0 // s-16.44
3019 muls.l sratch0_si, inv1, scratch0 // s-16.74
3020 sub result, round_scratch, result
3021 shari dividend, 14, scratch1 // s19.-14
3022 shari scratch0, 30, scratch0 // s-16.44
3023 muls.l scratch0, scratch1, round_scratch // s15.30
3024label:
3025 sub result, round_scratch, result */
3026
35ed5a70
OE
3027 const bool likely = TARGET_DIVIDE_INV20L;
3028 if (likely)
3029 return
3030 "muls.l %2, %3, %0" "\n"
3031 " xor %12, %5, %7" "\n"
3032 " bge/l %4, %6, %10" "\n"
3033 " muls.l %2, %1, %8" "\n"
3034 " shari %8, 16, %8" "\n"
3035 " muls.l %8, %2, %8" "\n"
3036 " shari %3, 14, %9" "\n"
3037 " shari %8, 30, %8" "\n"
3038 " muls.l %8, %9, %8" "\n"
3039 " sub %0, %8, %0" "\n"
3040 "%11: add %0, %7, %0";
3041 else
3042 return
3043 "muls.l %2, %1, %8" "\n"
3044 " muls.l %2, %3, %0" "\n"
3045 " xor %12, %5, %7" "\n"
3046 " bge/u %4, %6, %10" "\n"
3047 " shari %8, 16, %8" "\n"
3048 " muls.l %8, %2, %8" "\n"
3049 " sub %0, %7, %0" "\n"
3050 " shari %3, 14, %9" "\n"
3051 " shari %8, 30, %8" "\n"
3052 " muls.l %8, %9, %7" "\n"
3053 "%11: sub %0, %7, %0";
d9241861 3054})
73a4d10b
R
3055
3056(define_insn_and_split "divsi_inv_fp"
3057 [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3058 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3059 (match_operand:SI 2 "register_operand" "rf")))
3060 (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3061 (clobber (match_operand:SI 4 "register_operand" "=r"))
3062 (clobber (match_operand:SI 5 "register_operand" "=r"))
3063 (clobber (match_operand:DF 6 "register_operand" "=r"))
3064 (clobber (match_operand:DF 7 "register_operand" "=r"))
3065 (clobber (match_operand:DF 8 "register_operand" "=r"))]
3066 "TARGET_SHMEDIA_FPU"
3067 "#"
fae61228 3068 "&& (reload_in_progress || reload_completed)"
73a4d10b
R
3069 [(set (match_dup 0) (match_dup 3))]
3070 ""
3071 [(set_attr "highpart" "must_split")])
3072
3073;; If a matching group of divide-by-inverse instructions is in the same
3074;; basic block after gcse & loop optimizations, we want to transform them
3075;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3076(define_insn_and_split "*divsi_inv_fp_combine"
3077 [(set (match_operand:SI 0 "register_operand" "=f")
3078 (div:SI (match_operand:SI 1 "register_operand" "f")
3079 (match_operand:SI 2 "register_operand" "f")))
3080 (use (unspec:SI [(match_dup 1)
3081 (match_operand:SI 3 "" "")
3082 (unspec:SI [(match_operand:SI 4 "" "")
3083 (match_dup 3)
3084 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3085 (match_operand:DI 6 "" "")
3086 (const_int 0)
3087 (const_int 0)] UNSPEC_DIV_INV_M3))
3088 (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3089 (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3090 (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3091 (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3092 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
b3a13419 3093 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
73a4d10b
R
3094 "#"
3095 "&& 1"
3096 [(set (match_dup 9) (float:DF (match_dup 1)))
3097 (set (match_dup 10) (float:DF (match_dup 2)))
3098 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3099 (set (match_dup 8)
3100 (fix:SI (match_dup 11)))
3101 (set (match_dup 0) (match_dup 8))]
73a4d10b
R
3102{
3103 if (! fp_arith_reg_operand (operands[1], SImode))
3104 {
3105 emit_move_insn (operands[7], operands[1]);
3106 operands[1] = operands[7];
3107 }
3108 if (! fp_arith_reg_operand (operands[2], SImode))
3109 {
3110 emit_move_insn (operands[8], operands[2]);
3111 operands[2] = operands[8];
3112 }
d9241861 3113}
73a4d10b 3114 [(set_attr "highpart" "must_split")])
0d7e008e
SC
3115\f
3116;; -------------------------------------------------------------------------
3117;; Multiplication instructions
3118;; -------------------------------------------------------------------------
3119
a512fa97 3120(define_insn "umulhisi3_i"
4773afa4
AO
3121 [(set (reg:SI MACL_REG)
3122 (mult:SI (zero_extend:SI
3123 (match_operand:HI 0 "arith_reg_operand" "r"))
3124 (zero_extend:SI
3125 (match_operand:HI 1 "arith_reg_operand" "r"))))]
fa5322fa 3126 "TARGET_SH1"
e9a9e960 3127 "mulu.w %1,%0"
b9654711 3128 [(set_attr "type" "smpy")])
bc45ade3 3129
a512fa97 3130(define_insn "mulhisi3_i"
4773afa4 3131 [(set (reg:SI MACL_REG)
bc45ade3 3132 (mult:SI (sign_extend:SI
af55dae3 3133 (match_operand:HI 0 "arith_reg_operand" "r"))
bc45ade3 3134 (sign_extend:SI
af55dae3 3135 (match_operand:HI 1 "arith_reg_operand" "r"))))]
fa5322fa 3136 "TARGET_SH1"
e9a9e960 3137 "muls.w %1,%0"
b9654711 3138 [(set_attr "type" "smpy")])
bc45ade3
SC
3139
3140(define_expand "mulhisi3"
4773afa4 3141 [(set (reg:SI MACL_REG)
bc45ade3 3142 (mult:SI (sign_extend:SI
51aea58d 3143 (match_operand:HI 1 "arith_reg_operand" ""))
bc45ade3 3144 (sign_extend:SI
51aea58d
JW
3145 (match_operand:HI 2 "arith_reg_operand" ""))))
3146 (set (match_operand:SI 0 "arith_reg_operand" "")
4773afa4 3147 (reg:SI MACL_REG))]
fa5322fa 3148 "TARGET_SH1"
a512fa97 3149{
ba56ed65
KK
3150 rtx insn, macl;
3151
3152 macl = gen_rtx_REG (SImode, MACL_REG);
3153 start_sequence ();
3154 emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3155 insn = get_insns ();
3156 end_sequence ();
c49439f1
R
3157 /* expand_binop can't find a suitable code in umul_widen_optab to
3158 make a REG_EQUAL note from, so make one here.
3159 See also smulsi3_highpart.
3160 ??? Alternatively, we could put this at the calling site of expand_binop,
3161 i.e. expand_expr. */
ba56ed65
KK
3162 /* Use emit_libcall_block for loop invariant code motion and to make
3163 a REG_EQUAL note. */
3164 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
bd94cb6e 3165
a512fa97 3166 DONE;
d9241861 3167})
bc45ade3
SC
3168
3169(define_expand "umulhisi3"
4773afa4 3170 [(set (reg:SI MACL_REG)
bc45ade3 3171 (mult:SI (zero_extend:SI
51aea58d 3172 (match_operand:HI 1 "arith_reg_operand" ""))
bc45ade3 3173 (zero_extend:SI
51aea58d
JW
3174 (match_operand:HI 2 "arith_reg_operand" ""))))
3175 (set (match_operand:SI 0 "arith_reg_operand" "")
4773afa4 3176 (reg:SI MACL_REG))]
fa5322fa 3177 "TARGET_SH1"
a512fa97 3178{
ba56ed65
KK
3179 rtx insn, macl;
3180
3181 macl = gen_rtx_REG (SImode, MACL_REG);
3182 start_sequence ();
3183 emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3184 insn = get_insns ();
3185 end_sequence ();
c49439f1
R
3186 /* expand_binop can't find a suitable code in umul_widen_optab to
3187 make a REG_EQUAL note from, so make one here.
3188 See also smulsi3_highpart.
3189 ??? Alternatively, we could put this at the calling site of expand_binop,
3190 i.e. expand_expr. */
ba56ed65
KK
3191 /* Use emit_libcall_block for loop invariant code motion and to make
3192 a REG_EQUAL note. */
3193 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
bd94cb6e 3194
a512fa97 3195 DONE;
d9241861 3196})
bc45ade3 3197
0d7e008e
SC
3198;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3199;; a call to a routine which clobbers known registers.
3200
3201(define_insn ""
e96a50cc 3202 [(set (match_operand:SI 1 "register_operand" "=z")
4773afa4
AO
3203 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3204 (clobber (reg:SI MACL_REG))
3205 (clobber (reg:SI T_REG))
3206 (clobber (reg:SI PR_REG))
3207 (clobber (reg:SI R3_REG))
3208 (clobber (reg:SI R2_REG))
3209 (clobber (reg:SI R1_REG))
07a45e5c 3210 (use (match_operand:SI 0 "arith_reg_operand" "r"))]
fa5322fa 3211 "TARGET_SH1"
0d7e008e
SC
3212 "jsr @%0%#"
3213 [(set_attr "type" "sfunc")
0d7e008e
SC
3214 (set_attr "needs_delay_slot" "yes")])
3215
3216(define_expand "mulsi3_call"
4773afa4
AO
3217 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3218 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
51aea58d 3219 (parallel[(set (match_operand:SI 0 "register_operand" "")
4773afa4
AO
3220 (mult:SI (reg:SI R4_REG)
3221 (reg:SI R5_REG)))
3222 (clobber (reg:SI MACL_REG))
3223 (clobber (reg:SI T_REG))
3224 (clobber (reg:SI PR_REG))
3225 (clobber (reg:SI R3_REG))
3226 (clobber (reg:SI R2_REG))
3227 (clobber (reg:SI R1_REG))
225e4f43 3228 (use (match_operand:SI 3 "register_operand" ""))])]
fa5322fa 3229 "TARGET_SH1"
225e4f43 3230 "")
07a45e5c 3231
157371cf 3232(define_insn "mul_r"
73a4d10b 3233 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
157371cf
AO
3234 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3235 (match_operand:SI 2 "arith_reg_operand" "z")))]
3236 "TARGET_SH2A"
3237 "mulr %2,%0"
3238 [(set_attr "type" "dmpy")])
3239
0d7e008e 3240(define_insn "mul_l"
4773afa4 3241 [(set (reg:SI MACL_REG)
0d7e008e
SC
3242 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3243 (match_operand:SI 1 "arith_reg_operand" "r")))]
3244 "TARGET_SH2"
3245 "mul.l %1,%0"
51bd623f 3246 [(set_attr "type" "dmpy")])
0d7e008e
SC
3247
3248(define_expand "mulsi3"
4773afa4 3249 [(set (reg:SI MACL_REG)
51aea58d
JW
3250 (mult:SI (match_operand:SI 1 "arith_reg_operand" "")
3251 (match_operand:SI 2 "arith_reg_operand" "")))
3252 (set (match_operand:SI 0 "arith_reg_operand" "")
4773afa4 3253 (reg:SI MACL_REG))]
fa5322fa 3254 "TARGET_SH1"
51bd623f
JW
3255{
3256 if (!TARGET_SH2)
3257 {
225e4f43
R
3258 /* The address must be set outside the libcall,
3259 since it goes into a pseudo. */
d9241861 3260 rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
a6f463a0
AO
3261 rtx addr = force_reg (SImode, sym);
3262 rtx insns = gen_mulsi3_call (operands[0], operands[1],
3263 operands[2], addr);
ba56ed65 3264 emit_insn (insns);
51bd623f 3265 }
225e4f43
R
3266 else
3267 {
3268 rtx macl = gen_rtx_REG (SImode, MACL_REG);
aa4778b6 3269
ba56ed65 3270 emit_insn (gen_mul_l (operands[1], operands[2]));
aa4778b6
R
3271 /* consec_sets_giv can only recognize the first insn that sets a
3272 giv as the giv insn. So we must tag this also with a REG_EQUAL
3273 note. */
ba56ed65 3274 emit_insn (gen_movsi_i ((operands[0]), macl));
225e4f43 3275 }
225e4f43 3276 DONE;
d9241861 3277})
00f8ff66 3278
af55dae3 3279(define_insn "mulsidi3_i"
4773afa4 3280 [(set (reg:SI MACH_REG)
a512fa97 3281 (truncate:SI
4773afa4
AO
3282 (lshiftrt:DI
3283 (mult:DI
3284 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3285 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3286 (const_int 32))))
3287 (set (reg:SI MACL_REG)
a512fa97
R
3288 (mult:SI (match_dup 0)
3289 (match_dup 1)))]
06e1bace 3290 "TARGET_SH2"
af55dae3 3291 "dmuls.l %1,%0"
0d7e008e
SC
3292 [(set_attr "type" "dmpy")])
3293
fa5322fa 3294(define_expand "mulsidi3"
ee04b091
OE
3295 [(set (match_operand:DI 0 "arith_reg_dest" "")
3296 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3297 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
fa5322fa 3298 "TARGET_SH2 || TARGET_SHMEDIA"
fa5322fa
AO
3299{
3300 if (TARGET_SH2)
3301 {
d9241861
OE
3302 emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3303 DONE;
fa5322fa 3304 }
d9241861 3305})
fa5322fa
AO
3306
3307(define_insn "mulsidi3_media"
73a4d10b 3308 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
b6d33983
R
3309 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3310 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
fa5322fa 3311 "TARGET_SHMEDIA"
b6d33983 3312 "muls.l %1, %2, %0"
73a4d10b
R
3313 [(set_attr "type" "dmpy_media")
3314 (set_attr "highpart" "ignore")])
52702ae1 3315
ee04b091 3316(define_insn_and_split "mulsidi3_compact"
73a4d10b 3317 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4773afa4
AO
3318 (mult:DI
3319 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3320 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
5d00b10a
AO
3321 (clobber (reg:SI MACH_REG))
3322 (clobber (reg:SI MACL_REG))]
a512fa97 3323 "TARGET_SH2"
ee04b091
OE
3324 "#"
3325 "&& 1"
a512fa97 3326 [(const_int 0)]
af55dae3 3327{
a512fa97
R
3328 rtx low_dst = gen_lowpart (SImode, operands[0]);
3329 rtx high_dst = gen_highpart (SImode, operands[0]);
0d7e008e 3330
a512fa97 3331 emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
af55dae3 3332
4773afa4
AO
3333 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3334 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
a512fa97
R
3335 /* We need something to tag the possible REG_EQUAL notes on to. */
3336 emit_move_insn (operands[0], operands[0]);
3337 DONE;
d9241861 3338})
af55dae3
JW
3339
3340(define_insn "umulsidi3_i"
4773afa4 3341 [(set (reg:SI MACH_REG)
a512fa97 3342 (truncate:SI
4773afa4
AO
3343 (lshiftrt:DI
3344 (mult:DI
3345 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3346 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3347 (const_int 32))))
3348 (set (reg:SI MACL_REG)
a512fa97
R
3349 (mult:SI (match_dup 0)
3350 (match_dup 1)))]
06e1bace 3351 "TARGET_SH2"
af55dae3 3352 "dmulu.l %1,%0"
0d7e008e
SC
3353 [(set_attr "type" "dmpy")])
3354
fa5322fa 3355(define_expand "umulsidi3"
ee04b091
OE
3356 [(set (match_operand:DI 0 "arith_reg_dest" "")
3357 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3358 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
fa5322fa 3359 "TARGET_SH2 || TARGET_SHMEDIA"
fa5322fa
AO
3360{
3361 if (TARGET_SH2)
3362 {
d9241861
OE
3363 emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3364 DONE;
fa5322fa 3365 }
d9241861 3366})
fa5322fa
AO
3367
3368(define_insn "umulsidi3_media"
73a4d10b 3369 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
b6d33983
R
3370 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3371 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
fa5322fa 3372 "TARGET_SHMEDIA"
b6d33983 3373 "mulu.l %1, %2, %0"
73a4d10b
R
3374 [(set_attr "type" "dmpy_media")
3375 (set_attr "highpart" "ignore")])
52702ae1 3376
ee04b091 3377(define_insn_and_split "umulsidi3_compact"
73a4d10b 3378 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4773afa4
AO
3379 (mult:DI
3380 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3381 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
5d00b10a
AO
3382 (clobber (reg:SI MACH_REG))
3383 (clobber (reg:SI MACL_REG))]
a512fa97 3384 "TARGET_SH2"
ee04b091
OE
3385 "#"
3386 "&& 1"
a512fa97 3387 [(const_int 0)]
af55dae3 3388{
a512fa97
R
3389 rtx low_dst = gen_lowpart (SImode, operands[0]);
3390 rtx high_dst = gen_highpart (SImode, operands[0]);
af55dae3 3391
a512fa97 3392 emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
af55dae3 3393
4773afa4
AO
3394 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3395 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
a512fa97
R
3396 /* We need something to tag the possible REG_EQUAL notes on to. */
3397 emit_move_insn (operands[0], operands[0]);
3398 DONE;
d9241861 3399})
06e1bace 3400
a512fa97 3401(define_insn "smulsi3_highpart_i"
4773afa4 3402 [(set (reg:SI MACH_REG)
06e1bace 3403 (truncate:SI
4773afa4
AO
3404 (lshiftrt:DI
3405 (mult:DI
3406 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3407 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3408 (const_int 32))))
3409 (clobber (reg:SI MACL_REG))]
06e1bace 3410 "TARGET_SH2"
af55dae3 3411 "dmuls.l %1,%0"
06e1bace
RK
3412 [(set_attr "type" "dmpy")])
3413
3414(define_expand "smulsi3_highpart"
4773afa4
AO
3415 [(parallel
3416 [(set (reg:SI MACH_REG)
3417 (truncate:SI
3418 (lshiftrt:DI
3419 (mult:DI
3420 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3421 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3422 (const_int 32))))
3423 (clobber (reg:SI MACL_REG))])
06e1bace 3424 (set (match_operand:SI 0 "arith_reg_operand" "")
4773afa4 3425 (reg:SI MACH_REG))]
06e1bace 3426 "TARGET_SH2"
a512fa97 3427{
ba56ed65
KK
3428 rtx insn, mach;
3429
3430 mach = gen_rtx_REG (SImode, MACH_REG);
3431 start_sequence ();
3432 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3433 insn = get_insns ();
3434 end_sequence ();
22d05f60
R
3435 /* expand_binop can't find a suitable code in mul_highpart_optab to
3436 make a REG_EQUAL note from, so make one here.
c49439f1 3437 See also {,u}mulhisi.
22d05f60
R
3438 ??? Alternatively, we could put this at the calling site of expand_binop,
3439 i.e. expand_mult_highpart. */
ba56ed65
KK
3440 /* Use emit_libcall_block for loop invariant code motion and to make
3441 a REG_EQUAL note. */
3442 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
bd94cb6e 3443
a512fa97 3444 DONE;
d9241861 3445})
a512fa97
R
3446
3447(define_insn "umulsi3_highpart_i"
4773afa4 3448 [(set (reg:SI MACH_REG)
06e1bace 3449 (truncate:SI
4773afa4
AO
3450 (lshiftrt:DI
3451 (mult:DI
3452 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3453 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3454 (const_int 32))))
3455 (clobber (reg:SI MACL_REG))]
06e1bace 3456 "TARGET_SH2"
af55dae3 3457 "dmulu.l %1,%0"
06e1bace
RK
3458 [(set_attr "type" "dmpy")])
3459
3460(define_expand "umulsi3_highpart"
4773afa4
AO
3461 [(parallel
3462 [(set (reg:SI MACH_REG)
3463 (truncate:SI
3464 (lshiftrt:DI
3465 (mult:DI
3466 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3467 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3468 (const_int 32))))
3469 (clobber (reg:SI MACL_REG))])
06e1bace 3470 (set (match_operand:SI 0 "arith_reg_operand" "")
4773afa4 3471 (reg:SI MACH_REG))]
06e1bace 3472 "TARGET_SH2"
a512fa97 3473{
ba56ed65
KK
3474 rtx insn, mach;
3475
3476 mach = gen_rtx_REG (SImode, MACH_REG);
3477 start_sequence ();
3478 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3479 insn = get_insns ();
3480 end_sequence ();
3481 /* Use emit_libcall_block for loop invariant code motion and to make
3482 a REG_EQUAL note. */
3483 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3484
a512fa97 3485 DONE;
d9241861 3486})
73a4d10b
R
3487
3488(define_insn_and_split "muldi3"
3489 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3490 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3491 (match_operand:DI 2 "arith_reg_operand" "r")))
3492 (clobber (match_scratch:DI 3 "=&r"))
3493 (clobber (match_scratch:DI 4 "=r"))]
3494 "TARGET_SHMEDIA"
3495 "#"
3496 "reload_completed"
3497 [(const_int 0)]
73a4d10b
R
3498{
3499 rtx op3_v2si, op2_v2si;
3500
3501 op3_v2si = operands[3];
3502 if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3503 {
3504 op3_v2si = XEXP (op3_v2si, 0);
3505 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3506 }
3507 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3508 op2_v2si = operands[2];
3509 if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3510 {
3511 op2_v2si = XEXP (op2_v2si, 0);
3512 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3513 }
3514 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3515 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3516 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3517 emit_insn (gen_umulsidi3_media (operands[4],
3518 sh_gen_truncate (SImode, operands[1], 0),
3519 sh_gen_truncate (SImode, operands[2], 0)));
3520 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3521 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3522 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3523 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3524 DONE;
d9241861 3525})
73a4d10b 3526
bc45ade3
SC
3527\f
3528;; -------------------------------------------------------------------------
3529;; Logical operations
3530;; -------------------------------------------------------------------------
3531
5e204a6e
OE
3532(define_expand "andsi3"
3533 [(set (match_operand:SI 0 "arith_reg_operand" "")
3534 (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3535 (match_operand:SI 2 "logical_and_operand" "")))]
3536 ""
3537{
3538 /* If it is possible to turn the and insn into a zero extension
3539 already, redundant zero extensions will be folded, which results
3540 in better code.
197ddd06 3541 Ideally the splitter of *andsi_compact would be enough, if redundant
5e204a6e
OE
3542 zero extensions were detected after the combine pass, which does not
3543 happen at the moment. */
3544 if (TARGET_SH1)
3545 {
3546 if (satisfies_constraint_Jmb (operands[2]))
3547 {
3548 emit_insn (gen_zero_extendqisi2 (operands[0],
3549 gen_lowpart (QImode, operands[1])));
3550 DONE;
3551 }
3552 else if (satisfies_constraint_Jmw (operands[2]))
3553 {
3554 emit_insn (gen_zero_extendhisi2 (operands[0],
3555 gen_lowpart (HImode, operands[1])));
3556 DONE;
3557 }
3558 }
3559})
3560
3561(define_insn_and_split "*andsi_compact"
3562 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
3563 (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
3564 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
fa5322fa 3565 "TARGET_SH1"
5e204a6e
OE
3566 "@
3567 extu.b %1,%0
3568 extu.w %1,%0
3569 and %2,%0
3570 and %2,%0"
3571 "&& 1"
3572 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
3573{
3574 if (satisfies_constraint_Jmb (operands[2]))
3575 operands[1] = gen_lowpart (QImode, operands[1]);
3576 else if (satisfies_constraint_Jmw (operands[2]))
3577 operands[1] = gen_lowpart (HImode, operands[1]);
3578 else
3579 FAIL;
3580}
c49439f1 3581 [(set_attr "type" "arith")])
bc45ade3 3582
73a4d10b
R
3583(define_insn "*andsi3_media"
3584 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3585 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3586 (match_operand:SI 2 "logical_operand" "r,I10")))]
3587 "TARGET_SHMEDIA"
3588 "@
3589 and %1, %2, %0
3590 andi %1, %2, %0"
3591 [(set_attr "type" "arith_media")])
3592
de6adfa2
N
3593(define_insn "*andsi3_bclr"
3594 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3595 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3596 (match_operand:SI 2 "const_int_operand" "Psz")))]
3597 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
35ed5a70 3598 "bclr %W2,%0"
de6adfa2
N
3599 [(set_attr "type" "arith")])
3600
c1b92d09 3601(define_insn_and_split "anddi3"
73a4d10b 3602 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
c1b92d09 3603 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
735cb76e 3604 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
fa5322fa
AO
3605 "TARGET_SHMEDIA"
3606 "@
3607 and %1, %2, %0
c1b92d09
R
3608 andi %1, %2, %0
3609 #"
3610 "reload_completed
3611 && ! logical_operand (operands[2], DImode)"
3612 [(const_int 0)]
c1b92d09 3613{
f5b9e7c9 3614 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
c1b92d09
R
3615 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3616 else
3617 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3618 DONE;
6b45f126 3619}
2ad65b0e 3620 [(set_attr "type" "arith_media")])
fa5322fa 3621
73a4d10b
R
3622(define_insn "andcsi3"
3623 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3624 (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3625 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3626 "TARGET_SHMEDIA"
3627 "andc %1,%2,%0"
3628 [(set_attr "type" "arith_media")])
3629
b6d33983 3630(define_insn "andcdi3"
73a4d10b 3631 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
fa5322fa
AO
3632 (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3633 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3634 "TARGET_SHMEDIA"
2ad65b0e
SC
3635 "andc %1,%2,%0"
3636 [(set_attr "type" "arith_media")])
fa5322fa 3637
73a4d10b
R
3638(define_expand "iorsi3"
3639 [(set (match_operand:SI 0 "arith_reg_operand" "")
3640 (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3641 (match_operand:SI 2 "logical_operand" "")))]
3642 ""
3643 "")
3644
3645(define_insn "*iorsi3_compact"
3646 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
aa684c94 3647 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
735cb76e 3648 (match_operand:SI 2 "logical_operand" "r,K08")))]
9eb3a0dd
N
3649 "TARGET_SH1
3650 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
1245df60 3651 "or %2,%0"
c49439f1 3652 [(set_attr "type" "arith")])
bc45ade3 3653
73a4d10b
R
3654(define_insn "*iorsi3_media"
3655 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3656 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3657 (match_operand:SI 2 "logical_operand" "r,I10")))]
3658 "TARGET_SHMEDIA"
3659 "@
3660 or %1, %2, %0
3661 ori %1, %2, %0"
3662 [(set_attr "type" "arith_media")])
3663
de6adfa2
N
3664(define_insn "*iorsi3_bset"
3665 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3666 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3667 (match_operand:SI 2 "const_int_operand" "Pso")))]
3668 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
35ed5a70 3669 "bset %V2,%0"
de6adfa2
N
3670 [(set_attr "type" "arith")])
3671
fa5322fa 3672(define_insn "iordi3"
73a4d10b 3673 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
fa5322fa 3674 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
735cb76e 3675 (match_operand:DI 2 "logical_operand" "r,I10")))]
fa5322fa
AO
3676 "TARGET_SHMEDIA"
3677 "@
3678 or %1, %2, %0
2ad65b0e
SC
3679 ori %1, %2, %0"
3680 [(set_attr "type" "arith_media")])
fa5322fa 3681
73a4d10b
R
3682(define_insn_and_split "*logical_sidi3"
3683 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3684 (sign_extend:DI (match_operator:SI 3 "logical_operator"
3685 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3686 (match_operand:SI 2 "logical_operand" "r,I10")])))]
3687 "TARGET_SHMEDIA"
3688 "#"
3689 "&& reload_completed"
3690 [(set (match_dup 0) (match_dup 3))]
73a4d10b
R
3691{
3692 operands[3]
3693 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3694 simplify_gen_subreg (DImode, operands[1], SImode, 0),
3695 simplify_gen_subreg (DImode, operands[2], SImode, 0));
d9241861 3696})
73a4d10b
R
3697
3698(define_insn_and_split "*logical_sidisi3"
3699 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3700 (truncate:SI (sign_extend:DI
3701 (match_operator:SI 3 "logical_operator"
3702 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3703 (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3704 "TARGET_SHMEDIA"
3705 "#"
3706 "&& 1"
3707 [(set (match_dup 0) (match_dup 3))])
3708
3709(define_insn_and_split "*logical_sidi3_2"
3710 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3711 (sign_extend:DI (truncate:SI (sign_extend:DI
3712 (match_operator:SI 3 "logical_operator"
3713 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3714 (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3715 "TARGET_SHMEDIA"
3716 "#"
3717 "&& 1"
3718 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3719
3720(define_expand "xorsi3"
3721 [(set (match_operand:SI 0 "arith_reg_operand" "")
3722 (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3723 (match_operand:SI 2 "xor_operand" "")))]
3724 ""
3725 "")
3726
3727(define_insn "*xorsi3_compact"
3728 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
aa684c94 3729 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
735cb76e 3730 (match_operand:SI 2 "logical_operand" "K08,r")))]
fa5322fa 3731 "TARGET_SH1"
bc45ade3 3732 "xor %2,%0"
c49439f1 3733 [(set_attr "type" "arith")])
fa5322fa 3734
26943929
OE
3735;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
3736;; of results where one of the inputs is a T bit store. Notice that this
3737;; pattern must not match during reload. If reload picks this pattern it
3738;; will be impossible to split it afterwards.
3739(define_insn_and_split "*logical_op_t"
3740 [(set (match_operand:SI 0 "arith_reg_dest")
3741 (match_operator:SI 3 "logical_operator"
3742 [(match_operand:SI 1 "arith_reg_operand")
3743 (match_operand:SI 2 "t_reg_operand")]))]
3744 "TARGET_SH1 && can_create_pseudo_p ()"
3745 "#"
3746 "&& 1"
3747 [(set (match_dup 4) (reg:SI T_REG))
3748 (set (match_dup 0) (match_dup 3))]
3749{
3750 operands[4] = gen_reg_rtx (SImode);
3751 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
3752 operands[1], operands[4]);
3753})
3754
73a4d10b
R
3755(define_insn "*xorsi3_media"
3756 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3757 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3758 (match_operand:SI 2 "xor_operand" "r,I06")))]
3759 "TARGET_SHMEDIA"
3760 "@
3761 xor %1, %2, %0
3762 xori %1, %2, %0"
3763 [(set_attr "type" "arith_media")])
3764
fa5322fa 3765(define_insn "xordi3"
73a4d10b 3766 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
fa5322fa 3767 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
73a4d10b 3768 (match_operand:DI 2 "xor_operand" "r,I06")))]
fa5322fa
AO
3769 "TARGET_SHMEDIA"
3770 "@
3771 xor %1, %2, %0
2ad65b0e
SC
3772 xori %1, %2, %0"
3773 [(set_attr "type" "arith_media")])
ff881d52
R
3774
3775;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3776;; converts 2 * sign extend -> logical op into logical op -> sign extend
3777(define_split
73a4d10b 3778 [(set (match_operand:DI 0 "arith_reg_dest" "")
ff881d52
R
3779 (sign_extend:DI (match_operator 4 "binary_logical_operator"
3780 [(match_operand 1 "any_register_operand" "")
3781 (match_operand 2 "any_register_operand" "")])))]
3782 "TARGET_SHMEDIA"
3783 [(set (match_dup 5) (match_dup 4))
3784 (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
ff881d52
R
3785{
3786 enum machine_mode inmode = GET_MODE (operands[1]);
fada1961 3787 int offset = 0;
ff881d52
R
3788
3789 if (GET_CODE (operands[0]) == SUBREG)
3790 {
3791 offset = SUBREG_BYTE (operands[0]);
3792 operands[0] = SUBREG_REG (operands[0]);
3793 }
f3536097 3794 gcc_assert (REG_P (operands[0]));
ff881d52
R
3795 if (! TARGET_LITTLE_ENDIAN)
3796 offset += 8 - GET_MODE_SIZE (inmode);
3797 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
d9241861 3798})
bc45ade3
SC
3799\f
3800;; -------------------------------------------------------------------------
3801;; Shifts and rotates
3802;; -------------------------------------------------------------------------
3803
b6d33983 3804(define_expand "rotldi3"
ee04b091
OE
3805 [(set (match_operand:DI 0 "arith_reg_dest" "")
3806 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
3807 (match_operand:HI 2 "mextr_bit_offset" "")))]
b6d33983 3808 "TARGET_SHMEDIA"
35ed5a70
OE
3809{
3810 if (! mextr_bit_offset (operands[2], HImode))
3811 FAIL;
3812})
b6d33983
R
3813
3814(define_insn "rotldi3_mextr"
3815 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3816 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3817 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3818 "TARGET_SHMEDIA"
b6d33983
R
3819{
3820 static char templ[16];
35ed5a70 3821 sprintf (templ, "mextr%d %%1,%%1,%%0",
b6d33983
R
3822 8 - (int) (INTVAL (operands[2]) >> 3));
3823 return templ;
d9241861 3824}
b6d33983
R
3825 [(set_attr "type" "arith_media")])
3826
3827(define_expand "rotrdi3"
ee04b091
OE
3828 [(set (match_operand:DI 0 "arith_reg_dest" "")
3829 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
3830 (match_operand:HI 2 "mextr_bit_offset" "")))]
b6d33983 3831 "TARGET_SHMEDIA"
d9241861
OE
3832{
3833 if (! mextr_bit_offset (operands[2], HImode))
3834 FAIL;
3835})
b6d33983
R
3836
3837(define_insn "rotrdi3_mextr"
3838 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3839 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3840 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3841 "TARGET_SHMEDIA"
b6d33983
R
3842{
3843 static char templ[16];
35ed5a70 3844 sprintf (templ, "mextr%d %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
b6d33983 3845 return templ;
d9241861 3846}
b6d33983
R
3847 [(set_attr "type" "arith_media")])
3848
73a4d10b
R
3849(define_split
3850 [(set (match_operand:DI 0 "arith_reg_dest" "")
3851 (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3852 "ua_address_operand" "")))
3853 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3854 (const_int 8))))
3855 (clobber (match_operand:DI 3 "register_operand" ""))]
3856 "TARGET_SHMEDIA"
3857 [(match_dup 4) (match_dup 5)]
73a4d10b
R
3858{
3859 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3860 (operands[3], operands[1]));
3861 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3862 GEN_INT (56), GEN_INT (8));
d9241861 3863})
73a4d10b 3864
78040535
OE
3865(define_expand "rotrsi3"
3866 [(set (match_operand:SI 0 "arith_reg_dest")
3867 (rotatert:SI (match_operand:SI 1 "arith_reg_operand")
3868 (match_operand:SI 2 "const_int_operand")))]
3869 "TARGET_SH1"
3870{
3871 HOST_WIDE_INT ival = INTVAL (operands[2]);
3872 if (ival == 1)
3873 {
3874 emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
3875 DONE;
3876 }
3877
3878 FAIL;
3879})
3880
3881(define_insn "rotrsi3_1"
3882 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3883 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3884 (const_int 1)))
3885 (set (reg:SI T_REG)
3886 (and:SI (match_dup 1) (const_int 1)))]
3887 "TARGET_SH1"
3888 "rotr %0"
3889 [(set_attr "type" "arith")])
3890
3891;; A slimplified version of rotr for combine.
3892(define_insn "*rotrsi3_1"
3893 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3894 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3895 (const_int 1)))
3896 (clobber (reg:SI T_REG))]
3897 "TARGET_SH1"
3898 "rotr %0"
3899 [(set_attr "type" "arith")])
3900
51bd623f 3901(define_insn "rotlsi3_1"
73a4d10b 3902 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
b9654711
SC
3903 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3904 (const_int 1)))
4773afa4 3905 (set (reg:SI T_REG)
51aea58d 3906 (lshiftrt:SI (match_dup 1) (const_int 31)))]
fa5322fa 3907 "TARGET_SH1"
1245df60 3908 "rotl %0"
c49439f1 3909 [(set_attr "type" "arith")])
b9654711 3910
78040535
OE
3911;; A simplified version of rotl for combine.
3912(define_insn "*rotlsi3_1"
3913 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3914 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3915 (const_int 1)))
3916 (clobber (reg:SI T_REG))]
3917 "TARGET_SH1"
3918 "rotl %0"
3919 [(set_attr "type" "arith")])
3920
51bd623f 3921(define_insn "rotlsi3_31"
73a4d10b 3922 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
51bd623f
JW
3923 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3924 (const_int 31)))
4773afa4 3925 (clobber (reg:SI T_REG))]
fa5322fa 3926 "TARGET_SH1"
1245df60 3927 "rotr %0"
c49439f1 3928 [(set_attr "type" "arith")])
b9654711 3929
1245df60 3930(define_insn "rotlsi3_16"
73a4d10b 3931 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
51bd623f
JW
3932 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3933 (const_int 16)))]
fa5322fa 3934 "TARGET_SH1"
1245df60 3935 "swap.w %1,%0"
c49439f1 3936 [(set_attr "type" "arith")])
b9654711 3937
51bd623f 3938(define_expand "rotlsi3"
78040535
OE
3939 [(set (match_operand:SI 0 "arith_reg_dest")
3940 (rotate:SI (match_operand:SI 1 "arith_reg_operand")
3941 (match_operand:SI 2 "const_int_operand")))]
fa5322fa 3942 "TARGET_SH1"
51bd623f 3943{
0139adca 3944 static const char rot_tab[] = {
1245df60
R
3945 000, 000, 000, 000, 000, 000, 010, 001,
3946 001, 001, 011, 013, 003, 003, 003, 003,
3947 003, 003, 003, 003, 003, 013, 012, 002,
3948 002, 002, 010, 000, 000, 000, 000, 000,
3949 };
3950
78040535
OE
3951 int count = INTVAL (operands[2]);
3952 int choice = rot_tab[count];
1245df60
R
3953 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3954 FAIL;
3955 choice &= 7;
3956 switch (choice)
51bd623f 3957 {
1245df60
R
3958 case 0:
3959 emit_move_insn (operands[0], operands[1]);
3960 count -= (count & 16) * 2;
3961 break;
3962 case 3:
3963 emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3964 count -= 16;
3965 break;
3966 case 1:
3967 case 2:
3968 {
3969 rtx parts[2];
3970 parts[0] = gen_reg_rtx (SImode);
3971 parts[1] = gen_reg_rtx (SImode);
3972 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
4fbf3498 3973 emit_move_insn (parts[choice-1], operands[1]);
1245df60
R
3974 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3975 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3976 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3977 count = (count & ~16) - 8;
3978 }
51bd623f 3979 }
1245df60
R
3980
3981 for (; count > 0; count--)
3982 emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3983 for (; count < 0; count++)
3984 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3985
3986 DONE;
d9241861 3987})
51bd623f 3988
1245df60 3989(define_insn "*rotlhi3_8"
73a4d10b 3990 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
51bd623f
JW
3991 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3992 (const_int 8)))]
fa5322fa 3993 "TARGET_SH1"
1245df60 3994 "swap.b %1,%0"
c49439f1 3995 [(set_attr "type" "arith")])
51bd623f
JW
3996
3997(define_expand "rotlhi3"
78040535
OE
3998 [(set (match_operand:HI 0 "arith_reg_operand")
3999 (rotate:HI (match_operand:HI 1 "arith_reg_operand")
4000 (match_operand:HI 2 "const_int_operand")))]
fa5322fa 4001 "TARGET_SH1"
51bd623f 4002{
78040535 4003 if (INTVAL (operands[2]) != 8)
51bd623f 4004 FAIL;
d9241861 4005})
0d7e008e 4006
0f9a3fd3
OE
4007;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
4008;; They can also be used to implement things like
5592815a 4009;; bool t = a == b;
0f9a3fd3
OE
4010;; int x0 = (y >> 1) | (t << 31); // rotcr
4011;; int x1 = (y << 1) | t; // rotcl
5592815a
OE
4012(define_insn "rotcr"
4013 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4014 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4015 (const_int 1))
4016 (ashift:SI (match_operand:SI 2 "t_reg_operand")
4017 (const_int 31))))
4018 (set (reg:SI T_REG)
4019 (and:SI (match_dup 1) (const_int 1)))]
4020 "TARGET_SH1"
4021 "rotcr %0"
4022 [(set_attr "type" "arith")])
4023
0f9a3fd3
OE
4024(define_insn "rotcl"
4025 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4026 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4027 (const_int 1))
4028 (match_operand:SI 2 "t_reg_operand")))
4029 (set (reg:SI T_REG)
4030 (lshiftrt:SI (match_dup 1) (const_int 31)))]
4031 "TARGET_SH1"
4032 "rotcl %0"
4033 [(set_attr "type" "arith")])
4034
5592815a
OE
4035;; Simplified rotcr version for combine, which allows arbitrary shift
4036;; amounts for the reg. If the shift amount is '1' rotcr can be used
4037;; directly. Otherwise we have to insert a shift in between.
4038(define_insn_and_split "*rotcr"
4039 [(set (match_operand:SI 0 "arith_reg_dest")
4040 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4041 (match_operand:SI 2 "const_int_operand"))
4eddc42b 4042 (ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
5592815a
OE
4043 (const_int 31))))
4044 (clobber (reg:SI T_REG))]
4045 "TARGET_SH1"
4046 "#"
4047 "&& can_create_pseudo_p ()"
4048 [(const_int 0)]
4049{
4050 if (INTVAL (operands[2]) > 1)
4051 {
78040535 4052 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
5592815a
OE
4053 rtx prev_set_t_insn = NULL_RTX;
4054 rtx tmp_t_reg = NULL_RTX;
4055
4056 /* If we're going to emit a shift sequence that clobbers the T_REG,
4057 try to find the previous insn that sets the T_REG and emit the
4058 shift insn before that insn, to remove the T_REG dependency.
4059 If the insn that sets the T_REG cannot be found, store the T_REG
4060 in a temporary reg and restore it after the shift. */
78040535
OE
4061 if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4062 && ! sh_dynamicalize_shift_p (shift_count))
5592815a
OE
4063 {
4064 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
78040535
OE
4065
4066 /* Skip the nott insn, which was probably inserted by the splitter
4067 of *rotcr_neg_t. Don't use one of the recog functions
4068 here during insn splitting, since that causes problems in later
4069 passes. */
4070 if (prev_set_t_insn != NULL_RTX)
4071 {
4072 rtx pat = PATTERN (prev_set_t_insn);
4073 if (GET_CODE (pat) == SET
4074 && t_reg_operand (XEXP (pat, 0), SImode)
4075 && negt_reg_operand (XEXP (pat, 1), SImode))
4076 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4077 }
4078
5592815a
OE
4079 if (! (prev_set_t_insn != NULL_RTX
4080 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4081 && ! reg_referenced_p (get_t_reg_rtx (),
4082 PATTERN (prev_set_t_insn))))
4083 {
4084 prev_set_t_insn = NULL_RTX;
4085 tmp_t_reg = gen_reg_rtx (SImode);
4086 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4087 }
4088 }
4089
78040535
OE
4090 rtx shift_result = gen_reg_rtx (SImode);
4091 rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4092 operands[1] = shift_result;
5592815a
OE
4093
4094 /* Emit the shift insn before the insn that sets T_REG, if possible. */
4095 if (prev_set_t_insn != NULL_RTX)
78040535 4096 emit_insn_before (shift_insn, prev_set_t_insn);
5592815a 4097 else
78040535 4098 emit_insn (shift_insn);
5592815a
OE
4099
4100 /* Restore T_REG if it has been saved before. */
4101 if (tmp_t_reg != NULL_RTX)
4102 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4103 }
4104
4eddc42b
OE
4105 /* For the rotcr insn to work, operands[3] must be in T_REG.
4106 If it is not we can get it there by shifting it right one bit.
4107 In this case T_REG is not an input for this insn, thus we don't have to
4108 pay attention as of where to insert the shlr insn. */
4109 if (! t_reg_operand (operands[3], SImode))
4110 {
4111 /* We don't care about the shifted result here, only the T_REG. */
4112 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4113 operands[3] = get_t_reg_rtx ();
4114 }
4115
5592815a
OE
4116 emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4117 DONE;
4118})
4119
78040535
OE
4120;; If combine tries the same as above but with swapped operands, split
4121;; it so that it will try the pattern above.
4122(define_split
4123 [(set (match_operand:SI 0 "arith_reg_dest")
4124 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4125 (const_int 31))
4126 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4127 (match_operand:SI 3 "const_int_operand"))))]
4128 "TARGET_SH1 && can_create_pseudo_p ()"
4129 [(parallel [(set (match_dup 0)
4130 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4131 (ashift:SI (match_dup 1) (const_int 31))))
4132 (clobber (reg:SI T_REG))])])
4133
0f9a3fd3
OE
4134;; Basically the same as the rotcr pattern above, but for rotcl.
4135;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4136(define_insn_and_split "*rotcl"
4137 [(set (match_operand:SI 0 "arith_reg_dest")
4138 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4139 (match_operand:SI 2 "const_int_operand"))
4140 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4141 (const_int 1))))
4142 (clobber (reg:SI T_REG))]
4143 "TARGET_SH1"
4144 "#"
4145 "&& can_create_pseudo_p ()"
4146 [(const_int 0)]
4147{
4148 gcc_assert (INTVAL (operands[2]) > 0);
4149
4150 if (INTVAL (operands[2]) > 1)
4151 {
4152 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4153 rtx prev_set_t_insn = NULL_RTX;
4154 rtx tmp_t_reg = NULL_RTX;
4155
4156 /* If we're going to emit a shift sequence that clobbers the T_REG,
4157 try to find the previous insn that sets the T_REG and emit the
4158 shift insn before that insn, to remove the T_REG dependency.
4159 If the insn that sets the T_REG cannot be found, store the T_REG
4160 in a temporary reg and restore it after the shift. */
4161 if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4162 && ! sh_dynamicalize_shift_p (shift_count))
4163 {
4164 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4165
4166 /* Skip the nott insn, which was probably inserted by the splitter
4167 of *rotcl_neg_t. Don't use one of the recog functions
4168 here during insn splitting, since that causes problems in later
4169 passes. */
4170 if (prev_set_t_insn != NULL_RTX)
4171 {
4172 rtx pat = PATTERN (prev_set_t_insn);
4173 if (GET_CODE (pat) == SET
4174 && t_reg_operand (XEXP (pat, 0), SImode)
4175 && negt_reg_operand (XEXP (pat, 1), SImode))
4176 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4177 }
4178
4179 if (! (prev_set_t_insn != NULL_RTX
4180 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4181 && ! reg_referenced_p (get_t_reg_rtx (),
4182 PATTERN (prev_set_t_insn))))
4183 {
4184 prev_set_t_insn = NULL_RTX;
4185 tmp_t_reg = gen_reg_rtx (SImode);
4186 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4187 }
4188 }
4189
4190 rtx shift_result = gen_reg_rtx (SImode);
4191 rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4192 operands[1] = shift_result;
4193
4194 /* Emit the shift insn before the insn that sets T_REG, if possible. */
4195 if (prev_set_t_insn != NULL_RTX)
4196 emit_insn_before (shift_insn, prev_set_t_insn);
4197 else
4198 emit_insn (shift_insn);
4199
4200 /* Restore T_REG if it has been saved before. */
4201 if (tmp_t_reg != NULL_RTX)
4202 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4203 }
4204
4205 /* For the rotcl insn to work, operands[3] must be in T_REG.
4206 If it is not we can get it there by shifting it right one bit.
4207 In this case T_REG is not an input for this insn, thus we don't have to
4208 pay attention as of where to insert the shlr insn. */
4209 if (! t_reg_operand (operands[3], SImode))
4210 {
4211 /* We don't care about the shifted result here, only the T_REG. */
4212 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4213 operands[3] = get_t_reg_rtx ();
4214 }
4215
4216 emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4217 DONE;
4218})
4219
4220;; rotcl combine pattern variations
4221(define_insn_and_split "*rotcl"
4222 [(set (match_operand:SI 0 "arith_reg_dest")
4223 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4224 (match_operand:SI 2 "const_int_operand"))
4225 (match_operand:SI 3 "t_reg_operand")))
4226 (clobber (reg:SI T_REG))]
4227 "TARGET_SH1"
4228 "#"
4229 "&& can_create_pseudo_p ()"
4230 [(parallel [(set (match_dup 0)
4231 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4232 (and:SI (match_dup 3) (const_int 1))))
4233 (clobber (reg:SI T_REG))])])
4234
4235(define_insn_and_split "*rotcl"
4236 [(set (match_operand:SI 0 "arith_reg_dest")
4237 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4238 (const_int 1))
4239 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4240 (match_operand:SI 3 "const_int_operand"))))
4241 (clobber (reg:SI T_REG))]
4242 "TARGET_SH1"
4243 "#"
4244 "&& can_create_pseudo_p ()"
4245 [(parallel [(set (match_dup 0)
4246 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4247 (and:SI (match_dup 1) (const_int 1))))
4248 (clobber (reg:SI T_REG))])])
4249
4250(define_insn_and_split "*rotcl"
4251 [(set (match_operand:SI 0 "arith_reg_dest")
4252 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4253 (match_operand:SI 2 "const_int_operand"))
4254 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4255 (const_int 31))))
4256 (clobber (reg:SI T_REG))]
4257 "TARGET_SH1"
4258 "#"
4259 "&& can_create_pseudo_p ()"
4260 [(parallel [(set (match_dup 0)
4261 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4262 (and:SI (reg:SI T_REG) (const_int 1))))
4263 (clobber (reg:SI T_REG))])]
4264{
4265 /* We don't care about the result of the left shift, only the T_REG. */
4266 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4267})
4268
4269(define_insn_and_split "*rotcl"
4270 [(set (match_operand:SI 0 "arith_reg_dest")
4271 (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4272 (const_int 31))
4273 (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4274 (match_operand:SI 2 "const_int_operand"))))
4275 (clobber (reg:SI T_REG))]
4276 "TARGET_SH1"
4277 "#"
4278 "&& can_create_pseudo_p ()"
4279 [(parallel [(set (match_dup 0)
4280 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4281 (and:SI (reg:SI T_REG) (const_int 1))))
4282 (clobber (reg:SI T_REG))])]
4283{
4284 /* We don't care about the result of the left shift, only the T_REG. */
4285 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4286})
4287
5592815a
OE
4288;; rotcr combine bridge pattern which will make combine try out more
4289;; complex patterns.
4290(define_insn_and_split "*rotcr"
4291 [(set (match_operand:SI 0 "arith_reg_dest")
4292 (ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
4293 "TARGET_SH1"
4294 "#"
4295 "&& 1"
4296 [(set (match_dup 0) (match_dup 1))
4297 (parallel [(set (match_dup 0)
4298 (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
4299 (ashift:SI (match_dup 1) (const_int 31))))
4300 (set (reg:SI T_REG)
4301 (and:SI (match_dup 0) (const_int 1)))])])
4302
4eddc42b
OE
4303(define_insn_and_split "*rotcr"
4304 [(set (match_operand:SI 0 "arith_reg_dest")
4305 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4306 (const_int -2147483648)) ;; 0xffffffff80000000
4307 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4308 (const_int 1))))
4309 (clobber (reg:SI T_REG))]
4310 "TARGET_SH1"
4311 "#"
4312 "&& can_create_pseudo_p ()"
4313 [(const_int 0)]
4314{
4315 rtx tmp = gen_reg_rtx (SImode);
4316 emit_insn (gen_shll (tmp, operands[1]));
4317 emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4318 DONE;
4319})
4320
78040535
OE
4321;; rotcr combine patterns for rotating in the negated T_REG value.
4322(define_insn_and_split "*rotcr_neg_t"
4323 [(set (match_operand:SI 0 "arith_reg_dest")
4324 (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4325 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4326 (match_operand:SI 3 "const_int_operand"))))
4327 (clobber (reg:SI T_REG))]
4328 "TARGET_SH1"
4329 "#"
4330 "&& can_create_pseudo_p ()"
4331 [(parallel [(set (match_dup 0)
4332 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4333 (ashift:SI (reg:SI T_REG) (const_int 31))))
4334 (clobber (reg:SI T_REG))])]
4335{
4336 emit_insn (gen_nott (get_t_reg_rtx ()));
4337})
4338
4339(define_insn_and_split "*rotcr_neg_t"
4340 [(set (match_operand:SI 0 "arith_reg_dest")
4341 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4342 (match_operand:SI 2 "const_int_operand"))
4343 (match_operand:SI 3 "negt_reg_shl31_operand")))
4344 (clobber (reg:SI T_REG))]
4345 "TARGET_SH1"
4346 "#"
4347 "&& can_create_pseudo_p ()"
4348 [(parallel [(set (match_dup 0)
4349 (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4350 (ashift:SI (reg:SI T_REG) (const_int 31))))
4351 (clobber (reg:SI T_REG))])]
4352{
4353 emit_insn (gen_nott (get_t_reg_rtx ()));
4354})
4355
0f9a3fd3
OE
4356;; rotcl combine patterns for rotating in the negated T_REG value.
4357;; For some strange reason these have to be specified as splits which combine
4358;; will pick up. If they are specified as insn_and_split like the
4359;; *rotcr_neg_t patterns above, combine would recognize them successfully
4360;; but not emit them on non-SH2A targets.
4361(define_split
4362 [(set (match_operand:SI 0 "arith_reg_dest")
4363 (ior:SI (match_operand:SI 1 "negt_reg_operand")
4364 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4365 (match_operand:SI 3 "const_int_operand"))))]
4366 "TARGET_SH1"
4367 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4368 (parallel [(set (match_dup 0)
4369 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4370 (and:SI (reg:SI T_REG) (const_int 1))))
4371 (clobber (reg:SI T_REG))])])
4372
4373(define_split
4374 [(set (match_operand:SI 0 "arith_reg_dest")
4375 (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4376 (match_operand:SI 3 "const_int_operand"))
4377 (match_operand:SI 1 "negt_reg_operand")))]
4378 "TARGET_SH1"
4379 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4380 (parallel [(set (match_dup 0)
4381 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4382 (and:SI (reg:SI T_REG) (const_int 1))))
4383 (clobber (reg:SI T_REG))])])
4384
56e25830
OE
4385;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4386;; SImode shift left
4387
4388(define_expand "ashlsi3"
d8a48c21
OE
4389 [(set (match_operand:SI 0 "arith_reg_operand" "")
4390 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4391 (match_operand:SI 2 "shift_count_operand" "")))]
56e25830
OE
4392 ""
4393{
4394 if (TARGET_SHMEDIA)
4395 {
4396 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4397 DONE;
4398 }
d8a48c21
OE
4399 if (TARGET_DYNSHIFT
4400 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4401 operands[2] = force_reg (SImode, operands[2]);
70d4736c
OE
4402
4403 /* If the ashlsi3_* insn is going to clobber the T_REG it must be
4404 expanded here. */
4405 if (CONST_INT_P (operands[2])
4406 && sh_ashlsi_clobbers_t_reg_p (operands[2])
4407 && ! sh_dynamicalize_shift_p (operands[2]))
4408 {
4409 emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4410 operands[2]));
4411 DONE;
4412 }
aadb5b43
OE
4413
4414 /* Expand a library call for the dynamic shift. */
4415 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4416 {
4417 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4418 rtx funcaddr = gen_reg_rtx (Pmode);
4419 function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4420 emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4421
4422 DONE;
4423 }
56e25830 4424})
0d7e008e 4425
d8a48c21
OE
4426(define_insn "ashlsi3_k"
4427 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4428 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4429 (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4430 "TARGET_SH1"
0d7e008e 4431 "@
d8a48c21
OE
4432 add %0,%0
4433 shll%O2 %0"
4434 [(set_attr "type" "arith")])
4435
4436(define_insn_and_split "ashlsi3_d"
4437 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4438 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4439 (match_operand:SI 2 "shift_count_operand" "r")))]
4440 "TARGET_DYNSHIFT"
4441 "shld %2,%0"
043d627e
OE
4442 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4443 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
d8a48c21 4444 [(const_int 0)]
d9241861 4445{
d8a48c21
OE
4446 if (satisfies_constraint_P27 (operands[2]))
4447 {
4448 emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
4449 DONE;
4450 }
70d4736c 4451 else if (! satisfies_constraint_P27 (operands[2]))
d8a48c21 4452 {
be82afe6
OE
4453 /* This must happen before reload, otherwise the constant will be moved
4454 into a register due to the "r" constraint, after which this split
4455 cannot be done anymore.
043d627e
OE
4456 Unfortunately the move insn will not always be eliminated.
4457 Also, here we must not create a shift sequence that clobbers the
4458 T_REG. */
be82afe6
OE
4459 emit_move_insn (operands[0], operands[1]);
4460 gen_shifty_op (ASHIFT, operands);
d8a48c21
OE
4461 DONE;
4462 }
4463
4464 FAIL;
d9241861 4465}
6e01d526 4466 [(set_attr "type" "dyn_shift")])
0d7e008e 4467
aadb5b43
OE
4468;; If dynamic shifts are not available use a library function.
4469;; By specifying the pattern we reduce the number of call clobbered regs.
4470;; In order to make combine understand the truncation of the shift amount
4471;; operand we have to allow it to use pseudo regs for the shift operands.
4472(define_insn "ashlsi3_d_call"
4473 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4474 (ashift:SI (reg:SI R4_REG)
4475 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4476 (const_int 31))))
4477 (use (match_operand:SI 2 "arith_reg_operand" "r"))
4478 (clobber (reg:SI T_REG))
4479 (clobber (reg:SI PR_REG))]
4480 "TARGET_SH1 && !TARGET_DYNSHIFT"
4481 "jsr @%2%#"
4482 [(set_attr "type" "sfunc")
4483 (set_attr "needs_delay_slot" "yes")])
4484
ee04b091 4485(define_insn_and_split "ashlsi3_n"
73a4d10b 4486 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
0d7e008e 4487 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
d8a48c21 4488 (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
70d4736c
OE
4489 "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4490 "#"
4491 "&& (reload_completed
4492 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4493 [(const_int 0)]
4494{
4495 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4496 {
4497 /* If this pattern was picked and dynamic shifts are supported, switch
043d627e 4498 to dynamic shift pattern before reload. */
70d4736c
OE
4499 operands[2] = force_reg (SImode, operands[2]);
4500 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4501 }
4502 else
4503 gen_shifty_op (ASHIFT, operands);
4504
4505 DONE;
4506})
4507
4508(define_insn_and_split "ashlsi3_n_clobbers_t"
4509 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4510 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4511 (match_operand:SI 2 "not_p27_shift_count_operand" "")))
4512 (clobber (reg:SI T_REG))]
4513 "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
07a45e5c 4514 "#"
d8a48c21
OE
4515 "&& (reload_completed || INTVAL (operands[2]) == 31
4516 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4517 [(const_int 0)]
ee04b091 4518{
d8a48c21
OE
4519 if (INTVAL (operands[2]) == 31)
4520 {
4521 /* If the shift amount is 31 we split into a different sequence before
4522 reload so that it gets a chance to allocate R0 for the sequence.
4523 If it fails to do so (due to pressure on R0), it will take one insn
4524 more for the and. */
4525 emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
4526 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4527 }
4528 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4529 {
4530 /* If this pattern was picked and dynamic shifts are supported, switch
4531 to dynamic shift pattern before reload. */
4532 operands[2] = force_reg (SImode, operands[2]);
4533 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4534 }
4535 else
4536 gen_shifty_op (ASHIFT, operands);
4537
ee04b091 4538 DONE;
56e25830
OE
4539})
4540
6e01d526 4541(define_insn "shll"
56e25830
OE
4542 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4543 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
4544 (set (reg:SI T_REG)
4545 (lt:SI (match_dup 1) (const_int 0)))]
4546 "TARGET_SH1"
4547 "shll %0"
4548 [(set_attr "type" "arith")])
4549
4550(define_insn "*ashlsi_c_void"
4551 [(set (reg:SI T_REG)
4552 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
4553 (clobber (match_scratch:SI 1 "=0"))]
4554 "TARGET_SH1 && cse_not_expected"
4555 "shll %0"
4556 [(set_attr "type" "arith")])
4557
4558(define_peephole2
4559 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
4560 (set (reg:SI T_REG)
4561 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
4562 "TARGET_SH1
4563 && peep2_reg_dead_p (2, operands[0])
4564 && peep2_reg_dead_p (2, operands[1])"
4565 [(const_int 0)]
4566{
6e01d526 4567 emit_insn (gen_shll (operands[1], operands[1]));
56e25830
OE
4568 DONE;
4569})
bc45ade3 4570
fa5322fa 4571(define_insn "ashlsi3_media"
73a4d10b 4572 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
b6d33983 4573 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
73a4d10b 4574 (match_operand:SI 2 "shift_count_operand" "r,n")))]
fa5322fa
AO
4575 "TARGET_SHMEDIA"
4576 "@
4577 shlld.l %1, %2, %0
b6d33983 4578 shlli.l %1, %2, %0"
73a4d10b
R
4579 [(set_attr "type" "arith_media")
4580 (set_attr "highpart" "ignore")])
fa5322fa 4581
56e25830
OE
4582;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4583;; HImode shift left
0d7e008e 4584
39f44b0b
KK
4585(define_expand "ashlhi3"
4586 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
4587 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
4588 (match_operand:SI 2 "nonmemory_operand" "")))
4589 (clobber (reg:SI T_REG))])]
4590 "TARGET_SH1"
39f44b0b 4591{
f3536097 4592 if (!CONST_INT_P (operands[2]))
39f44b0b
KK
4593 FAIL;
4594 /* It may be possible to call gen_ashlhi3 directly with more generic
4595 operands. Make sure operands[1] is a HImode register here. */
4596 if (!arith_reg_operand (operands[1], HImode))
4597 operands[1] = copy_to_mode_reg (HImode, operands[1]);
d9241861 4598})
39f44b0b 4599
56e25830
OE
4600(define_insn "ashlhi3_k"
4601 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4602 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
4603 (match_operand:HI 2 "const_int_operand" "M,P27")))]
4604 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
4605 "@
4606 add %0,%0
4607 shll%O2 %0"
4608 [(set_attr "type" "arith")])
4609
ee04b091
OE
4610(define_insn_and_split "*ashlhi3_n"
4611 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4612 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
4613 (match_operand:HI 2 "const_int_operand" "n")))
4773afa4 4614 (clobber (reg:SI T_REG))]
ee04b091
OE
4615 "TARGET_SH1"
4616 "#"
4617 "&& reload_completed"
4773afa4 4618 [(use (reg:SI R0_REG))]
98e819b9
JW
4619{
4620 gen_shifty_hi_op (ASHIFT, operands);
4621 DONE;
56e25830
OE
4622})
4623
4624;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4625;; DImode shift left
4626
4627(define_expand "ashldi3"
4628 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4629 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4630 (match_operand:DI 2 "immediate_operand" "")))
4631 (clobber (reg:SI T_REG))])]
4632 ""
4633{
4634 if (TARGET_SHMEDIA)
4635 {
4636 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4637 DONE;
4638 }
4639 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
4640 {
4641 emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4642 DONE;
4643 }
4644 else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
4645 {
4646 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4647 DONE;
4648 }
4649 else
4650 FAIL;
4651})
4652
4653;; Expander for DImode shift left with SImode operations.
4654(define_expand "ashldi3_std"
4655 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4656 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4657 (match_operand:DI 2 "const_int_operand" "n")))]
4658 "TARGET_SH1 && INTVAL (operands[2]) < 32"
4659{
4660 rtx low_src = gen_lowpart (SImode, operands[1]);
4661 rtx high_src = gen_highpart (SImode, operands[1]);
4662 rtx dst = gen_reg_rtx (DImode);
4663 rtx low_dst = gen_lowpart (SImode, dst);
4664 rtx high_dst = gen_highpart (SImode, dst);
4665 rtx tmp0 = gen_reg_rtx (SImode);
4666 rtx tmp1 = gen_reg_rtx (SImode);
4667
4668 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
4669 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
4670 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
4671 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
4672 emit_move_insn (operands[0], dst);
4673 DONE;
4674})
4675
0f9a3fd3 4676(define_insn_and_split "ashldi3_k"
56e25830
OE
4677 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4678 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
4679 (const_int 1)))
4680 (clobber (reg:SI T_REG))]
4681 "TARGET_SH1"
0f9a3fd3
OE
4682 "#"
4683 "&& reload_completed"
4684 [(const_int 0)]
4685{
4686 rtx high = gen_highpart (SImode, operands[0]);
4687 rtx low = gen_lowpart (SImode, operands[0]);
4688 emit_insn (gen_shll (low, low));
4689 emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
4690 DONE;
4691})
98e819b9 4692
56e25830
OE
4693(define_insn "ashldi3_media"
4694 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4695 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4696 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4697 "TARGET_SHMEDIA"
4698 "@
4699 shlld %1, %2, %0
4700 shlli %1, %2, %0"
4701 [(set_attr "type" "arith_media")])
4702
4703(define_insn "*ashldisi3_media"
4704 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4705 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4706 (match_operand:DI 2 "const_int_operand" "n")))]
4707 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4708 "shlli.l %1, %2, %0"
4709 [(set_attr "type" "arith_media")
4710 (set_attr "highpart" "ignore")])
4711
4712;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4713;; SImode arithmetic shift right
d9241861 4714;;
56e25830
OE
4715;; We can't do HImode right shifts correctly unless we start out with an
4716;; explicit zero / sign extension; doing that would result in worse overall
4717;; code, so just let the machine independent code widen the mode.
4718;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
4719
4720(define_expand "ashrsi3"
4721 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4722 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4723 (match_operand:SI 2 "nonmemory_operand" "")))
4724 (clobber (reg:SI T_REG))])]
4725 ""
4726{
4727 if (TARGET_SHMEDIA)
4728 {
4729 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4730 DONE;
4731 }
4732 if (expand_ashiftrt (operands))
4733 DONE;
4734 else
4735 FAIL;
4736})
bc45ade3 4737
5592815a
OE
4738(define_insn "shar"
4739 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4740 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4741 (const_int 1)))
4742 (set (reg:SI T_REG)
4743 (and:SI (match_dup 1) (const_int 1)))]
4744 "TARGET_SH1"
4745 "shar %0"
4746 [(set_attr "type" "arith")])
4747
bc45ade3 4748(define_insn "ashrsi3_k"
73a4d10b 4749 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
aa684c94 4750 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
ffae286a 4751 (match_operand:SI 2 "const_int_operand" "M")))
4773afa4 4752 (clobber (reg:SI T_REG))]
fa5322fa 4753 "TARGET_SH1 && INTVAL (operands[2]) == 1"
bc45ade3 4754 "shar %0"
c49439f1 4755 [(set_attr "type" "arith")])
bc45ade3 4756
ee04b091 4757(define_insn_and_split "ashrsi2_16"
73a4d10b 4758 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
07a45e5c 4759 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
3e8bd1ce 4760 (const_int 16)))]
fa5322fa 4761 "TARGET_SH1"
1245df60 4762 "#"
ee04b091 4763 "&& 1"
1245df60
R
4764 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
4765 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
d9241861
OE
4766{
4767 operands[2] = gen_lowpart (HImode, operands[0]);
4768})
1245df60 4769
ee04b091 4770(define_insn_and_split "ashrsi2_31"
73a4d10b 4771 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1245df60
R
4772 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4773 (const_int 31)))
4773afa4 4774 (clobber (reg:SI T_REG))]
fa5322fa 4775 "TARGET_SH1"
1245df60 4776 "#"
ee04b091 4777 "&& 1"
1245df60 4778 [(const_int 0)]
1245df60 4779{
6e01d526 4780 emit_insn (gen_shll (operands[0], operands[1]));
be8cbce1 4781 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
73a4d10b 4782 DONE;
d9241861 4783})
73a4d10b 4784
6b005b88 4785(define_insn "ashrsi3_d"
73a4d10b 4786 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6b005b88
JW
4787 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4788 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
a594120b 4789 "TARGET_DYNSHIFT"
1245df60 4790 "shad %2,%0"
c49439f1 4791 [(set_attr "type" "dyn_shift")])
51aea58d 4792
0d7e008e 4793(define_insn "ashrsi3_n"
4773afa4
AO
4794 [(set (reg:SI R4_REG)
4795 (ashiftrt:SI (reg:SI R4_REG)
ffae286a 4796 (match_operand:SI 0 "const_int_operand" "i")))
4773afa4
AO
4797 (clobber (reg:SI T_REG))
4798 (clobber (reg:SI PR_REG))
0d7e008e 4799 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
fa5322fa 4800 "TARGET_SH1"
0d7e008e
SC
4801 "jsr @%1%#"
4802 [(set_attr "type" "sfunc")
0d7e008e
SC
4803 (set_attr "needs_delay_slot" "yes")])
4804
fa5322fa 4805(define_insn "ashrsi3_media"
73a4d10b 4806 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
b6d33983 4807 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
73a4d10b 4808 (match_operand:SI 2 "shift_count_operand" "r,n")))]
fa5322fa
AO
4809 "TARGET_SHMEDIA"
4810 "@
4811 shard.l %1, %2, %0
b6d33983 4812 shari.l %1, %2, %0"
73a4d10b
R
4813 [(set_attr "type" "arith_media")
4814 (set_attr "highpart" "ignore")])
fa5322fa 4815
56e25830
OE
4816;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4817;; DImode arithmetic shift right
4818
4819(define_expand "ashrdi3"
4820 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4821 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4822 (match_operand:DI 2 "immediate_operand" "")))
4773afa4 4823 (clobber (reg:SI T_REG))])]
bc45ade3 4824 ""
fa5322fa
AO
4825{
4826 if (TARGET_SHMEDIA)
4827 {
56e25830 4828 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
fa5322fa
AO
4829 DONE;
4830 }
56e25830 4831 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
fa5322fa 4832 FAIL;
d9241861 4833})
0d7e008e 4834
5592815a 4835(define_insn_and_split "ashrdi3_k"
56e25830
OE
4836 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4837 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4838 (const_int 1)))
4839 (clobber (reg:SI T_REG))]
4840 "TARGET_SH1"
5592815a
OE
4841 "#"
4842 "&& reload_completed"
4843 [(const_int 0)]
4844{
4845 rtx high = gen_highpart (SImode, operands[0]);
4846 rtx low = gen_lowpart (SImode, operands[0]);
4847 emit_insn (gen_shar (high, high));
4848 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
4849 DONE;
4850})
56e25830
OE
4851
4852(define_insn "ashrdi3_media"
4853 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4854 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4855 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4856 "TARGET_SHMEDIA
4857 && (arith_reg_dest (operands[0], DImode)
4858 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4859 "@
4860 shard %1, %2, %0
4861 shari %1, %2, %0"
4862 [(set_attr "type" "arith_media")])
4863
4864(define_insn "*ashrdisi3_media"
4865 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4866 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4867 (match_operand:DI 2 "const_int_operand" "n")))]
4868 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4869 "shari.l %1, %2, %0"
4870 [(set_attr "type" "arith_media")
4871 (set_attr "highpart" "ignore")])
4872
4873(define_insn "ashrdisi3_media_high"
4874 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4875 (truncate:SI
4876 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4877 (match_operand:DI 2 "const_int_operand" "n"))))]
4878 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4879 "shari %1, %2, %0"
4880 [(set_attr "type" "arith_media")])
4881
4882(define_insn "ashrdisi3_media_opaque"
4883 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4884 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4885 (match_operand:DI 2 "const_int_operand" "n")]
4886 UNSPEC_ASHIFTRT))]
4887 "TARGET_SHMEDIA"
4888 "shari %1, %2, %0"
4889 [(set_attr "type" "arith_media")])
4890
4891;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4892;; SImode logical shift right
4893
56e25830 4894(define_expand "lshrsi3"
6e01d526
OE
4895 [(set (match_operand:SI 0 "arith_reg_dest" "")
4896 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4897 (match_operand:SI 2 "shift_count_operand" "")))]
56e25830
OE
4898 ""
4899{
4900 if (TARGET_SHMEDIA)
4901 {
4902 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
4903 DONE;
4904 }
6e01d526
OE
4905
4906 /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
4907 here, otherwise the pattern will never match due to the shift amount reg
4908 negation. */
a594120b 4909 if (TARGET_DYNSHIFT
6e01d526 4910 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
56e25830 4911 {
6e01d526
OE
4912 rtx neg_count = force_reg (SImode,
4913 gen_int_mode (- INTVAL (operands[2]), SImode));
4914 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
56e25830
OE
4915 DONE;
4916 }
bc45ade3 4917
6e01d526
OE
4918 if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
4919 {
4920 rtx neg_count = gen_reg_rtx (SImode);
4921 emit_insn (gen_negsi2 (neg_count, operands[2]));
4922 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
4923 DONE;
4924 }
00f8ff66 4925
6e01d526
OE
4926 /* If the lshrsi3_* insn is going to clobber the T_REG it must be
4927 expanded here. */
4928 if (CONST_INT_P (operands[2])
4929 && sh_lshrsi_clobbers_t_reg_p (operands[2])
4930 && ! sh_dynamicalize_shift_p (operands[2]))
4931 {
4932 emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
4933 operands[2]));
4934 DONE;
4935 }
aadb5b43
OE
4936
4937 /* Expand a library call for the dynamic shift. */
4938 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4939 {
4940 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4941 rtx funcaddr = gen_reg_rtx (Pmode);
4942 function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
4943 emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
4944 DONE;
4945 }
6e01d526
OE
4946})
4947
4948(define_insn "lshrsi3_k"
5592815a
OE
4949 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4950 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
6e01d526 4951 (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
5592815a 4952 "TARGET_SH1"
6e01d526 4953 "shlr%O2 %0"
5592815a
OE
4954 [(set_attr "type" "arith")])
4955
6e01d526 4956(define_insn_and_split "lshrsi3_d"
73a4d10b 4957 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
07a45e5c 4958 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
6e01d526
OE
4959 (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
4960 "TARGET_DYNSHIFT"
4961 "shld %2,%0"
4962 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4963 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
4964 [(const_int 0)]
4965{
4966 if (satisfies_constraint_P27 (operands[2]))
4967 {
4968 /* This will not be done for a shift amount of 1, because it would
4969 clobber the T_REG. */
4970 emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
4971 DONE;
4972 }
4973 else if (! satisfies_constraint_P27 (operands[2]))
4974 {
4975 /* This must happen before reload, otherwise the constant will be moved
4976 into a register due to the "r" constraint, after which this split
4977 cannot be done anymore.
4978 Unfortunately the move insn will not always be eliminated.
4979 Also, here we must not create a shift sequence that clobbers the
4980 T_REG. */
4981 emit_move_insn (operands[0], operands[1]);
4982 gen_shifty_op (LSHIFTRT, operands);
4983 DONE;
4984 }
0d7e008e 4985
6e01d526
OE
4986 FAIL;
4987}
4988 [(set_attr "type" "dyn_shift")])
4989
aadb5b43
OE
4990;; If dynamic shifts are not available use a library function.
4991;; By specifying the pattern we reduce the number of call clobbered regs.
4992;; In order to make combine understand the truncation of the shift amount
4993;; operand we have to allow it to use pseudo regs for the shift operands.
4994(define_insn "lshrsi3_d_call"
4995 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4996 (lshiftrt:SI (reg:SI R4_REG)
4997 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4998 (const_int 31))))
4999 (use (match_operand:SI 2 "arith_reg_operand" "r"))
5000 (clobber (reg:SI T_REG))
5001 (clobber (reg:SI PR_REG))]
5002 "TARGET_SH1 && !TARGET_DYNSHIFT"
5003 "jsr @%2%#"
5004 [(set_attr "type" "sfunc")
5005 (set_attr "needs_delay_slot" "yes")])
5006
6e01d526 5007(define_insn_and_split "lshrsi3_n"
73a4d10b 5008 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
07a45e5c 5009 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
6e01d526
OE
5010 (match_operand:SI 2 "not_p27_rshift_count_operand")))]
5011 "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5012 "#"
5013 "&& (reload_completed
5014 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5015 [(const_int 0)]
5016{
5017 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5018 {
5019 /* If this pattern was picked and dynamic shifts are supported, switch
5020 to dynamic shift pattern before reload. */
5021 operands[2] = force_reg (SImode,
5022 gen_int_mode (- INTVAL (operands[2]), SImode));
5023 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5024 }
5025 else
5026 gen_shifty_op (LSHIFTRT, operands);
0d7e008e 5027
6e01d526
OE
5028 DONE;
5029})
5030
5031;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5032;; the shlr pattern.
5033(define_insn_and_split "lshrsi3_n_clobbers_t"
73a4d10b 5034 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
0d7e008e 5035 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
6e01d526 5036 (match_operand:SI 2 "not_p27_rshift_count_operand")))
4773afa4 5037 (clobber (reg:SI T_REG))]
6e01d526 5038 "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
07a45e5c 5039 "#"
6e01d526
OE
5040 "&& (reload_completed || INTVAL (operands[2]) == 31
5041 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5042 [(const_int 0)]
ee04b091 5043{
6e01d526
OE
5044 if (INTVAL (operands[2]) == 31)
5045 {
5046 emit_insn (gen_shll (operands[0], operands[1]));
5047 emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5048 }
5049 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5050 {
5051 /* If this pattern was picked and dynamic shifts are supported, switch
5052 to dynamic shift pattern before reload. */
5053 operands[2] = force_reg (SImode,
5054 gen_int_mode (- INTVAL (operands[2]), SImode));
5055 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5056 }
5057 else
5058 gen_shifty_op (LSHIFTRT, operands);
5059
ee04b091 5060 DONE;
56e25830 5061})
bc45ade3 5062
6e01d526
OE
5063(define_insn "shlr"
5064 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5065 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5066 (const_int 1)))
5067 (set (reg:SI T_REG)
5068 (and:SI (match_dup 1) (const_int 1)))]
5069 "TARGET_SH1"
5070 "shlr %0"
5071 [(set_attr "type" "arith")])
5072
fa5322fa 5073(define_insn "lshrsi3_media"
73a4d10b 5074 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
b6d33983 5075 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
73a4d10b 5076 (match_operand:SI 2 "shift_count_operand" "r,n")))]
fa5322fa
AO
5077 "TARGET_SHMEDIA"
5078 "@
5079 shlrd.l %1, %2, %0
b6d33983 5080 shlri.l %1, %2, %0"
73a4d10b
R
5081 [(set_attr "type" "arith_media")
5082 (set_attr "highpart" "ignore")])
fa5322fa 5083
56e25830
OE
5084;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5085;; DImode logical shift right
bc45ade3 5086
56e25830 5087(define_expand "lshrdi3"
ffae286a 5088 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
56e25830
OE
5089 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5090 (match_operand:DI 2 "immediate_operand" "")))
5091 (clobber (reg:SI T_REG))])]
bc45ade3 5092 ""
fa5322fa
AO
5093{
5094 if (TARGET_SHMEDIA)
5095 {
56e25830 5096 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
ed7910bb
KK
5097 DONE;
5098 }
56e25830 5099 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
fa5322fa 5100 FAIL;
d9241861 5101})
ffae286a 5102
5592815a 5103(define_insn_and_split "lshrdi3_k"
73a4d10b 5104 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
b9654711 5105 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
8e87e161 5106 (const_int 1)))
4773afa4 5107 (clobber (reg:SI T_REG))]
fa5322fa 5108 "TARGET_SH1"
5592815a
OE
5109 "#"
5110 "&& reload_completed"
5111 [(const_int 0)]
5112{
5113 rtx high = gen_highpart (SImode, operands[0]);
5114 rtx low = gen_lowpart (SImode, operands[0]);
5115 emit_insn (gen_shlr (high, high));
5116 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5117 DONE;
5118})
bc45ade3 5119
fa5322fa 5120(define_insn "lshrdi3_media"
73a4d10b 5121 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
fa5322fa 5122 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
73a4d10b
R
5123 (match_operand:DI 2 "shift_count_operand" "r,n")))]
5124 "TARGET_SHMEDIA
5125 && (arith_reg_dest (operands[0], DImode)
f3536097 5126 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
fa5322fa
AO
5127 "@
5128 shlrd %1, %2, %0
2ad65b0e
SC
5129 shlri %1, %2, %0"
5130 [(set_attr "type" "arith_media")])
fa5322fa 5131
73a4d10b
R
5132(define_insn "*lshrdisi3_media"
5133 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5134 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5135 (match_operand:DI 2 "const_int_operand" "n")))]
5136 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5137 "shlri.l %1, %2, %0"
5138 [(set_attr "type" "arith_media")
5139 (set_attr "highpart" "ignore")])
5140
56e25830
OE
5141;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5142;; Combined left/right shifts
98e819b9
JW
5143
5144(define_split
5145 [(set (match_operand:SI 0 "register_operand" "")
5146 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
e69d1422
R
5147 (match_operand:SI 2 "const_int_operand" ""))
5148 (match_operand:SI 3 "const_int_operand" "")))]
85af47b9 5149 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4773afa4 5150 [(use (reg:SI R0_REG))]
d9241861
OE
5151{
5152 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5153 FAIL;
5154 DONE;
5155})
98e819b9
JW
5156
5157(define_split
5158 [(set (match_operand:SI 0 "register_operand" "")
5159 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
e69d1422
R
5160 (match_operand:SI 2 "const_int_operand" ""))
5161 (match_operand:SI 3 "const_int_operand" "")))
4773afa4 5162 (clobber (reg:SI T_REG))]
85af47b9 5163 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4773afa4 5164 [(use (reg:SI R0_REG))]
d9241861
OE
5165{
5166 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5167 FAIL;
5168 DONE;
5169})
98e819b9
JW
5170
5171(define_insn ""
5172 [(set (match_operand:SI 0 "register_operand" "=r")
5173 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5174 (match_operand:SI 2 "const_int_operand" "n"))
5175 (match_operand:SI 3 "const_int_operand" "n")))
4773afa4 5176 (clobber (reg:SI T_REG))]
fa5322fa 5177 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
d9241861 5178 "#"
98e819b9
JW
5179 [(set (attr "length")
5180 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5181 (const_string "4")
5182 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5183 (const_string "6")
5184 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5185 (const_string "8")
5186 (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5187 (const_string "10")
5188 (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5189 (const_string "12")
5190 (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5191 (const_string "14")
5192 (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5193 (const_string "16")]
5194 (const_string "18")))
5195 (set_attr "type" "arith")])
5196
5197(define_insn ""
5198 [(set (match_operand:SI 0 "register_operand" "=z")
5199 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5200 (match_operand:SI 2 "const_int_operand" "n"))
5201 (match_operand:SI 3 "const_int_operand" "n")))
4773afa4 5202 (clobber (reg:SI T_REG))]
fa5322fa 5203 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
d9241861 5204 "#"
98e819b9
JW
5205 [(set (attr "length")
5206 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5207 (const_string "4")
5208 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5209 (const_string "6")
5210 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5211 (const_string "8")]
5212 (const_string "10")))
5213 (set_attr "type" "arith")])
5214
5215;; shift left / and combination with a scratch register: The combine pass
5216;; does not accept the individual instructions, even though they are
5217;; cheap. But it needs a precise description so that it is usable after
5218;; reload.
5219(define_insn "and_shl_scratch"
5220 [(set (match_operand:SI 0 "register_operand" "=r,&r")
4773afa4
AO
5221 (lshiftrt:SI
5222 (ashift:SI
5223 (and:SI
5224 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5225 (match_operand:SI 2 "const_int_operand" "N,n"))
5226 (match_operand:SI 3 "" "0,r"))
5227 (match_operand:SI 4 "const_int_operand" "n,n"))
5228 (match_operand:SI 5 "const_int_operand" "n,n")))
5229 (clobber (reg:SI T_REG))]
fa5322fa 5230 "TARGET_SH1"
98e819b9
JW
5231 "#"
5232 [(set (attr "length")
5233 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5234 (const_string "4")
5235 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5236 (const_string "6")
5237 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
9788ff4d 5238 (const_string "8")
98e819b9
JW
5239 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5240 (const_string "10")]
5241 (const_string "12")))
5242 (set_attr "type" "arith")])
5243
5244(define_split
e69d1422 5245 [(set (match_operand:SI 0 "register_operand" "")
4773afa4
AO
5246 (lshiftrt:SI
5247 (ashift:SI
5248 (and:SI
e69d1422
R
5249 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5250 (match_operand:SI 2 "const_int_operand" ""))
5251 (match_operand:SI 3 "register_operand" ""))
5252 (match_operand:SI 4 "const_int_operand" ""))
5253 (match_operand:SI 5 "const_int_operand" "")))
4773afa4 5254 (clobber (reg:SI T_REG))]
fa5322fa 5255 "TARGET_SH1"
4773afa4 5256 [(use (reg:SI R0_REG))]
98e819b9 5257{
fc2380b9 5258 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
98e819b9
JW
5259
5260 if (INTVAL (operands[2]))
5261 {
5262 gen_shifty_op (LSHIFTRT, operands);
98e819b9
JW
5263 }
5264 emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5265 operands[2] = operands[4];
5266 gen_shifty_op (ASHIFT, operands);
5267 if (INTVAL (operands[5]))
5268 {
5269 operands[2] = operands[5];
5270 gen_shifty_op (LSHIFTRT, operands);
5271 }
5272 DONE;
d9241861 5273})
98e819b9
JW
5274
5275;; signed left/right shift combination.
5276(define_split
e69d1422 5277 [(set (match_operand:SI 0 "register_operand" "")
4773afa4 5278 (sign_extract:SI
e69d1422
R
5279 (ashift:SI (match_operand:SI 1 "register_operand" "")
5280 (match_operand:SI 2 "const_int_operand" ""))
5281 (match_operand:SI 3 "const_int_operand" "")
4773afa4
AO
5282 (const_int 0)))
5283 (clobber (reg:SI T_REG))]
fa5322fa 5284 "TARGET_SH1"
4773afa4 5285 [(use (reg:SI R0_REG))]
d9241861
OE
5286{
5287 if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5288 FAIL;
5289 DONE;
5290})
98e819b9
JW
5291
5292(define_insn "shl_sext_ext"
5293 [(set (match_operand:SI 0 "register_operand" "=r")
4773afa4
AO
5294 (sign_extract:SI
5295 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5296 (match_operand:SI 2 "const_int_operand" "n"))
5297 (match_operand:SI 3 "const_int_operand" "n")
5298 (const_int 0)))
5299 (clobber (reg:SI T_REG))]
fa5322fa 5300 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
98e819b9
JW
5301 "#"
5302 [(set (attr "length")
68ed2b9c 5303 (cond [(match_test "shl_sext_length (insn)")
98e819b9
JW
5304 (const_string "2")
5305 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5306 (const_string "4")
5307 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5308 (const_string "6")
5309 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5310 (const_string "8")
5311 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5312 (const_string "10")
5313 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5314 (const_string "12")
5315 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5316 (const_string "14")
5317 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5318 (const_string "16")]
5319 (const_string "18")))
5320 (set_attr "type" "arith")])
5321
5322(define_insn "shl_sext_sub"
5323 [(set (match_operand:SI 0 "register_operand" "=z")
e11cddec
AO
5324 (sign_extract:SI
5325 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5326 (match_operand:SI 2 "const_int_operand" "n"))
5327 (match_operand:SI 3 "const_int_operand" "n")
5328 (const_int 0)))
4773afa4 5329 (clobber (reg:SI T_REG))]
fa5322fa 5330 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
98e819b9
JW
5331 "#"
5332 [(set (attr "length")
5333 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5334 (const_string "6")
5335 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5336 (const_string "8")
5337 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5338 (const_string "10")
5339 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5340 (const_string "12")]
5341 (const_string "14")))
5342 (set_attr "type" "arith")])
5343
977eef43
JW
5344;; These patterns are found in expansions of DImode shifts by 16, and
5345;; allow the xtrct instruction to be generated from C source.
5346
5347(define_insn "xtrct_left"
73a4d10b 5348 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
977eef43
JW
5349 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5350 (const_int 16))
5351 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5352 (const_int 16))))]
fa5322fa 5353 "TARGET_SH1"
1245df60 5354 "xtrct %1,%0"
c49439f1 5355 [(set_attr "type" "arith")])
977eef43
JW
5356
5357(define_insn "xtrct_right"
73a4d10b 5358 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
977eef43
JW
5359 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5360 (const_int 16))
5361 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5362 (const_int 16))))]
fa5322fa 5363 "TARGET_SH1"
1245df60 5364 "xtrct %2,%0"
c49439f1 5365 [(set_attr "type" "arith")])
fae15c93 5366
bc45ade3
SC
5367;; -------------------------------------------------------------------------
5368;; Unary arithmetic
5369;; -------------------------------------------------------------------------
5370
7222fdd8 5371(define_insn "negc"
73a4d10b 5372 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4773afa4 5373 (neg:SI (plus:SI (reg:SI T_REG)
51bd623f 5374 (match_operand:SI 1 "arith_reg_operand" "r"))))
4773afa4
AO
5375 (set (reg:SI T_REG)
5376 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
51bd623f 5377 (const_int 0)))]
fa5322fa 5378 "TARGET_SH1"
8e87e161 5379 "negc %1,%0"
c49439f1 5380 [(set_attr "type" "arith")])
bc45ade3 5381
0c66c562
OE
5382;; A simplified version of the negc insn, where the exact value of the
5383;; T bit doesn't matter. This is easier for combine to pick up.
5384;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5385;; extra patterns for this case.
5386(define_insn "*negc"
5387 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5388 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5389 (match_operand:SI 2 "t_reg_operand" "")))
5390 (clobber (reg:SI T_REG))]
5391 "TARGET_SH1"
5392 "negc %1,%0"
5393 [(set_attr "type" "arith")])
5394
fa5322fa 5395(define_insn "*negdi_media"
73a4d10b 5396 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
fa5322fa
AO
5397 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5398 "TARGET_SHMEDIA"
2ad65b0e
SC
5399 "sub r63, %1, %0"
5400 [(set_attr "type" "arith_media")])
fa5322fa 5401
39f2bcb5
OE
5402;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
5403;; combined.
8e87e161 5404(define_expand "negdi2"
01850a76
OE
5405 [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
5406 (neg:DI (match_operand:DI 1 "arith_reg_operand")))
5407 (clobber (reg:SI T_REG))])]
5408 "TARGET_SH1")
39f2bcb5
OE
5409
5410(define_insn_and_split "*negdi2"
01850a76
OE
5411 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
5412 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))
5413 (clobber (reg:SI T_REG))]
39f2bcb5
OE
5414 "TARGET_SH1"
5415 "#"
01850a76 5416 "&& reload_completed"
39f2bcb5 5417 [(const_int 0)]
ffae286a 5418{
39f2bcb5 5419 emit_insn (gen_clrt ());
01850a76
OE
5420 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5421 gen_lowpart (SImode, operands[1])));
5422 emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5423 gen_highpart (SImode, operands[1])));
39f2bcb5 5424 DONE;
d9241861 5425})
8e87e161 5426
bc45ade3 5427(define_insn "negsi2"
73a4d10b 5428 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
aa684c94 5429 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
fa5322fa 5430 "TARGET_SH1"
bc45ade3 5431 "neg %1,%0"
c49439f1 5432 [(set_attr "type" "arith")])
bc45ade3 5433
f429813d 5434(define_insn_and_split "one_cmplsi2"
73a4d10b 5435 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
aa684c94 5436 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
fa5322fa 5437 "TARGET_SH1"
bc45ade3 5438 "not %1,%0"
f429813d
OE
5439 "&& can_create_pseudo_p ()"
5440 [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
5441 (set (match_dup 0) (reg:SI T_REG))]
5442{
5443/* PR 54685
5444 If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
5445 sequence:
5446
5447 (set (reg0) (not:SI (reg0) (reg1)))
5448 (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
5449 (clobber (reg:SI T_REG))])
5450
5451 ... match and combine the sequence manually in the split pass after the
5452 combine pass. Notice that combine does try the target pattern of this
5453 split, but if the pattern is added it interferes with other patterns, in
5454 particular with the div0s comparisons.
5455 This could also be done with a peephole but doing it here before register
5456 allocation can save one temporary.
5457 When we're here, the not:SI pattern obviously has been matched already
5458 and we only have to see whether the following insn is the left shift. */
5459
5460 rtx i = next_nonnote_insn_bb (curr_insn);
5461 if (i == NULL_RTX || !NONJUMP_INSN_P (i))
5462 FAIL;
5463
5464 rtx p = PATTERN (i);
5465 if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
5466 FAIL;
5467
5468 rtx p0 = XVECEXP (p, 0, 0);
5469 rtx p1 = XVECEXP (p, 0, 1);
5470
5471 if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */
5472 GET_CODE (p0) == SET
5473 && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
5474 && REG_P (XEXP (XEXP (p0, 1), 0))
5475 && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
5476 && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
5477 && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
5478
5479 /* (clobber (reg:SI T_REG)) */
5480 && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
5481 && REGNO (XEXP (p1, 0)) == T_REG)
5482 {
5483 operands[0] = XEXP (p0, 0);
5484 set_insn_deleted (i);
5485 }
5486 else
5487 FAIL;
5488}
c49439f1 5489 [(set_attr "type" "arith")])
fa5322fa 5490
73a4d10b
R
5491(define_expand "one_cmpldi2"
5492 [(set (match_operand:DI 0 "arith_reg_dest" "")
5493 (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
5494 (const_int -1)))]
5495 "TARGET_SHMEDIA" "")
5496
01850a76
OE
5497(define_expand "abs<mode>2"
5498 [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
5499 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5500 (clobber (reg:SI T_REG))])]
5501 "TARGET_SH1")
39f2bcb5 5502
01850a76
OE
5503(define_insn_and_split "*abs<mode>2"
5504 [(set (match_operand:SIDI 0 "arith_reg_dest")
5505 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
5506 (clobber (reg:SI T_REG))]
39f2bcb5
OE
5507 "TARGET_SH1"
5508 "#"
01850a76 5509 "&& can_create_pseudo_p ()"
73a4d10b 5510 [(const_int 0)]
39f2bcb5 5511{
01850a76
OE
5512 if (<MODE>mode == SImode)
5513 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5514 else
5515 {
5516 rtx high_src = gen_highpart (SImode, operands[1]);
5517 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5518 }
5519
5520 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5521 const1_rtx));
39f2bcb5 5522 DONE;
d9241861 5523})
73a4d10b 5524
01850a76
OE
5525(define_insn_and_split "*negabs<mode>2"
5526 [(set (match_operand:SIDI 0 "arith_reg_dest")
5527 (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
5528 (clobber (reg:SI T_REG))]
39f2bcb5
OE
5529 "TARGET_SH1"
5530 "#"
01850a76 5531 "&& can_create_pseudo_p ()"
39f2bcb5 5532 [(const_int 0)]
39f2bcb5 5533{
01850a76
OE
5534 if (<MODE>mode == SImode)
5535 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5536 else
5537 {
5538 rtx high_src = gen_highpart (SImode, operands[1]);
5539 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5540 }
5541
5542 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
5543 const0_rtx));
39f2bcb5 5544 DONE;
d9241861 5545})
39f2bcb5 5546
39f2bcb5
OE
5547;; The SH4 202 can do zero-offset branches without pipeline stalls.
5548;; This can be used as some kind of conditional execution, which is useful
5549;; for abs.
5550;; Actually the instruction scheduling should decide whether to use a
5551;; zero-offset branch or not for any generic case involving a single
5552;; instruction on SH4 202.
5553
5554(define_insn_and_split "negsi_cond"
5555 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
01850a76
OE
5556 (if_then_else
5557 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
5558 (match_operand:SI 1 "arith_reg_operand" "0,0")
5559 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
f34ee0b2 5560 "TARGET_SH1 && TARGET_ZDCBRANCH"
35ed5a70
OE
5561{
5562 static const char* alt[] =
5563 {
5564 "bt 0f" "\n"
5565 " neg %2,%0" "\n"
5566 "0:",
5567
5568 "bf 0f" "\n"
5569 " neg %2,%0" "\n"
5570 "0:"
5571 };
5572 return alt[which_alternative];
5573}
f34ee0b2 5574 "TARGET_SH1 && ! TARGET_ZDCBRANCH"
39f2bcb5 5575 [(const_int 0)]
39f2bcb5
OE
5576{
5577 rtx skip_neg_label = gen_label_rtx ();
5578
01850a76 5579 emit_move_insn (operands[0], operands[1]);
39f2bcb5
OE
5580
5581 emit_jump_insn (INTVAL (operands[3])
b4eca9c8
OE
5582 ? gen_branch_true (skip_neg_label)
5583 : gen_branch_false (skip_neg_label));
39f2bcb5
OE
5584
5585 emit_label_after (skip_neg_label,
5586 emit_insn (gen_negsi2 (operands[0], operands[1])));
5587 DONE;
d9241861 5588}
73a4d10b
R
5589 [(set_attr "type" "arith") ;; poor approximation
5590 (set_attr "length" "4")])
5591
5e44ea89 5592(define_insn_and_split "negdi_cond"
01850a76
OE
5593 [(set (match_operand:DI 0 "arith_reg_dest")
5594 (if_then_else
5595 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
5596 (match_operand:DI 1 "arith_reg_operand")
5597 (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
5598 (clobber (reg:SI T_REG))]
5e44ea89
OE
5599 "TARGET_SH1"
5600 "#"
01850a76 5601 "&& can_create_pseudo_p ()"
5e44ea89
OE
5602 [(const_int 0)]
5603{
5e44ea89
OE
5604 rtx skip_neg_label = gen_label_rtx ();
5605
01850a76 5606 emit_move_insn (operands[0], operands[1]);
5e44ea89
OE
5607
5608 emit_jump_insn (INTVAL (operands[3])
b4eca9c8
OE
5609 ? gen_branch_true (skip_neg_label)
5610 : gen_branch_false (skip_neg_label));
5e44ea89
OE
5611
5612 if (!INTVAL (operands[3]))
5613 emit_insn (gen_clrt ());
5614
01850a76
OE
5615 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
5616 gen_lowpart (SImode, operands[1])));
5617 emit_label_after (skip_neg_label,
5618 emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
5619 gen_highpart (SImode, operands[1]))));
5e44ea89
OE
5620 DONE;
5621})
638a085f
OE
5622
5623(define_expand "bswapsi2"
5624 [(set (match_operand:SI 0 "arith_reg_dest" "")
5625 (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
5626 "TARGET_SH1"
5627{
5628 if (! can_create_pseudo_p ())
5629 FAIL;
5630 else
5631 {
5632 rtx tmp0 = gen_reg_rtx (SImode);
5633 rtx tmp1 = gen_reg_rtx (SImode);
5634
5635 emit_insn (gen_swapbsi2 (tmp0, operands[1]));
5636 emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
5637 emit_insn (gen_swapbsi2 (operands[0], tmp1));
5638 DONE;
5639 }
5640})
5641
5642(define_insn "swapbsi2"
5643 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5644 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
5645 (const_int 4294901760))
5646 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5647 (const_int 65280))
5648 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5649 (const_int 255)))))]
5650 "TARGET_SH1"
5651 "swap.b %1,%0"
5652 [(set_attr "type" "arith")])
5653
3f8d753f
OE
5654;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
5655;; partial byte swap expressions such as...
5656;; ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
5657;; ...which are currently not handled by the tree optimizers.
5658;; The combine pass will not initially try to combine the full expression,
5659;; but only some sub-expressions. In such a case the *swapbisi2_and_shl8
5660;; pattern acts as an intermediate pattern that will eventually lead combine
5661;; to the swapbsi2 pattern above.
5662;; As a side effect this also improves code that does (x & 0xFF) << 8
5663;; or (x << 8) & 0xFF00.
5664(define_insn_and_split "*swapbisi2_and_shl8"
5665 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5666 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5667 (const_int 8))
5668 (const_int 65280))
5669 (match_operand:SI 2 "arith_reg_operand" "r")))]
5670 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5671 "#"
5672 "&& can_create_pseudo_p ()"
5673 [(const_int 0)]
5674{
5675 rtx tmp0 = gen_reg_rtx (SImode);
5676 rtx tmp1 = gen_reg_rtx (SImode);
5677
5678 emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
5679 emit_insn (gen_swapbsi2 (tmp1, tmp0));
5680 emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
5681 DONE;
5682})
5683
5684;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
5685;; intermediate pattern that will help the combine pass arriving at swapbsi2.
5686(define_insn_and_split "*swapbhisi2"
5687 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5688 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5689 (const_int 8))
5690 (const_int 65280))
5691 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
5692 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5693 "#"
5694 "&& can_create_pseudo_p ()"
5695 [(const_int 0)]
5696{
5697 rtx tmp = gen_reg_rtx (SImode);
5698
5699 emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
5700 emit_insn (gen_swapbsi2 (operands[0], tmp));
5701 DONE;
5702})
5703
5704;; In some cases the swapbsi2 pattern might leave a sequence such as...
5705;; swap.b r4,r4
5706;; mov r4,r0
5707;;
5708;; which can be simplified to...
5709;; swap.b r4,r0
5710(define_peephole2
5711 [(set (match_operand:SI 0 "arith_reg_dest" "")
5712 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5713 (const_int 4294901760))
5714 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5715 (const_int 65280))
5716 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5717 (const_int 255)))))
5718 (set (match_operand:SI 2 "arith_reg_dest" "")
5719 (match_dup 0))]
5720 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
5721 [(set (match_dup 2)
5722 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5723 (const_int 4294901760))
5724 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5725 (const_int 65280))
5726 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5727 (const_int 255)))))])
5728
bc45ade3
SC
5729\f
5730;; -------------------------------------------------------------------------
5731;; Zero extension instructions
5732;; -------------------------------------------------------------------------
5733
fa5322fa 5734(define_insn "zero_extendsidi2"
73a4d10b 5735 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
b6d33983 5736 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
fa5322fa 5737 "TARGET_SHMEDIA"
b6d33983 5738 "addz.l %1, r63, %0"
73a4d10b
R
5739 [(set_attr "type" "arith_media")
5740 (set_attr "highpart" "extend")])
fa5322fa
AO
5741
5742(define_insn "zero_extendhidi2"
5743 [(set (match_operand:DI 0 "register_operand" "=r,r")
b6d33983 5744 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
fa5322fa
AO
5745 "TARGET_SHMEDIA"
5746 "@
5747 #
b6d33983 5748 ld%M1.uw %m1, %0"
73a4d10b
R
5749 [(set_attr "type" "*,load_media")
5750 (set (attr "highpart")
68ed2b9c 5751 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
5752 (const_string "user")]
5753 (const_string "ignore")))])
fa5322fa
AO
5754
5755(define_split
e69d1422
R
5756 [(set (match_operand:DI 0 "register_operand" "")
5757 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
fa5322fa
AO
5758 "TARGET_SHMEDIA && reload_completed"
5759 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
b6d33983 5760 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
b6d33983
R
5761{
5762 if (GET_CODE (operands[1]) == TRUNCATE)
5763 operands[1] = XEXP (operands[1], 0);
d9241861 5764})
b6d33983 5765
fae778eb
KH
5766;; ??? when a truncated input to a zero_extend is reloaded, reload will
5767;; reload the entire truncate expression.
b6d33983 5768(define_insn_and_split "*loaddi_trunc"
73a4d10b 5769 [(set (match_operand 0 "any_register_operand" "=r")
b6d33983
R
5770 (truncate (match_operand:DI 1 "memory_operand" "m")))]
5771 "TARGET_SHMEDIA && reload_completed"
5772 "#"
5773 "TARGET_SHMEDIA && reload_completed"
5774 [(set (match_dup 0) (match_dup 1))]
d9241861
OE
5775{
5776 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5777})
fa5322fa
AO
5778
5779(define_insn "zero_extendqidi2"
5780 [(set (match_operand:DI 0 "register_operand" "=r,r")
b6d33983 5781 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
fa5322fa
AO
5782 "TARGET_SHMEDIA"
5783 "@
5784 andi %1, 255, %0
b6d33983 5785 ld%M1.ub %m1, %0"
73a4d10b
R
5786 [(set_attr "type" "arith_media,load_media")
5787 (set (attr "highpart")
68ed2b9c 5788 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
5789 (const_string "user")]
5790 (const_string "ignore")))])
b6d33983 5791
7fa4bf9b
OE
5792(define_expand "zero_extend<mode>si2"
5793 [(set (match_operand:SI 0 "arith_reg_dest")
5794 (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
fa5322fa 5795
b4eca9c8 5796(define_insn_and_split "*zero_extend<mode>si2_compact"
73a4d10b 5797 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7fa4bf9b 5798 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
fa5322fa 5799 "TARGET_SH1"
7fa4bf9b 5800 "extu.<bw> %1,%0"
b4eca9c8
OE
5801 "&& can_create_pseudo_p ()"
5802 [(set (match_dup 0) (match_dup 2))]
5803{
5804 /* Sometimes combine fails to combine a T bit or negated T bit store to a
5805 reg with a following zero extension. In the split pass after combine,
5806 try to figure the extended reg was set. If it originated from the T
5807 bit we can replace the zero extension with a reg move, which will be
5808 eliminated. Notice that this also helps the *cbranch_t splitter when
5809 it tries to post-combine tests and conditional branches, as it does not
5810 check for zero extensions. */
26943929 5811 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
b4eca9c8
OE
5812 if (operands[2] == NULL_RTX)
5813 FAIL;
5814}
c49439f1 5815 [(set_attr "type" "arith")])
bc45ade3 5816
b6d33983
R
5817(define_insn "*zero_extendhisi2_media"
5818 [(set (match_operand:SI 0 "register_operand" "=r,r")
5819 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5820 "TARGET_SHMEDIA"
5821 "@
5822 #
5823 ld%M1.uw %m1, %0"
73a4d10b
R
5824 [(set_attr "type" "arith_media,load_media")
5825 (set (attr "highpart")
68ed2b9c 5826 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
5827 (const_string "user")]
5828 (const_string "ignore")))])
b6d33983
R
5829
5830(define_split
e69d1422
R
5831 [(set (match_operand:SI 0 "register_operand" "")
5832 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
b6d33983 5833 "TARGET_SHMEDIA && reload_completed"
73a4d10b 5834 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
b6d33983 5835 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
b6d33983 5836{
73a4d10b
R
5837 rtx op1 = operands[1];
5838
5839 if (GET_CODE (op1) == TRUNCATE)
5840 op1 = XEXP (op1, 0);
5841 operands[2]
5842 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
5843 subreg_lowpart_offset (SImode, GET_MODE (op1)));
d9241861 5844})
b6d33983 5845
b6d33983
R
5846(define_insn "*zero_extendqisi2_media"
5847 [(set (match_operand:SI 0 "register_operand" "=r,r")
5848 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5849 "TARGET_SHMEDIA"
5850 "@
5851 andi %1, 255, %0
5852 ld%M1.ub %m1, %0"
73a4d10b
R
5853 [(set_attr "type" "arith_media,load_media")
5854 (set (attr "highpart")
68ed2b9c 5855 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
5856 (const_string "user")]
5857 (const_string "ignore")))])
b6d33983 5858
bc45ade3 5859(define_insn "zero_extendqihi2"
73a4d10b 5860 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
aa684c94 5861 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
fa5322fa 5862 "TARGET_SH1"
bc45ade3 5863 "extu.b %1,%0"
c49439f1 5864 [(set_attr "type" "arith")])
fae15c93 5865
24c18ad8
OE
5866;; SH2A supports two zero extending load instructions: movu.b and movu.w.
5867;; They could also be used for simple memory addresses like @Rn by setting
5868;; the displacement value to zero. However, doing so too early results in
5869;; missed opportunities for other optimizations such as post-inc or index
5870;; addressing loads.
5871;; Although the 'zero_extend_movu_operand' predicate does not allow simple
5872;; register addresses (an address without a displacement, index, post-inc),
5873;; zero-displacement addresses might be generated during reload, wich are
5874;; simplified to simple register addresses in turn. Thus, we have to
5875;; provide the Sdd and Sra alternatives in the patterns.
7fa4bf9b 5876(define_insn "*zero_extend<mode>si2_disp_mem"
24c18ad8
OE
5877 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5878 (zero_extend:SI
7fa4bf9b 5879 (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
24c18ad8
OE
5880 "TARGET_SH2A"
5881 "@
7fa4bf9b
OE
5882 movu.<bw> %1,%0
5883 movu.<bw> @(0,%t1),%0"
24c18ad8
OE
5884 [(set_attr "type" "load")
5885 (set_attr "length" "4")])
5886
5887;; Convert the zero extending loads in sequences such as:
5888;; movu.b @(1,r5),r0 movu.w @(2,r5),r0
5889;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
5890;;
5891;; back to sign extending loads like:
5892;; mov.b @(1,r5),r0 mov.w @(2,r5),r0
5893;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
5894;;
5895;; if the extension type is irrelevant. The sign extending mov.{b|w} insn
5896;; is only 2 bytes in size if the displacement is {K04|K05}.
5897;; If the displacement is greater it doesn't matter, so we convert anyways.
5898(define_peephole2
5899 [(set (match_operand:SI 0 "arith_reg_dest" "")
5900 (zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
5901 (set (match_operand 2 "general_operand" "")
5902 (match_operand 3 "arith_reg_operand" ""))]
5903 "TARGET_SH2A
5904 && REGNO (operands[0]) == REGNO (operands[3])
5905 && peep2_reg_dead_p (2, operands[0])
5906 && GET_MODE_SIZE (GET_MODE (operands[2]))
5907 <= GET_MODE_SIZE (GET_MODE (operands[1]))"
5908 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
5909 (set (match_dup 2) (match_dup 3))])
5910
5911;; Fold sequences such as
5912;; mov.b @r3,r7
5913;; extu.b r7,r7
5914;; into
5915;; movu.b @(0,r3),r7
5916;; This does not reduce the code size but the number of instructions is
5917;; halved, which results in faster code.
5918(define_peephole2
5919 [(set (match_operand:SI 0 "arith_reg_dest" "")
5920 (sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
5921 (set (match_operand:SI 2 "arith_reg_dest" "")
5922 (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
5923 "TARGET_SH2A
5924 && GET_MODE (operands[1]) == GET_MODE (operands[3])
5925 && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
5926 && REGNO (operands[0]) == REGNO (operands[3])
5927 && (REGNO (operands[2]) == REGNO (operands[0])
5928 || peep2_reg_dead_p (2, operands[0]))"
5929 [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
5930{
5931 operands[4]
5932 = replace_equiv_address (operands[1],
5933 gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
5934 const0_rtx));
5935})
5936
bc45ade3
SC
5937;; -------------------------------------------------------------------------
5938;; Sign extension instructions
5939;; -------------------------------------------------------------------------
5940
ffae286a
JW
5941;; ??? This should be a define expand.
5942;; ??? Or perhaps it should be dropped?
5943
fa5322fa
AO
5944;; convert_move generates good code for SH[1-4].
5945(define_insn "extendsidi2"
73a4d10b
R
5946 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
5947 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
fa5322fa
AO
5948 "TARGET_SHMEDIA"
5949 "@
5950 add.l %1, r63, %0
73a4d10b
R
5951 ld%M1.l %m1, %0
5952 fmov.sl %1, %0"
5953 [(set_attr "type" "arith_media,load_media,fpconv_media")
5954 (set (attr "highpart")
68ed2b9c 5955 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
5956 (const_string "user")]
5957 (const_string "extend")))])
fa5322fa
AO
5958
5959(define_insn "extendhidi2"
5960 [(set (match_operand:DI 0 "register_operand" "=r,r")
b6d33983 5961 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
fa5322fa
AO
5962 "TARGET_SHMEDIA"
5963 "@
5964 #
b6d33983 5965 ld%M1.w %m1, %0"
73a4d10b
R
5966 [(set_attr "type" "*,load_media")
5967 (set (attr "highpart")
68ed2b9c 5968 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
5969 (const_string "user")]
5970 (const_string "ignore")))])
fa5322fa
AO
5971
5972(define_split
e69d1422
R
5973 [(set (match_operand:DI 0 "register_operand" "")
5974 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
fa5322fa
AO
5975 "TARGET_SHMEDIA && reload_completed"
5976 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
b6d33983 5977 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
b6d33983
R
5978{
5979 if (GET_CODE (operands[1]) == TRUNCATE)
5980 operands[1] = XEXP (operands[1], 0);
d9241861 5981})
fa5322fa
AO
5982
5983(define_insn "extendqidi2"
5984 [(set (match_operand:DI 0 "register_operand" "=r,r")
b6d33983 5985 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
fa5322fa
AO
5986 "TARGET_SHMEDIA"
5987 "@
5988 #
b6d33983 5989 ld%M1.b %m1, %0"
73a4d10b
R
5990 [(set_attr "type" "*,load_media")
5991 (set (attr "highpart")
68ed2b9c 5992 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
5993 (const_string "user")]
5994 (const_string "ignore")))])
fa5322fa
AO
5995
5996(define_split
e69d1422
R
5997 [(set (match_operand:DI 0 "register_operand" "")
5998 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
fa5322fa
AO
5999 "TARGET_SHMEDIA && reload_completed"
6000 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
b6d33983 6001 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
b6d33983
R
6002{
6003 if (GET_CODE (operands[1]) == TRUNCATE)
6004 operands[1] = XEXP (operands[1], 0);
d9241861 6005})
b6d33983 6006
7fa4bf9b
OE
6007(define_expand "extend<mode>si2"
6008 [(set (match_operand:SI 0 "arith_reg_dest")
6009 (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
bc45ade3 6010
b6d33983
R
6011(define_insn "*extendhisi2_media"
6012 [(set (match_operand:SI 0 "register_operand" "=r,r")
6013 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6014 "TARGET_SHMEDIA"
6015 "@
6016 #
6017 ld%M1.w %m1, %0"
73a4d10b
R
6018 [(set_attr "type" "arith_media,load_media")
6019 (set (attr "highpart")
68ed2b9c 6020 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
6021 (const_string "user")]
6022 (const_string "ignore")))])
b6d33983
R
6023
6024(define_split
e69d1422
R
6025 [(set (match_operand:SI 0 "register_operand" "")
6026 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
b6d33983 6027 "TARGET_SHMEDIA && reload_completed"
73a4d10b 6028 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
b6d33983 6029 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
b6d33983 6030{
73a4d10b
R
6031 rtx op1 = operands[1];
6032 if (GET_CODE (op1) == TRUNCATE)
6033 op1 = XEXP (op1, 0);
6034 operands[2]
6035 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6036 subreg_lowpart_offset (SImode, GET_MODE (op1)));
d9241861 6037})
b6d33983 6038
26943929 6039(define_insn_and_split "*extend<mode>si2_compact_reg"
ef812306 6040 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7fa4bf9b 6041 (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
fa5322fa 6042 "TARGET_SH1"
7fa4bf9b 6043 "exts.<bw> %1,%0"
26943929
OE
6044 "&& can_create_pseudo_p ()"
6045 [(set (match_dup 0) (match_dup 2))]
6046{
6047 /* Sometimes combine fails to combine a T bit or negated T bit store to a
6048 reg with a following sign extension. In the split pass after combine,
6049 try to figure the extended reg was set. If it originated from the T
6050 bit we can replace the sign extension with a reg move, which will be
6051 eliminated. */
6052 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6053 if (operands[2] == NULL_RTX)
6054 FAIL;
6055}
ef812306 6056 [(set_attr "type" "arith")])
8c2a3f3b 6057
344332e8
OE
6058;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6059;; See movqi insns.
7fa4bf9b 6060(define_insn "*extend<mode>si2_compact_mem_disp"
8c2a3f3b
OE
6061 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6062 (sign_extend:SI
7fa4bf9b
OE
6063 (mem:QIHI
6064 (plus:SI
6065 (match_operand:SI 1 "arith_reg_operand" "%r,r")
6066 (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
8c2a3f3b 6067 "TARGET_SH1 && ! TARGET_SH2A
7fa4bf9b 6068 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
8c2a3f3b 6069 "@
7fa4bf9b
OE
6070 mov.<bw> @(%O2,%1),%0
6071 mov.<bw> @%1,%0"
8c2a3f3b
OE
6072 [(set_attr "type" "load")])
6073
7fa4bf9b 6074(define_insn "*extend<mode>si2_compact_mem_disp"
344332e8
OE
6075 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6076 (sign_extend:SI
7fa4bf9b
OE
6077 (mem:QIHI
6078 (plus:SI
6079 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6080 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
ee86a05f 6081 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
344332e8 6082 "@
7fa4bf9b
OE
6083 mov.<bw> @(%O2,%1),%0
6084 mov.<bw> @%1,%0
6085 mov.<bw> @(%O2,%1),%0"
8c2a3f3b
OE
6086 [(set_attr "type" "load")
6087 (set_attr "length" "2,2,4")])
6088
6089;; The *_snd patterns will take care of other QImode/HImode addressing
6090;; modes than displacement addressing. They must be defined _after_ the
6091;; displacement addressing patterns. Otherwise the displacement addressing
6092;; patterns will not be picked.
7fa4bf9b 6093(define_insn "*extend<mode>si2_compact_snd"
8c2a3f3b 6094 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7fa4bf9b
OE
6095 (sign_extend:SI
6096 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
8c2a3f3b 6097 "TARGET_SH1"
7fa4bf9b 6098 "mov.<bw> %1,%0"
8c2a3f3b
OE
6099 [(set_attr "type" "load")])
6100
b6d33983
R
6101(define_insn "*extendqisi2_media"
6102 [(set (match_operand:SI 0 "register_operand" "=r,r")
6103 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6104 "TARGET_SHMEDIA"
6105 "@
6106 #
6107 ld%M1.b %m1, %0"
73a4d10b
R
6108 [(set_attr "type" "arith_media,load_media")
6109 (set (attr "highpart")
68ed2b9c 6110 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
6111 (const_string "user")]
6112 (const_string "ignore")))])
b6d33983
R
6113
6114(define_split
e69d1422
R
6115 [(set (match_operand:SI 0 "register_operand" "")
6116 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
b6d33983 6117 "TARGET_SHMEDIA && reload_completed"
73a4d10b 6118 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
b6d33983 6119 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
b6d33983 6120{
73a4d10b
R
6121 rtx op1 = operands[1];
6122 if (GET_CODE (op1) == TRUNCATE)
6123 op1 = XEXP (op1, 0);
6124 operands[2]
6125 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6126 subreg_lowpart_offset (SImode, GET_MODE (op1)));
d9241861 6127})
b6d33983 6128
344332e8
OE
6129(define_expand "extendqihi2"
6130 [(set (match_operand:HI 0 "arith_reg_dest" "")
6131 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))]
6132 ""
6133 "")
6134
6135(define_insn "*extendqihi2_compact_reg"
6136 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6137 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
fa5322fa 6138 "TARGET_SH1"
344332e8
OE
6139 "exts.b %1,%0"
6140 [(set_attr "type" "arith")])
fae15c93 6141
d9241861
OE
6142;; It would seem useful to combine the truncXi patterns into the movXi
6143;; patterns, but unary operators are ignored when matching constraints,
6144;; so we need separate patterns.
b6d33983 6145(define_insn "truncdisi2"
0ac78517 6146 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
b6d33983
R
6147 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6148 "TARGET_SHMEDIA"
6149 "@
6150 add.l %1, r63, %0
6151 st%M0.l %m0, %1
6152 fst%M0.s %m0, %T1
6153 fmov.ls %1, %0
6154 fmov.sl %T1, %0
6155 fmov.s %T1, %0"
73a4d10b
R
6156 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
6157 (set (attr "highpart")
68ed2b9c 6158 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
6159 (const_string "user")]
6160 (const_string "extend")))])
b6d33983
R
6161
6162(define_insn "truncdihi2"
0ac78517 6163 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
b6d33983
R
6164 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6165 "TARGET_SHMEDIA"
35ed5a70
OE
6166{
6167 static const char* alt[] =
6168 {
6169 "shlli %1,48,%0" "\n"
6170 " shlri %0,48,%0",
6171
6172 "st%M0.w %m0, %1"
6173 };
6174 return alt[which_alternative];
6175}
b6d33983 6176 [(set_attr "type" "arith_media,store_media")
73a4d10b
R
6177 (set_attr "length" "8,4")
6178 (set (attr "highpart")
68ed2b9c 6179 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
6180 (const_string "user")]
6181 (const_string "extend")))])
b6d33983 6182
59324685
R
6183; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6184; Because we use zero extension, we can't provide signed QImode compares
9f5ed61a 6185; using a simple compare or conditional branch insn.
b6d33983
R
6186(define_insn "truncdiqi2"
6187 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6188 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6189 "TARGET_SHMEDIA"
6190 "@
40779a72 6191 andi %1, 255, %0
b6d33983 6192 st%M0.b %m0, %1"
73a4d10b
R
6193 [(set_attr "type" "arith_media,store")
6194 (set (attr "highpart")
68ed2b9c 6195 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
6196 (const_string "user")]
6197 (const_string "extend")))])
bc45ade3
SC
6198;; -------------------------------------------------------------------------
6199;; Move instructions
6200;; -------------------------------------------------------------------------
6201
0d7e008e 6202;; define push and pop so it is easy for sh.c
fa5322fa
AO
6203;; We can't use push and pop on SHcompact because the stack must always
6204;; be 8-byte aligned.
b9654711 6205
225e4f43 6206(define_expand "push"
4773afa4 6207 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
ffae286a 6208 (match_operand:SI 0 "register_operand" "r,l,x"))]
fa5322fa 6209 "TARGET_SH1 && ! TARGET_SH5"
225e4f43 6210 "")
b9654711 6211
225e4f43 6212(define_expand "pop"
51bd623f 6213 [(set (match_operand:SI 0 "register_operand" "=r,l,x")
4773afa4 6214 (mem:SI (post_inc:SI (reg:SI SP_REG))))]
fa5322fa 6215 "TARGET_SH1 && ! TARGET_SH5"
225e4f43
R
6216 "")
6217
6218(define_expand "push_e"
4773afa4 6219 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
225e4f43 6220 (match_operand:SF 0 "" ""))
4773afa4 6221 (use (reg:PSI FPSCR_REG))
225e4f43 6222 (clobber (scratch:SI))])]
fa5322fa 6223 "TARGET_SH1 && ! TARGET_SH5"
225e4f43 6224 "")
b9654711 6225
225e4f43 6226(define_insn "push_fpul"
4773afa4 6227 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
3a8699c7 6228 "TARGET_SH2E && ! TARGET_SH5"
225e4f43 6229 "sts.l fpul,@-r15"
78d310c2 6230 [(set_attr "type" "fstore")
c49439f1 6231 (set_attr "late_fp_use" "yes")
45348d9e
JW
6232 (set_attr "hit_stack" "yes")])
6233
225e4f43
R
6234;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6235;; so use that.
6236(define_expand "push_4"
4773afa4
AO
6237 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6238 (match_operand:DF 0 "" ""))
6239 (use (reg:PSI FPSCR_REG))
225e4f43 6240 (clobber (scratch:SI))])]
fa5322fa 6241 "TARGET_SH1 && ! TARGET_SH5"
225e4f43
R
6242 "")
6243
6244(define_expand "pop_e"
6245 [(parallel [(set (match_operand:SF 0 "" "")
4773afa4
AO
6246 (mem:SF (post_inc:SI (reg:SI SP_REG))))
6247 (use (reg:PSI FPSCR_REG))
225e4f43 6248 (clobber (scratch:SI))])]
fa5322fa 6249 "TARGET_SH1 && ! TARGET_SH5"
225e4f43
R
6250 "")
6251
6252(define_insn "pop_fpul"
4773afa4 6253 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
3a8699c7 6254 "TARGET_SH2E && ! TARGET_SH5"
225e4f43 6255 "lds.l @r15+,fpul"
45348d9e
JW
6256 [(set_attr "type" "load")
6257 (set_attr "hit_stack" "yes")])
6258
225e4f43
R
6259(define_expand "pop_4"
6260 [(parallel [(set (match_operand:DF 0 "" "")
4773afa4
AO
6261 (mem:DF (post_inc:SI (reg:SI SP_REG))))
6262 (use (reg:PSI FPSCR_REG))
225e4f43 6263 (clobber (scratch:SI))])]
fa5322fa 6264 "TARGET_SH1 && ! TARGET_SH5"
225e4f43
R
6265 "")
6266
7144b2d8
DD
6267(define_expand "push_fpscr"
6268 [(const_int 0)]
603ff6b5 6269 "TARGET_SH2E"
7144b2d8 6270{
57d38024 6271 rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
c0d4e710 6272 gen_rtx_PRE_DEC (Pmode,
7144b2d8
DD
6273 stack_pointer_rtx)),
6274 get_fpscr_rtx ()));
b757d36f 6275 add_reg_note (insn, REG_INC, stack_pointer_rtx);
7144b2d8 6276 DONE;
d9241861 6277})
7144b2d8
DD
6278
6279(define_expand "pop_fpscr"
6280 [(const_int 0)]
603ff6b5 6281 "TARGET_SH2E"
7144b2d8
DD
6282{
6283 rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
57d38024 6284 gen_frame_mem (PSImode,
c0d4e710 6285 gen_rtx_POST_INC (Pmode,
7144b2d8 6286 stack_pointer_rtx))));
b757d36f 6287 add_reg_note (insn, REG_INC, stack_pointer_rtx);
7144b2d8 6288 DONE;
d9241861 6289})
7144b2d8 6290
55f7c481
OE
6291;; The clrt and sett patterns can happen as the result of optimization and
6292;; insn expansion.
6293;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6294;; In this case they might not disappear completely, because the T reg is
6295;; a fixed hard reg.
6296;; When DImode operations that use the T reg as carry/borrow are split into
6297;; individual SImode operations, the T reg is usually cleared before the
6298;; first SImode insn.
ffae286a 6299
0d7e008e 6300(define_insn "clrt"
4773afa4 6301 [(set (reg:SI T_REG) (const_int 0))]
fa5322fa 6302 "TARGET_SH1"
eb11dba2
OE
6303 "clrt"
6304 [(set_attr "type" "mt_group")])
bc45ade3 6305
e3391510 6306(define_insn "sett"
4773afa4 6307 [(set (reg:SI T_REG) (const_int 1))]
fa5322fa 6308 "TARGET_SH1"
eb11dba2
OE
6309 "sett"
6310 [(set_attr "type" "mt_group")])
974f90ba
OE
6311
6312;; Use the combine pass to transform sequences such as
6313;; mov r5,r0
6314;; add #1,r0
6315;; shll2 r0
6316;; mov.l @(r0,r4),r0
6317;; into
6318;; shll2 r5
6319;; add r4,r5
6320;; mov.l @(4,r5),r0
6321;;
6322;; See also PR 39423.
9839afaf
OE
6323;; Notice that these patterns have a T_REG clobber, because the shift
6324;; sequence that will be split out might clobber the T_REG. Ideally, the
6325;; clobber would be added conditionally, depending on the result of
6326;; sh_ashlsi_clobbers_t_reg_p. When splitting out the shifts we must go
6327;; through the ashlsi3 expander in order to get the right shift insn --
6328;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
974f90ba 6329;; FIXME: Combine never tries this kind of patterns for DImode.
7fa4bf9b 6330(define_insn_and_split "*movsi_index_disp_load"
974f90ba 6331 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
9839afaf
OE
6332 (match_operand:SI 1 "mem_index_disp_operand" "m"))
6333 (clobber (reg:SI T_REG))]
b67b3838 6334 "TARGET_SH1"
974f90ba
OE
6335 "#"
6336 "&& can_create_pseudo_p ()"
9839afaf 6337 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
b67b3838 6338 (set (match_dup 0) (match_dup 7))]
974f90ba 6339{
b67b3838
OE
6340 rtx mem = operands[1];
6341 rtx plus0_rtx = XEXP (mem, 0);
6342 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6343 rtx mult_rtx = XEXP (plus1_rtx, 0);
6344
6345 operands[1] = XEXP (mult_rtx, 0);
6346 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6347 operands[3] = XEXP (plus1_rtx, 1);
6348 operands[4] = XEXP (plus0_rtx, 1);
974f90ba
OE
6349 operands[5] = gen_reg_rtx (SImode);
6350 operands[6] = gen_reg_rtx (SImode);
b67b3838
OE
6351 operands[7] =
6352 replace_equiv_address (mem,
6353 gen_rtx_PLUS (SImode, operands[6], operands[4]));
9839afaf
OE
6354
6355 emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
974f90ba
OE
6356})
6357
7fa4bf9b 6358(define_insn_and_split "*movhi_index_disp_load"
b67b3838 6359 [(set (match_operand:SI 0 "arith_reg_dest")
7fa4bf9b 6360 (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
9839afaf 6361 (clobber (reg:SI T_REG))]
b67b3838 6362 "TARGET_SH1"
9839afaf 6363 "#"
082ea1dc
OE
6364 "&& can_create_pseudo_p ()"
6365 [(const_int 0)]
974f90ba 6366{
082ea1dc
OE
6367 rtx mem = operands[1];
6368 rtx plus0_rtx = XEXP (mem, 0);
6369 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6370 rtx mult_rtx = XEXP (plus1_rtx, 0);
6371
6372 rtx op_1 = XEXP (mult_rtx, 0);
6373 rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6374 rtx op_3 = XEXP (plus1_rtx, 1);
6375 rtx op_4 = XEXP (plus0_rtx, 1);
6376 rtx op_5 = gen_reg_rtx (SImode);
6377 rtx op_6 = gen_reg_rtx (SImode);
6378 rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6379
6380 emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6381 emit_insn (gen_addsi3 (op_6, op_5, op_3));
6382
7fa4bf9b 6383 if (<CODE> == SIGN_EXTEND)
082ea1dc
OE
6384 {
6385 emit_insn (gen_extendhisi2 (operands[0], op_7));
7fa4bf9b 6386 DONE;
082ea1dc 6387 }
7fa4bf9b
OE
6388 else if (<CODE> == ZERO_EXTEND)
6389 {
6390 /* On SH2A the movu.w insn can be used for zero extending loads. */
6391 if (TARGET_SH2A)
6392 emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
6393 else
6394 {
6395 emit_insn (gen_extendhisi2 (operands[0], op_7));
6396 emit_insn (gen_zero_extendhisi2 (operands[0],
6397 gen_lowpart (HImode, operands[0])));
6398 }
6399 DONE;
6400 }
6401 else
6402 FAIL;
974f90ba
OE
6403})
6404
7fa4bf9b
OE
6405(define_insn_and_split "*mov<mode>_index_disp_store"
6406 [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
6407 (match_operand:HISI 1 "arith_reg_operand" "r"))
9839afaf 6408 (clobber (reg:SI T_REG))]
b67b3838 6409 "TARGET_SH1"
974f90ba
OE
6410 "#"
6411 "&& can_create_pseudo_p ()"
9839afaf 6412 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
b67b3838 6413 (set (match_dup 7) (match_dup 1))]
974f90ba 6414{
b67b3838
OE
6415 rtx mem = operands[0];
6416 rtx plus0_rtx = XEXP (mem, 0);
6417 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6418 rtx mult_rtx = XEXP (plus1_rtx, 0);
6419
6420 operands[0] = XEXP (mult_rtx, 0);
6421 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6422 operands[3] = XEXP (plus1_rtx, 1);
6423 operands[4] = XEXP (plus0_rtx, 1);
974f90ba
OE
6424 operands[5] = gen_reg_rtx (SImode);
6425 operands[6] = gen_reg_rtx (SImode);
b67b3838
OE
6426 operands[7] =
6427 replace_equiv_address (mem,
6428 gen_rtx_PLUS (SImode, operands[6], operands[4]));
9839afaf
OE
6429
6430 emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
974f90ba
OE
6431})
6432
3ca0a524 6433;; t/r must come after r/r, lest reload will try to reload stuff like
4773afa4 6434;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
e11cddec 6435;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
0d7e008e 6436(define_insn "movsi_i"
735cb76e 6437 [(set (match_operand:SI 0 "general_movdst_operand"
ef812306 6438 "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
735cb76e 6439 (match_operand:SI 1 "general_movsrc_operand"
ef812306 6440 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
fa5322fa 6441 "TARGET_SH1
3a8699c7 6442 && ! TARGET_SH2E
157371cf 6443 && ! TARGET_SH2A
1245df60
R
6444 && (register_operand (operands[0], SImode)
6445 || register_operand (operands[1], SImode))"
8e87e161
SC
6446 "@
6447 mov.l %1,%0
6448 mov %1,%0
78d310c2 6449 mov %1,%0
8e87e161
SC
6450 mov.l %1,%0
6451 sts %1,%0
99e87c10 6452 sts %1,%0
8e87e161
SC
6453 mov.l %1,%0
6454 sts.l %1,%0
1245df60 6455 sts.l %1,%0
8e87e161 6456 lds %1,%0
99e87c10 6457 lds %1,%0
8e87e161 6458 lds.l %1,%0
1245df60 6459 lds.l %1,%0
51bd623f 6460 fake %1,%0"
ef812306
OE
6461 [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,pcload_si")
6462 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
07a45e5c 6463
1245df60 6464;; t/r must come after r/r, lest reload will try to reload stuff like
e11cddec 6465;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
45348d9e
JW
6466;; ??? This allows moves from macl to fpul to be recognized, but these moves
6467;; will require a reload.
ec555f32
R
6468;; ??? We can't include f/f because we need the proper FPSCR setting when
6469;; TARGET_FMOVD is in effect, and mode switching is done before reload.
45348d9e 6470(define_insn "movsi_ie"
735cb76e 6471 [(set (match_operand:SI 0 "general_movdst_operand"
ef812306 6472 "=r,r,r,r,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
735cb76e 6473 (match_operand:SI 1 "general_movsrc_operand"
ef812306 6474 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
157371cf 6475 "(TARGET_SH2E || TARGET_SH2A)
45348d9e
JW
6476 && (register_operand (operands[0], SImode)
6477 || register_operand (operands[1], SImode))"
6478 "@
45348d9e
JW
6479 mov.l %1,%0
6480 mov %1,%0
78d310c2 6481 mov %1,%0
157371cf 6482 movi20 %1,%0
e990551a 6483 movi20s %1,%0
45348d9e
JW
6484 mov.l %1,%0
6485 sts %1,%0
99e87c10 6486 sts %1,%0
45348d9e
JW
6487 mov.l %1,%0
6488 sts.l %1,%0
1245df60 6489 sts.l %1,%0
45348d9e 6490 lds %1,%0
99e87c10 6491 lds %1,%0
45348d9e 6492 lds.l %1,%0
1245df60 6493 lds.l %1,%0
225e4f43 6494 lds.l %1,%0
a92facbb 6495 sts.l %1,%0
45348d9e
JW
6496 fake %1,%0
6497 lds %1,%0
1245df60 6498 sts %1,%0
ec555f32
R
6499 fsts fpul,%0
6500 flds %1,fpul
6501 fmov %1,%0
1245df60 6502 ! move optimized away"
ef812306
OE
6503 [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
6504 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
6b2eeb54
KK
6505 (set_attr_alternative "length"
6506 [(const_int 2)
6507 (const_int 2)
6508 (const_int 2)
6509 (const_int 4)
e990551a 6510 (const_int 4)
6b2eeb54 6511 (if_then_else
68ed2b9c 6512 (match_test "TARGET_SH2A")
6b2eeb54
KK
6513 (const_int 4) (const_int 2))
6514 (const_int 2)
6515 (const_int 2)
6b2eeb54 6516 (if_then_else
68ed2b9c 6517 (match_test "TARGET_SH2A")
6b2eeb54
KK
6518 (const_int 4) (const_int 2))
6519 (const_int 2)
6520 (const_int 2)
6521 (const_int 2)
6522 (const_int 2)
6523 (const_int 2)
6524 (const_int 2)
6525 (const_int 2)
6526 (const_int 2)
6527 (const_int 2)
6528 (const_int 2)
6529 (const_int 2)
6530 (const_int 2)
6531 (const_int 2)
6532 (const_int 2)
6533 (const_int 0)])])
1245df60
R
6534
6535(define_insn "movsi_i_lowpart"
ef812306
OE
6536 [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
6537 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
fa5322fa
AO
6538 "TARGET_SH1
6539 && (register_operand (operands[0], SImode)
6540 || register_operand (operands[1], SImode))"
1245df60
R
6541 "@
6542 mov.l %1,%0
6543 mov %1,%0
78d310c2 6544 mov %1,%0
1245df60
R
6545 mov.l %1,%0
6546 sts %1,%0
99e87c10 6547 sts %1,%0
1245df60
R
6548 mov.l %1,%0
6549 fake %1,%0"
ef812306 6550 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
a6f463a0 6551
7d73a2ba 6552(define_insn_and_split "load_ra"
b869f904 6553 [(set (match_operand:SI 0 "general_movdst_operand" "")
73a4d10b 6554 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
dce20bbc 6555 "TARGET_SH1"
7d73a2ba 6556 "#"
4586b4ca 6557 "&& ! currently_expanding_to_rtl"
b869f904 6558 [(set (match_dup 0) (match_dup 1))]
7d73a2ba 6559{
e3b5732b 6560 if (TARGET_SHCOMPACT && crtl->saves_all_registers)
57d38024 6561 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
d9241861 6562})
b869f904 6563
73a4d10b
R
6564;; The '?'s in the following constraints may not reflect the time taken
6565;; to perform the move. They are there to discourage the use of floating-
6566;; point registers for storing integer values.
fa5322fa 6567(define_insn "*movsi_media"
735cb76e 6568 [(set (match_operand:SI 0 "general_movdst_operand"
73a4d10b 6569 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
735cb76e 6570 (match_operand:SI 1 "general_movsrc_operand"
42201282 6571 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
fa5322fa
AO
6572 "TARGET_SHMEDIA_FPU
6573 && (register_operand (operands[0], SImode)
73a4d10b
R
6574 || sh_register_operand (operands[1], SImode)
6575 || GET_CODE (operands[1]) == TRUNCATE)"
fa5322fa
AO
6576 "@
6577 add.l %1, r63, %0
6578 movi %1, %0
6579 #
6580 ld%M1.l %m1, %0
d9da94a1 6581 st%M0.l %m0, %N1
fa5322fa
AO
6582 fld%M1.s %m1, %0
6583 fst%M0.s %m0, %1
0ac78517 6584 fmov.ls %N1, %0
fa5322fa
AO
6585 fmov.sl %1, %0
6586 fmov.s %1, %0
6587 ptabs %1, %0
6588 gettr %1, %0
6589 pt %1, %0"
2ad65b0e 6590 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,fpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
73a4d10b
R
6591 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
6592 (set (attr "highpart")
68ed2b9c 6593 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
6594 (const_string "user")]
6595 (const_string "ignore")))])
fa5322fa
AO
6596
6597(define_insn "*movsi_media_nofpu"
735cb76e 6598 [(set (match_operand:SI 0 "general_movdst_operand"
73a4d10b 6599 "=r,r,r,r,m,*b,r,*b")
735cb76e 6600 (match_operand:SI 1 "general_movsrc_operand"
42201282 6601 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
fa5322fa
AO
6602 "TARGET_SHMEDIA
6603 && (register_operand (operands[0], SImode)
73a4d10b
R
6604 || sh_register_operand (operands[1], SImode)
6605 || GET_CODE (operands[1]) == TRUNCATE)"
fa5322fa
AO
6606 "@
6607 add.l %1, r63, %0
6608 movi %1, %0
6609 #
6610 ld%M1.l %m1, %0
d9da94a1 6611 st%M0.l %m0, %N1
fa5322fa
AO
6612 ptabs %1, %0
6613 gettr %1, %0
6614 pt %1, %0"
2ad65b0e 6615 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
73a4d10b
R
6616 (set_attr "length" "4,4,8,4,4,4,4,12")
6617 (set (attr "highpart")
68ed2b9c 6618 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
6619 (const_string "user")]
6620 (const_string "ignore")))])
6621
6622(define_expand "movsi_const"
6623 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
dc3ba671
RS
6624 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6625 (const_int 16)] UNSPEC_EXTRACT_S16)))
73a4d10b
R
6626 (set (match_dup 0)
6627 (ior:SI (ashift:SI (match_dup 0) (const_int 16))
dc3ba671
RS
6628 (const:SI (unspec:SI [(match_dup 1)
6629 (const_int 0)] UNSPEC_EXTRACT_U16))))]
73a4d10b
R
6630 "TARGET_SHMEDIA && reload_completed
6631 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
73a4d10b
R
6632{
6633 if (GET_CODE (operands[1]) == LABEL_REF
6634 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
6635 LABEL_NUSES (XEXP (operands[1], 0)) += 2;
6636 else if (GOTOFF_P (operands[1]))
6637 {
6638 rtx unspec = XEXP (operands[1], 0);
6639
6640 if (! UNSPEC_GOTOFF_P (unspec))
6641 {
6642 unspec = XEXP (unspec, 0);
6643 if (! UNSPEC_GOTOFF_P (unspec))
6644 abort ();
6645 }
6646 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
6647 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
6648 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
6649 }
d9241861 6650})
73a4d10b
R
6651
6652(define_expand "movsi_const_16bit"
6653 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
dc3ba671
RS
6654 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6655 (const_int 0)] UNSPEC_EXTRACT_S16)))]
73a4d10b
R
6656 "TARGET_SHMEDIA && flag_pic && reload_completed
6657 && GET_CODE (operands[1]) == SYMBOL_REF"
6658 "")
fa5322fa
AO
6659
6660(define_split
73a4d10b 6661 [(set (match_operand:SI 0 "arith_reg_dest" "")
e69d1422 6662 (match_operand:SI 1 "immediate_operand" ""))]
fa5322fa
AO
6663 "TARGET_SHMEDIA && reload_completed
6664 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
73a4d10b 6665 [(const_int 0)]
fa5322fa 6666{
73a4d10b
R
6667 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
6668
bd94cb6e 6669 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
73a4d10b
R
6670
6671 DONE;
d9241861 6672})
fa5322fa
AO
6673
6674(define_split
e69d1422
R
6675 [(set (match_operand:SI 0 "register_operand" "")
6676 (match_operand:SI 1 "immediate_operand" ""))]
b6d33983 6677 "TARGET_SHMEDIA && reload_completed
f3536097 6678 && ((CONST_INT_P (operands[1])
32a7ab3d 6679 && ! satisfies_constraint_I16 (operands[1]))
fa5322fa
AO
6680 || GET_CODE (operands[1]) == CONST_DOUBLE)"
6681 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6682
bc45ade3 6683(define_expand "movsi"
0d7e008e
SC
6684 [(set (match_operand:SI 0 "general_movdst_operand" "")
6685 (match_operand:SI 1 "general_movsrc_operand" ""))]
bc45ade3 6686 ""
d9241861 6687{
2ef6611e 6688 prepare_move_operands (operands, SImode);
d9241861 6689})
961c4780 6690
225e4f43
R
6691(define_expand "ic_invalidate_line"
6692 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
4773afa4 6693 (match_dup 1)] UNSPEC_ICACHE)
225e4f43 6694 (clobber (scratch:SI))])]
fa5322fa 6695 "TARGET_HARD_SH4 || TARGET_SH5"
225e4f43 6696{
fa5322fa
AO
6697 if (TARGET_SHMEDIA)
6698 {
6699 emit_insn (gen_ic_invalidate_line_media (operands[0]));
6700 DONE;
6701 }
6702 else if (TARGET_SHCOMPACT)
6703 {
d9241861 6704 operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
fa5322fa
AO
6705 operands[1] = force_reg (Pmode, operands[1]);
6706 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
6707 DONE;
6708 }
dc557046 6709 else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
312209c6
AO
6710 {
6711 emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
6712 DONE;
6713 }
225e4f43 6714 operands[0] = force_reg (Pmode, operands[0]);
90e65b70
AO
6715 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
6716 Pmode)));
d9241861 6717})
225e4f43
R
6718
6719;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing
0aa54da2
R
6720;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
6721;; the requirement *1*00 for associative address writes. The alignment of
225e4f43
R
6722;; %0 implies that its least significant bit is cleared,
6723;; thus we clear the V bit of a matching entry if there is one.
6724(define_insn "ic_invalidate_line_i"
0aa54da2 6725 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
4773afa4
AO
6726 (match_operand:SI 1 "register_operand" "r")]
6727 UNSPEC_ICACHE)
0aa54da2 6728 (clobber (match_scratch:SI 2 "=&r"))]
225e4f43 6729 "TARGET_HARD_SH4"
35ed5a70
OE
6730{
6731 return "ocbwb @%0" "\n"
6732 " extu.w %0,%2" "\n"
6733 " or %1,%2" "\n"
6734 " mov.l %0,@%2";
6735}
fae15c93 6736 [(set_attr "length" "8")
c49439f1 6737 (set_attr "type" "cwb")])
225e4f43 6738
312209c6
AO
6739(define_insn "ic_invalidate_line_sh4a"
6740 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
6741 UNSPEC_ICACHE)]
dc557046 6742 "TARGET_SH4A_ARCH || TARGET_SH4_300"
35ed5a70
OE
6743{
6744 return "ocbwb @%0" "\n"
6745 " synco" "\n"
6746 " icbi @%0";
6747}
6748 [(set_attr "length" "16") ;; FIXME: Why 16 and not 6? Looks like typo.
312209c6
AO
6749 (set_attr "type" "cwb")])
6750
ca903bba
R
6751;; ??? could make arg 0 an offsettable memory operand to allow to save
6752;; an add in the code that calculates the address.
fa5322fa 6753(define_insn "ic_invalidate_line_media"
73a4d10b 6754 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
fa5322fa
AO
6755 UNSPEC_ICACHE)]
6756 "TARGET_SHMEDIA"
35ed5a70
OE
6757{
6758 return "ocbwb %0,0" "\n"
6759 " synco" "\n"
6760 " icbi %0,0" "\n"
6761 " synci";
6762}
b6d33983
R
6763 [(set_attr "length" "16")
6764 (set_attr "type" "invalidate_line_media")])
fa5322fa
AO
6765
6766(define_insn "ic_invalidate_line_compact"
6767 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6768 (match_operand:SI 1 "register_operand" "r")]
6769 UNSPEC_ICACHE)
6770 (clobber (reg:SI PR_REG))]
6771 "TARGET_SHCOMPACT"
6772 "jsr @%1%#"
6773 [(set_attr "type" "sfunc")
6774 (set_attr "needs_delay_slot" "yes")])
6775
ca903bba
R
6776(define_expand "initialize_trampoline"
6777 [(match_operand:SI 0 "" "")
6778 (match_operand:SI 1 "" "")
6779 (match_operand:SI 2 "" "")]
6780 "TARGET_SHCOMPACT"
ca903bba
R
6781{
6782 rtx sfun, tramp;
6783
e300c78c 6784 tramp = force_reg (Pmode, operands[0]);
d9241861 6785 sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
73a4d10b 6786 SFUNC_STATIC));
ca903bba
R
6787 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
6788 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
6789
6790 emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
6791 DONE;
d9241861 6792})
ca903bba
R
6793
6794(define_insn "initialize_trampoline_compact"
6795 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6796 (match_operand:SI 1 "register_operand" "r")
6797 (reg:SI R2_REG) (reg:SI R3_REG)]
6798 UNSPEC_INIT_TRAMP)
6799
6800 (clobber (reg:SI PR_REG))]
6801 "TARGET_SHCOMPACT"
6802 "jsr @%1%#"
6803 [(set_attr "type" "sfunc")
6804 (set_attr "needs_delay_slot" "yes")])
6805
8c2a3f3b
OE
6806(define_expand "movhi"
6807 [(set (match_operand:HI 0 "general_movdst_operand" "")
6808 (match_operand:HI 1 "general_movsrc_operand" ""))]
6809 ""
6810{
6811 prepare_move_operands (operands, HImode);
6812})
6813
344332e8
OE
6814(define_expand "movqi"
6815 [(set (match_operand:QI 0 "general_operand" "")
6816 (match_operand:QI 1 "general_operand" ""))]
6817 ""
d9241861 6818{
2ef6611e 6819 prepare_move_operands (operands, QImode);
d9241861 6820})
344332e8
OE
6821
6822;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be
6823;; selected to copy QImode regs. If one of them happens to be allocated
6824;; on the stack, reload will stick to movqi insn and generate wrong
6825;; displacement addressing because of the generic m alternatives.
073a8998 6826;; With the movqi_reg_reg being specified before movqi it will be initially
344332e8
OE
6827;; picked to load/store regs. If the regs regs are on the stack reload will
6828;; try other insns and not stick to movqi_reg_reg.
8c2a3f3b 6829;; The same applies to the movhi variants.
26943929
OE
6830;;
6831;; Notice, that T bit is not allowed as a mov src operand here. This is to
6832;; avoid things like (set (reg:QI) (subreg:QI (reg:SI T_REG) 0)), which
6833;; introduces zero extensions after T bit stores and redundant reg copies.
6834;;
6835;; FIXME: We can't use 'arith_reg_operand' (which disallows T_REG) as a
6836;; predicate for the mov src operand because reload will have trouble
6837;; reloading MAC subregs otherwise. For that probably special patterns
6838;; would be required.
7fa4bf9b
OE
6839(define_insn "*mov<mode>_reg_reg"
6840 [(set (match_operand:QIHI 0 "arith_reg_dest" "=r")
6841 (match_operand:QIHI 1 "register_operand" "r"))]
26943929 6842 "TARGET_SH1 && !t_reg_operand (operands[1], VOIDmode)"
ef812306
OE
6843 "mov %1,%0"
6844 [(set_attr "type" "move")])
8c2a3f3b 6845
344332e8
OE
6846;; FIXME: The non-SH2A and SH2A variants should be combined by adding
6847;; "enabled" attribute as it is done in other targets.
7fa4bf9b
OE
6848(define_insn "*mov<mode>_store_mem_disp04"
6849 [(set (mem:QIHI
6850 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
6851 (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
6852 (match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
6853 "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
344332e8 6854 "@
7fa4bf9b
OE
6855 mov.<bw> %2,@(%O1,%0)
6856 mov.<bw> %2,@%0"
344332e8
OE
6857 [(set_attr "type" "store")])
6858
7fa4bf9b
OE
6859(define_insn "*mov<mode>_store_mem_disp12"
6860 [(set (mem:QIHI
6861 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
6862 (match_operand:SI 1 "const_int_operand" "<disp12>")))
6863 (match_operand:QIHI 2 "arith_reg_operand" "r"))]
6864 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
6865 "mov.<bw> %2,@(%O1,%0)"
8c2a3f3b
OE
6866 [(set_attr "type" "store")
6867 (set_attr "length" "4")])
6868
7fa4bf9b
OE
6869(define_insn "*mov<mode>_load_mem_disp04"
6870 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
6871 (mem:QIHI
6872 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
6873 (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
8c2a3f3b 6874 "TARGET_SH1 && ! TARGET_SH2A
7fa4bf9b 6875 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
344332e8 6876 "@
7fa4bf9b
OE
6877 mov.<bw> @(%O2,%1),%0
6878 mov.<bw> @%1,%0"
344332e8
OE
6879 [(set_attr "type" "load")])
6880
7fa4bf9b
OE
6881(define_insn "*mov<mode>_load_mem_disp12"
6882 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
6883 (mem:QIHI
6884 (plus:SI
6885 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6886 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
6887 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
8c2a3f3b 6888 "@
7fa4bf9b
OE
6889 mov.<bw> @(%O2,%1),%0
6890 mov.<bw> @%1,%0
6891 mov.<bw> @(%O2,%1),%0"
8c2a3f3b
OE
6892 [(set_attr "type" "load")
6893 (set_attr "length" "2,2,4")])
6894
344332e8
OE
6895;; The m constraints basically allow any kind of addresses to be used with any
6896;; source/target register as the other operand. This is not true for
6897;; displacement addressing modes on anything but SH2A. That's why the
6898;; specialized load/store insns are specified above.
6899(define_insn "*movqi"
6900 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,l")
6901 (match_operand:QI 1 "general_movsrc_operand" "i,m,r,l,r"))]
fa5322fa
AO
6902 "TARGET_SH1
6903 && (arith_reg_operand (operands[0], QImode)
6904 || arith_reg_operand (operands[1], QImode))"
bc45ade3
SC
6905 "@
6906 mov %1,%0
0d7e008e
SC
6907 mov.b %1,%0
6908 mov.b %1,%0
bc45ade3 6909 sts %1,%0
0d7e008e 6910 lds %1,%0"
344332e8 6911 [(set_attr "type" "movi8,load,store,prget,prset")])
bc45ade3 6912
8c2a3f3b
OE
6913(define_insn "*movhi"
6914 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l")
6915 (match_operand:HI 1 "general_movsrc_operand" "Q,i,m,r,l,r"))]
6916 "TARGET_SH1
6917 && (arith_reg_operand (operands[0], HImode)
6918 || arith_reg_operand (operands[1], HImode))"
6919 "@
6920 mov.w %1,%0
6921 mov %1,%0
6922 mov.w %1,%0
6923 mov.w %1,%0
6924 sts %1,%0
6925 lds %1,%0"
6926 [(set_attr "type" "pcload,movi8,load,store,prget,prset")])
6927
fa5322fa
AO
6928(define_insn "*movqi_media"
6929 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
42201282 6930 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
fa5322fa
AO
6931 "TARGET_SHMEDIA
6932 && (arith_reg_operand (operands[0], QImode)
73a4d10b 6933 || extend_reg_or_0_operand (operands[1], QImode))"
fa5322fa
AO
6934 "@
6935 add.l %1, r63, %0
6936 movi %1, %0
59324685 6937 ld%M1.ub %m1, %0
d9da94a1 6938 st%M0.b %m0, %N1"
73a4d10b
R
6939 [(set_attr "type" "arith_media,arith_media,load_media,store_media")
6940 (set (attr "highpart")
68ed2b9c 6941 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
6942 (const_string "user")]
6943 (const_string "ignore")))])
fa5322fa 6944
b6d33983
R
6945(define_expand "reload_inqi"
6946 [(set (match_operand:SI 2 "" "=&r")
6947 (match_operand:QI 1 "inqhi_operand" ""))
6948 (set (match_operand:QI 0 "arith_reg_operand" "=r")
ea45c4b0 6949 (truncate:QI (match_dup 3)))]
b6d33983 6950 "TARGET_SHMEDIA"
b6d33983
R
6951{
6952 rtx inner = XEXP (operands[1], 0);
6953 int regno = REGNO (inner);
6954
6955 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
6956 operands[1] = gen_rtx_REG (SImode, regno);
6957 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
d9241861 6958})
b6d33983 6959
fa5322fa 6960(define_insn "*movhi_media"
735cb76e 6961 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
42201282 6962 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
fa5322fa
AO
6963 "TARGET_SHMEDIA
6964 && (arith_reg_operand (operands[0], HImode)
d9da94a1 6965 || arith_reg_or_0_operand (operands[1], HImode))"
fa5322fa
AO
6966 "@
6967 add.l %1, r63, %0
6968 movi %1, %0
6969 #
6970 ld%M1.w %m1, %0
d9da94a1 6971 st%M0.w %m0, %N1"
73a4d10b
R
6972 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
6973 (set (attr "highpart")
68ed2b9c 6974 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
6975 (const_string "user")]
6976 (const_string "ignore")))])
fa5322fa
AO
6977
6978(define_split
e69d1422
R
6979 [(set (match_operand:HI 0 "register_operand" "")
6980 (match_operand:HI 1 "immediate_operand" ""))]
b6d33983 6981 "TARGET_SHMEDIA && reload_completed
32a7ab3d 6982 && ! satisfies_constraint_I16 (operands[1])"
fa5322fa
AO
6983 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6984
b6d33983
R
6985(define_expand "reload_inhi"
6986 [(set (match_operand:SI 2 "" "=&r")
6987 (match_operand:HI 1 "inqhi_operand" ""))
6988 (set (match_operand:HI 0 "arith_reg_operand" "=r")
6989 (truncate:HI (match_dup 3)))]
6990 "TARGET_SHMEDIA"
b6d33983
R
6991{
6992 rtx inner = XEXP (operands[1], 0);
6993 int regno = REGNO (inner);
6994
6995 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
6996 operands[1] = gen_rtx_REG (SImode, regno);
6997 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
d9241861 6998})
b6d33983 6999
1245df60
R
7000;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
7001;; compiled with -m2 -ml -O3 -funroll-loops
0113c3c0 7002(define_insn "*movdi_i"
1245df60 7003 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
735cb76e 7004 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
fa5322fa
AO
7005 "TARGET_SH1
7006 && (arith_reg_operand (operands[0], DImode)
7007 || arith_reg_operand (operands[1], DImode))"
6b45f126
OE
7008{
7009 return output_movedouble (insn, operands, DImode);
7010}
22e1ebf1 7011 [(set_attr "length" "4")
1245df60 7012 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
bc45ade3 7013
d0aae509 7014;; If the output is a register and the input is memory or a register, we have
52702ae1 7015;; to be careful and see which word needs to be loaded first.
b9b7c1c9 7016
8e87e161
SC
7017(define_split
7018 [(set (match_operand:DI 0 "general_movdst_operand" "")
7019 (match_operand:DI 1 "general_movsrc_operand" ""))]
fa5322fa 7020 "TARGET_SH1 && reload_completed"
8e87e161
SC
7021 [(set (match_dup 2) (match_dup 3))
7022 (set (match_dup 4) (match_dup 5))]
d0aae509
RK
7023{
7024 int regno;
7025
f3536097 7026 if ((MEM_P (operands[0])
d0aae509 7027 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
f3536097 7028 || (MEM_P (operands[1])
d0aae509
RK
7029 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7030 FAIL;
7031
f5b9e7c9
NS
7032 switch (GET_CODE (operands[0]))
7033 {
7034 case REG:
7035 regno = REGNO (operands[0]);
7036 break;
7037 case SUBREG:
7038 regno = subreg_regno (operands[0]);
7039 break;
7040 case MEM:
7041 regno = -1;
7042 break;
7043 default:
7044 gcc_unreachable ();
7045 }
d0aae509
RK
7046
7047 if (regno == -1
7048 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
8e87e161
SC
7049 {
7050 operands[2] = operand_subword (operands[0], 0, 0, DImode);
7051 operands[3] = operand_subword (operands[1], 0, 0, DImode);
7052 operands[4] = operand_subword (operands[0], 1, 0, DImode);
7053 operands[5] = operand_subword (operands[1], 1, 0, DImode);
7054 }
7055 else
7056 {
7057 operands[2] = operand_subword (operands[0], 1, 0, DImode);
7058 operands[3] = operand_subword (operands[1], 1, 0, DImode);
7059 operands[4] = operand_subword (operands[0], 0, 0, DImode);
7060 operands[5] = operand_subword (operands[1], 0, 0, DImode);
7061 }
7062
7063 if (operands[2] == 0 || operands[3] == 0
7064 || operands[4] == 0 || operands[5] == 0)
7065 FAIL;
d9241861 7066})
961c4780 7067
73a4d10b
R
7068;; The '?'s in the following constraints may not reflect the time taken
7069;; to perform the move. They are there to discourage the use of floating-
7070;; point registers for storing integer values.
fa5322fa 7071(define_insn "*movdi_media"
735cb76e 7072 [(set (match_operand:DI 0 "general_movdst_operand"
73a4d10b 7073 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
735cb76e 7074 (match_operand:DI 1 "general_movsrc_operand"
42201282 7075 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
fa5322fa
AO
7076 "TARGET_SHMEDIA_FPU
7077 && (register_operand (operands[0], DImode)
d9da94a1 7078 || sh_register_operand (operands[1], DImode))"
fa5322fa
AO
7079 "@
7080 add %1, r63, %0
7081 movi %1, %0
7082 #
7083 ld%M1.q %m1, %0
d9da94a1 7084 st%M0.q %m0, %N1
fa5322fa
AO
7085 fld%M1.d %m1, %0
7086 fst%M0.d %m0, %1
0ac78517 7087 fmov.qd %N1, %0
fa5322fa
AO
7088 fmov.dq %1, %0
7089 fmov.d %1, %0
7090 ptabs %1, %0
7091 gettr %1, %0
7092 pt %1, %0"
2ad65b0e 7093 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,dfpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
fa5322fa
AO
7094 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7095
7096(define_insn "*movdi_media_nofpu"
73a4d10b 7097 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
42201282 7098 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
fa5322fa
AO
7099 "TARGET_SHMEDIA
7100 && (register_operand (operands[0], DImode)
d9da94a1 7101 || sh_register_operand (operands[1], DImode))"
fa5322fa
AO
7102 "@
7103 add %1, r63, %0
7104 movi %1, %0
7105 #
7106 ld%M1.q %m1, %0
d9da94a1 7107 st%M0.q %m0, %N1
fa5322fa
AO
7108 ptabs %1, %0
7109 gettr %1, %0
7110 pt %1, %0"
2ad65b0e 7111 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
fa5322fa
AO
7112 (set_attr "length" "4,4,16,4,4,4,4,*")])
7113
73a4d10b
R
7114(define_insn "*movdi_media_I16"
7115 [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7116 (match_operand:DI 1 "const_int_operand" "I16"))]
7117 "TARGET_SHMEDIA && reload_completed"
7118 "movi %1, %0"
7119 [(set_attr "type" "arith_media")
7120 (set_attr "length" "4")])
7121
fa5322fa 7122(define_split
73a4d10b 7123 [(set (match_operand:DI 0 "arith_reg_dest" "")
e69d1422 7124 (match_operand:DI 1 "immediate_operand" ""))]
fa5322fa
AO
7125 "TARGET_SHMEDIA && reload_completed
7126 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7127 [(set (match_dup 0) (match_dup 1))]
fa5322fa
AO
7128{
7129 rtx insn;
7130
7131 if (TARGET_SHMEDIA64)
7132 insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7133 else
7134 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7135
bd94cb6e 7136 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
fa5322fa
AO
7137
7138 DONE;
d9241861 7139})
fa5322fa
AO
7140
7141(define_expand "movdi_const"
7142 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
dc3ba671
RS
7143 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7144 (const_int 48)] UNSPEC_EXTRACT_S16)))
fa5322fa
AO
7145 (set (match_dup 0)
7146 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
dc3ba671
RS
7147 (const:DI (unspec:DI [(match_dup 1)
7148 (const_int 32)] UNSPEC_EXTRACT_U16))))
fa5322fa
AO
7149 (set (match_dup 0)
7150 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
dc3ba671
RS
7151 (const:DI (unspec:DI [(match_dup 1)
7152 (const_int 16)] UNSPEC_EXTRACT_U16))))
fa5322fa
AO
7153 (set (match_dup 0)
7154 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
dc3ba671
RS
7155 (const:DI (unspec:DI [(match_dup 1)
7156 (const_int 0)] UNSPEC_EXTRACT_U16))))]
fa5322fa
AO
7157 "TARGET_SHMEDIA64 && reload_completed
7158 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
fa5322fa 7159{
ea4210ef 7160 sh_mark_label (operands[1], 4);
d9241861 7161})
fa5322fa
AO
7162
7163(define_expand "movdi_const_32bit"
7164 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
dc3ba671
RS
7165 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7166 (const_int 16)] UNSPEC_EXTRACT_S16)))
fa5322fa
AO
7167 (set (match_dup 0)
7168 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
dc3ba671
RS
7169 (const:DI (unspec:DI [(match_dup 1)
7170 (const_int 0)] UNSPEC_EXTRACT_U16))))]
fa5322fa
AO
7171 "TARGET_SHMEDIA32 && reload_completed
7172 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
fa5322fa 7173{
ea4210ef 7174 sh_mark_label (operands[1], 2);
d9241861 7175})
fa5322fa
AO
7176
7177(define_expand "movdi_const_16bit"
7178 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
dc3ba671
RS
7179 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7180 (const_int 0)] UNSPEC_EXTRACT_S16)))]
fa5322fa
AO
7181 "TARGET_SHMEDIA && flag_pic && reload_completed
7182 && GET_CODE (operands[1]) == SYMBOL_REF"
7183 "")
7184
7185(define_split
73a4d10b 7186 [(set (match_operand:DI 0 "ext_dest_operand" "")
e69d1422 7187 (match_operand:DI 1 "immediate_operand" ""))]
fa5322fa 7188 "TARGET_SHMEDIA && reload_completed
f3536097 7189 && CONST_INT_P (operands[1])
32a7ab3d 7190 && ! satisfies_constraint_I16 (operands[1])"
fa5322fa 7191 [(set (match_dup 0) (match_dup 2))
c1b92d09 7192 (match_dup 1)]
fa5322fa 7193{
c1b92d09
R
7194 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7195 unsigned HOST_WIDE_INT low = val;
7196 unsigned HOST_WIDE_INT high = val;
fa5322fa 7197 unsigned HOST_WIDE_INT sign;
c1b92d09 7198 unsigned HOST_WIDE_INT val2 = val ^ (val-1);
fa5322fa 7199
42201282 7200 /* Zero-extend the 16 least-significant bits. */
c1b92d09 7201 low &= 0xffff;
fa5322fa
AO
7202
7203 /* Arithmetic shift right the word by 16 bits. */
c1b92d09 7204 high >>= 16;
73a4d10b
R
7205 if (GET_CODE (operands[0]) == SUBREG
7206 && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7207 {
7208 high &= 0xffff;
7209 high ^= 0x8000;
7210 high -= 0x8000;
7211 }
7212 else
7213 {
7214 sign = 1;
7215 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7216 high ^= sign;
7217 high -= sign;
7218 }
c1b92d09
R
7219 do
7220 {
7221 /* If we can't generate the constant with a two-insn movi / shori
7222 sequence, try some other strategies. */
735cb76e 7223 if (! CONST_OK_FOR_I16 (high))
c1b92d09
R
7224 {
7225 /* Try constant load / left shift. We know VAL != 0. */
7226 val2 = val ^ (val-1);
7227 if (val2 > 0x1ffff)
7228 {
7229 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7230
735cb76e
R
7231 if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7232 || (! CONST_OK_FOR_I16 (high >> 16)
7233 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
c1b92d09
R
7234 {
7235 val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7236 operands[1] = gen_ashldi3_media (operands[0], operands[0],
7237 GEN_INT (trailing_zeroes));
7238 break;
7239 }
7240 }
7241 /* Try constant load / right shift. */
7242 val2 = (val >> 15) + 1;
7243 if (val2 == (val2 & -val2))
7244 {
7245 int shift = 49 - exact_log2 (val2);
7246
7247 val2 = trunc_int_for_mode (val << shift, DImode);
735cb76e 7248 if (CONST_OK_FOR_I16 (val2))
c1b92d09
R
7249 {
7250 operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7251 GEN_INT (shift));
7252 break;
7253 }
7254 }
7255 /* Try mperm.w . */
7256 val2 = val & 0xffff;
7257 if ((val >> 16 & 0xffff) == val2
7258 && (val >> 32 & 0xffff) == val2
7259 && (val >> 48 & 0xffff) == val2)
7260 {
7261 val2 = (HOST_WIDE_INT) val >> 48;
7262 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7263 operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7264 break;
7265 }
7266 /* Try movi / mshflo.l */
7267 val2 = (HOST_WIDE_INT) val >> 32;
45dc67b7
KK
7268 if (val2 == ((unsigned HOST_WIDE_INT)
7269 trunc_int_for_mode (val, SImode)))
c1b92d09
R
7270 {
7271 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7272 operands[0]);
7273 break;
7274 }
7275 /* Try movi / mshflo.l w/ r63. */
7276 val2 = val + ((HOST_WIDE_INT) -1 << 32);
735cb76e 7277 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
c1b92d09
R
7278 {
7279 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
a556fd39 7280 const0_rtx);
c1b92d09
R
7281 break;
7282 }
7283 }
7284 val2 = high;
7285 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7286 }
7287 while (0);
7288 operands[2] = GEN_INT (val2);
d9241861 7289})
fa5322fa
AO
7290
7291(define_split
73a4d10b 7292 [(set (match_operand:DI 0 "ext_dest_operand" "")
e69d1422 7293 (match_operand:DI 1 "immediate_operand" ""))]
fa5322fa
AO
7294 "TARGET_SHMEDIA && reload_completed
7295 && GET_CODE (operands[1]) == CONST_DOUBLE"
7296 [(set (match_dup 0) (match_dup 2))
7297 (set (match_dup 0)
42201282 7298 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
fa5322fa
AO
7299{
7300 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7301 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7302 unsigned HOST_WIDE_INT val = low;
7303 unsigned HOST_WIDE_INT sign;
7304
42201282 7305 /* Zero-extend the 16 least-significant bits. */
fa5322fa 7306 val &= 0xffff;
fa5322fa
AO
7307 operands[1] = GEN_INT (val);
7308
7309 /* Arithmetic shift right the double-word by 16 bits. */
7310 low >>= 16;
7311 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7312 high >>= 16;
7313 sign = 1;
7314 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7315 high ^= sign;
7316 high -= sign;
7317
7318 /* This will only be true if high is a sign-extension of low, i.e.,
7319 it must be either 0 or (unsigned)-1, and be zero iff the
7320 most-significant bit of low is set. */
7321 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7322 operands[2] = GEN_INT (low);
7323 else
7324 operands[2] = immed_double_const (low, high, DImode);
d9241861 7325})
fa5322fa 7326
c1b92d09 7327(define_insn "shori_media"
73a4d10b 7328 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
fa5322fa
AO
7329 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7330 (const_int 16))
42201282 7331 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
73a4d10b 7332 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
fa5322fa
AO
7333 "@
7334 shori %u2, %0
2ad65b0e
SC
7335 #"
7336 [(set_attr "type" "arith_media,*")])
fa5322fa 7337
73a4d10b
R
7338(define_insn "*shori_media_si"
7339 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7340 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7341 (const_int 16))
42201282 7342 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
73a4d10b
R
7343 "TARGET_SHMEDIA"
7344 "shori %u2, %0")
7345
bc45ade3 7346(define_expand "movdi"
961c4780
SC
7347 [(set (match_operand:DI 0 "general_movdst_operand" "")
7348 (match_operand:DI 1 "general_movsrc_operand" ""))]
bc45ade3 7349 ""
d9241861 7350{
2ef6611e 7351 prepare_move_operands (operands, DImode);
d9241861 7352})
ffae286a 7353
fa5322fa
AO
7354(define_insn "movdf_media"
7355 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
735cb76e 7356 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
fa5322fa
AO
7357 "TARGET_SHMEDIA_FPU
7358 && (register_operand (operands[0], DFmode)
d9da94a1 7359 || sh_register_operand (operands[1], DFmode))"
fa5322fa
AO
7360 "@
7361 fmov.d %1, %0
0ac78517 7362 fmov.qd %N1, %0
fa5322fa
AO
7363 fmov.dq %1, %0
7364 add %1, r63, %0
7365 #
7366 fld%M1.d %m1, %0
7367 fst%M0.d %m0, %1
7368 ld%M1.q %m1, %0
d9da94a1 7369 st%M0.q %m0, %N1"
2ad65b0e 7370 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
fa5322fa
AO
7371
7372(define_insn "movdf_media_nofpu"
7373 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
735cb76e 7374 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
fa5322fa
AO
7375 "TARGET_SHMEDIA
7376 && (register_operand (operands[0], DFmode)
d9da94a1 7377 || sh_register_operand (operands[1], DFmode))"
fa5322fa
AO
7378 "@
7379 add %1, r63, %0
7380 #
7381 ld%M1.q %m1, %0
d9da94a1 7382 st%M0.q %m0, %N1"
2ad65b0e 7383 [(set_attr "type" "arith_media,*,load_media,store_media")])
fa5322fa
AO
7384
7385(define_split
73a4d10b 7386 [(set (match_operand:DF 0 "arith_reg_dest" "")
fa5322fa
AO
7387 (match_operand:DF 1 "immediate_operand" ""))]
7388 "TARGET_SHMEDIA && reload_completed"
7389 [(set (match_dup 3) (match_dup 2))]
fa5322fa
AO
7390{
7391 int endian = WORDS_BIG_ENDIAN ? 1 : 0;
7392 long values[2];
7393 REAL_VALUE_TYPE value;
7394
7395 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
7396 REAL_VALUE_TO_TARGET_DOUBLE (value, values);
7397
7398 if (HOST_BITS_PER_WIDE_INT >= 64)
7399 operands[2] = immed_double_const ((unsigned long) values[endian]
7400 | ((HOST_WIDE_INT) values[1 - endian]
7401 << 32), 0, DImode);
fa5322fa 7402 else
f5b9e7c9
NS
7403 {
7404 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
7405 operands[2] = immed_double_const (values[endian], values[1 - endian],
7406 DImode);
7407 }
fa5322fa
AO
7408
7409 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
d9241861 7410})
fa5322fa 7411
ffae286a 7412;; ??? This should be a define expand.
bc45ade3 7413
bc45ade3 7414(define_insn "movdf_k"
3e943b59
JR
7415 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7416 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
fa5322fa 7417 "TARGET_SH1
157371cf 7418 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
fa5322fa 7419 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
f3536097
SZ
7420 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
7421 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
225e4f43
R
7422 && (arith_reg_operand (operands[0], DFmode)
7423 || arith_reg_operand (operands[1], DFmode))"
d9241861
OE
7424{
7425 return output_movedouble (insn, operands, DFmode);
7426}
b9654711 7427 [(set_attr "length" "4")
3e943b59 7428 (set_attr "type" "move,pcload,load,store")])
bc45ade3 7429
225e4f43
R
7430;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
7431;; However, the d/F/c/z alternative cannot be split directly; it is converted
7432;; with special code in machine_dependent_reorg into a load of the R0_REG and
7433;; the d/m/c/X alternative, which is split later into single-precision
7434;; instructions. And when not optimizing, no splits are done before fixing
7435;; up pcloads, so we need usable length information for that.
7436(define_insn "movdf_i4"
7437 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
7a61cf6f
NC
7438 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
7439 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
7440 (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
157371cf 7441 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
225e4f43
R
7442 && (arith_reg_operand (operands[0], DFmode)
7443 || arith_reg_operand (operands[1], DFmode))"
7a61cf6f
NC
7444 {
7445 switch (which_alternative)
7446 {
7447 case 0:
7448 if (TARGET_FMOVD)
7449 return "fmov %1,%0";
7450 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
35ed5a70
OE
7451 return "fmov %R1,%R0" "\n"
7452 " fmov %S1,%S0";
7a61cf6f 7453 else
35ed5a70
OE
7454 return "fmov %S1,%S0" "\n"
7455 " fmov %R1,%R0";
7a61cf6f
NC
7456 case 3:
7457 case 4:
7458 return "fmov.d %1,%0";
7459 default:
7460 return "#";
7461 }
7462 }
225e4f43 7463 [(set_attr_alternative "length"
7a61cf6f 7464 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
225e4f43
R
7465 (const_int 4)
7466 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
157371cf
AO
7467 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7468 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
225e4f43
R
7469 (const_int 4)
7470 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
fa5322fa
AO
7471 ;; We can't use 4-byte push/pop on SHcompact, so we have to
7472 ;; increment or decrement r15 explicitly.
7473 (if_then_else
68ed2b9c 7474 (match_test "TARGET_SHCOMPACT")
fa5322fa
AO
7475 (const_int 10) (const_int 8))
7476 (if_then_else
68ed2b9c 7477 (match_test "TARGET_SHCOMPACT")
fa5322fa 7478 (const_int 10) (const_int 8))])
78d310c2 7479 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
c49439f1 7480 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
d64264ff
R
7481 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
7482 (const_string "double")
7483 (const_string "none")))])
225e4f43
R
7484
7485;; Moving DFmode between fp/general registers through memory
7486;; (the top of the stack) is faster than moving through fpul even for
7487;; little endian. Because the type of an instruction is important for its
7488;; scheduling, it is beneficial to split these operations, rather than
7489;; emitting them in one single chunk, even if this will expose a stack
7490;; use that will prevent scheduling of other stack accesses beyond this
7491;; instruction.
7492(define_split
7493 [(set (match_operand:DF 0 "register_operand" "")
7494 (match_operand:DF 1 "register_operand" ""))
e69d1422 7495 (use (match_operand:PSI 2 "fpscr_operand" ""))
225e4f43 7496 (clobber (match_scratch:SI 3 "=X"))]
157371cf 7497 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
225e4f43
R
7498 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
7499 [(const_int 0)]
225e4f43
R
7500{
7501 rtx insn, tos;
7502
fa5322fa
AO
7503 if (TARGET_SH5 && true_regnum (operands[1]) < 16)
7504 {
7505 emit_move_insn (stack_pointer_rtx,
0a81f074 7506 plus_constant (Pmode, stack_pointer_rtx, -8));
57d38024 7507 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
fa5322fa
AO
7508 }
7509 else
57d38024
R
7510 tos = gen_tmp_stack_mem (DFmode,
7511 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
225e4f43 7512 insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
fa5322fa 7513 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
b757d36f 7514 add_reg_note (insn, REG_INC, stack_pointer_rtx);
fa5322fa 7515 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
57d38024 7516 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
fa5322fa 7517 else
57d38024
R
7518 tos = gen_tmp_stack_mem (DFmode,
7519 gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
225e4f43 7520 insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
fa5322fa 7521 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
0a81f074
RS
7522 emit_move_insn (stack_pointer_rtx,
7523 plus_constant (Pmode, stack_pointer_rtx, 8));
fa5322fa 7524 else
b757d36f 7525 add_reg_note (insn, REG_INC, stack_pointer_rtx);
225e4f43 7526 DONE;
d9241861 7527})
225e4f43
R
7528
7529;; local-alloc sometimes allocates scratch registers even when not required,
7530;; so we must be prepared to handle these.
7531
7532;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
7533(define_split
7534 [(set (match_operand:DF 0 "general_movdst_operand" "")
7535 (match_operand:DF 1 "general_movsrc_operand" ""))
e69d1422
R
7536 (use (match_operand:PSI 2 "fpscr_operand" ""))
7537 (clobber (match_scratch:SI 3 ""))]
157371cf 7538 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
225e4f43
R
7539 && reload_completed
7540 && true_regnum (operands[0]) < 16
7541 && true_regnum (operands[1]) < 16"
7542 [(set (match_dup 0) (match_dup 1))]
225e4f43
R
7543{
7544 /* If this was a reg <-> mem operation with base + index reg addressing,
7545 we have to handle this in a special way. */
7546 rtx mem = operands[0];
7547 int store_p = 1;
7548 if (! memory_operand (mem, DFmode))
7549 {
7550 mem = operands[1];
7551 store_p = 0;
7552 }
ddef6bc7 7553 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
225e4f43 7554 mem = SUBREG_REG (mem);
f3536097 7555 if (MEM_P (mem))
225e4f43
R
7556 {
7557 rtx addr = XEXP (mem, 0);
7558 if (GET_CODE (addr) == PLUS
f3536097
SZ
7559 && REG_P (XEXP (addr, 0))
7560 && REG_P (XEXP (addr, 1)))
225e4f43
R
7561 {
7562 int offset;
c0d4e710 7563 rtx reg0 = gen_rtx_REG (Pmode, 0);
225e4f43
R
7564 rtx regop = operands[store_p], word0 ,word1;
7565
7566 if (GET_CODE (regop) == SUBREG)
55a2c322 7567 alter_subreg (&regop, true);
225e4f43
R
7568 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
7569 offset = 2;
7570 else
7571 offset = 4;
7572 mem = copy_rtx (mem);
7573 PUT_MODE (mem, SImode);
c0d4e710 7574 word0 = gen_rtx_SUBREG (SImode, regop, 0);
55a2c322 7575 alter_subreg (&word0, true);
c0d4e710 7576 word1 = gen_rtx_SUBREG (SImode, regop, 4);
55a2c322 7577 alter_subreg (&word1, true);
18a7c2a7
AO
7578 if (store_p || ! refers_to_regno_p (REGNO (word0),
7579 REGNO (word0) + 1, addr, 0))
7580 {
7581 emit_insn (store_p
7582 ? gen_movsi_ie (mem, word0)
7583 : gen_movsi_ie (word0, mem));
7584 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7585 mem = copy_rtx (mem);
7586 emit_insn (store_p
7587 ? gen_movsi_ie (mem, word1)
7588 : gen_movsi_ie (word1, mem));
7589 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7590 }
7591 else
7592 {
7593 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7594 emit_insn (gen_movsi_ie (word1, mem));
7595 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7596 mem = copy_rtx (mem);
7597 emit_insn (gen_movsi_ie (word0, mem));
7598 }
225e4f43
R
7599 DONE;
7600 }
7601 }
d9241861 7602})
225e4f43
R
7603
7604;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
7605(define_split
7606 [(set (match_operand:DF 0 "register_operand" "")
7607 (match_operand:DF 1 "memory_operand" ""))
e69d1422 7608 (use (match_operand:PSI 2 "fpscr_operand" ""))
4773afa4 7609 (clobber (reg:SI R0_REG))]
157371cf 7610 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
225e4f43
R
7611 [(parallel [(set (match_dup 0) (match_dup 1))
7612 (use (match_dup 2))
7613 (clobber (scratch:SI))])]
7614 "")
7615
8a99f6f9
R
7616(define_expand "reload_indf__frn"
7617 [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
225e4f43 7618 (match_operand:DF 1 "immediate_operand" "FQ"))
4773afa4 7619 (use (reg:PSI FPSCR_REG))
225e4f43 7620 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
fa5322fa 7621 "TARGET_SH1"
225e4f43
R
7622 "")
7623
8a99f6f9 7624(define_expand "reload_outdf__RnFRm"
225e4f43
R
7625 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
7626 (match_operand:DF 1 "register_operand" "af,r"))
7627 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
fa5322fa 7628 "TARGET_SH1"
225e4f43
R
7629 "")
7630
7631;; Simplify no-op moves.
7632(define_split
7633 [(set (match_operand:SF 0 "register_operand" "")
7634 (match_operand:SF 1 "register_operand" ""))
7635 (use (match_operand:PSI 2 "fpscr_operand" ""))
40779a72 7636 (clobber (match_scratch:SI 3 ""))]
3a8699c7 7637 "TARGET_SH2E && reload_completed
225e4f43
R
7638 && true_regnum (operands[0]) == true_regnum (operands[1])"
7639 [(set (match_dup 0) (match_dup 0))]
7640 "")
7641
7642;; fmovd substitute post-reload splits
7643(define_split
7644 [(set (match_operand:DF 0 "register_operand" "")
7645 (match_operand:DF 1 "register_operand" ""))
e69d1422 7646 (use (match_operand:PSI 2 "fpscr_operand" ""))
40779a72 7647 (clobber (match_scratch:SI 3 ""))]
225e4f43 7648 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
104ee20b
AO
7649 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7650 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
225e4f43 7651 [(const_int 0)]
225e4f43
R
7652{
7653 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
c0d4e710
KH
7654 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
7655 gen_rtx_REG (SFmode, src), operands[2]));
7656 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
7657 gen_rtx_REG (SFmode, src + 1), operands[2]));
225e4f43 7658 DONE;
d9241861 7659})
225e4f43
R
7660
7661(define_split
7662 [(set (match_operand:DF 0 "register_operand" "")
7663 (mem:DF (match_operand:SI 1 "register_operand" "")))
e69d1422
R
7664 (use (match_operand:PSI 2 "fpscr_operand" ""))
7665 (clobber (match_scratch:SI 3 ""))]
157371cf 7666 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
b6c02328 7667 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
225e4f43
R
7668 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
7669 [(const_int 0)]
225e4f43
R
7670{
7671 int regno = true_regnum (operands[0]);
7672 rtx insn;
57d38024
R
7673 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
7674 rtx mem2
7675 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
c0d4e710 7676 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
225e4f43
R
7677 regno + !! TARGET_LITTLE_ENDIAN),
7678 mem2, operands[2]));
b757d36f 7679 add_reg_note (insn, REG_INC, operands[1]);
c0d4e710 7680 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
57d38024
R
7681 regno + ! TARGET_LITTLE_ENDIAN),
7682 change_address (mem, SFmode, NULL_RTX),
225e4f43
R
7683 operands[2]));
7684 DONE;
d9241861 7685})
225e4f43
R
7686
7687(define_split
7688 [(set (match_operand:DF 0 "register_operand" "")
7689 (match_operand:DF 1 "memory_operand" ""))
e69d1422
R
7690 (use (match_operand:PSI 2 "fpscr_operand" ""))
7691 (clobber (match_scratch:SI 3 ""))]
157371cf 7692 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
104ee20b 7693 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
225e4f43 7694 [(const_int 0)]
225e4f43
R
7695{
7696 int regno = true_regnum (operands[0]);
7a61cf6f 7697 rtx addr, insn;
57d38024 7698 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
7a61cf6f
NC
7699 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
7700 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
225e4f43 7701
225e4f43
R
7702 operands[1] = copy_rtx (mem2);
7703 addr = XEXP (mem2, 0);
7a61cf6f
NC
7704
7705 switch (GET_CODE (addr))
225e4f43 7706 {
7a61cf6f
NC
7707 case REG:
7708 /* This is complicated. If the register is an arithmetic register
7709 we can just fall through to the REG+DISP case below. Otherwise
7710 we have to use a combination of POST_INC and REG addressing... */
7711 if (! arith_reg_operand (operands[1], SFmode))
7712 {
7713 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
7714 insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
7715 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7716
7717 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7718
7719 /* If we have modified the stack pointer, the value that we have
7720 read with post-increment might be modified by an interrupt,
7721 so write it back. */
d5652a5a 7722 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
7a61cf6f
NC
7723 emit_insn (gen_push_e (reg0));
7724 else
7725 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), GEN_INT (-4)));
7726 break;
7727 }
7728 /* Fall through. */
7729
7730 case PLUS:
7731 emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7732 operands[1] = copy_rtx (operands[1]);
0a81f074 7733 XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
7a61cf6f
NC
7734 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7735 break;
7736
7737 case POST_INC:
7738 insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7739 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7740
7741 insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7742 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7743 break;
7744
7745 default:
7746 debug_rtx (addr);
7747 gcc_unreachable ();
225e4f43 7748 }
7a61cf6f 7749
225e4f43 7750 DONE;
7a61cf6f 7751})
225e4f43
R
7752
7753(define_split
7754 [(set (match_operand:DF 0 "memory_operand" "")
7755 (match_operand:DF 1 "register_operand" ""))
e69d1422
R
7756 (use (match_operand:PSI 2 "fpscr_operand" ""))
7757 (clobber (match_scratch:SI 3 ""))]
157371cf 7758 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
104ee20b 7759 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
225e4f43 7760 [(const_int 0)]
225e4f43
R
7761{
7762 int regno = true_regnum (operands[1]);
7a61cf6f
NC
7763 rtx insn, addr;
7764 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
7765 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
225e4f43
R
7766
7767 operands[0] = copy_rtx (operands[0]);
7768 PUT_MODE (operands[0], SFmode);
225e4f43 7769 addr = XEXP (operands[0], 0);
7a61cf6f
NC
7770
7771 switch (GET_CODE (addr))
225e4f43 7772 {
7a61cf6f
NC
7773 case REG:
7774 /* This is complicated. If the register is an arithmetic register
7775 we can just fall through to the REG+DISP case below. Otherwise
7776 we have to use a combination of REG and PRE_DEC addressing... */
7777 if (! arith_reg_operand (operands[0], SFmode))
7778 {
7779 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
7780 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7781
7782 operands[0] = copy_rtx (operands[0]);
7783 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
7784
7785 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7786 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7787 break;
7788 }
7789 /* Fall through. */
7790
7791 case PLUS:
7792 /* Since REG+DISP addressing has already been decided upon by gcc
7793 we can rely upon it having chosen an arithmetic register as the
7794 register component of the address. Just emit the lower numbered
7795 register first, to the lower address, then the higher numbered
7796 register to the higher address. */
7797 emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7798
7799 operands[0] = copy_rtx (operands[0]);
0a81f074 7800 XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
7a61cf6f
NC
7801
7802 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7803 break;
7804
7805 case PRE_DEC:
7806 /* This is easy. Output the word to go to the higher address
7807 first (ie the word in the higher numbered register) then the
7808 word to go to the lower address. */
7809
7810 insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7811 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7812
7813 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7814 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7815 break;
7816
7817 default:
7818 /* FAIL; */
7819 debug_rtx (addr);
7820 gcc_unreachable ();
225e4f43 7821 }
7a61cf6f 7822
225e4f43 7823 DONE;
7a61cf6f 7824})
225e4f43 7825
d0aae509 7826;; If the output is a register and the input is memory or a register, we have
52702ae1 7827;; to be careful and see which word needs to be loaded first.
07a45e5c 7828
8e87e161
SC
7829(define_split
7830 [(set (match_operand:DF 0 "general_movdst_operand" "")
7831 (match_operand:DF 1 "general_movsrc_operand" ""))]
fa5322fa 7832 "TARGET_SH1 && reload_completed"
8e87e161
SC
7833 [(set (match_dup 2) (match_dup 3))
7834 (set (match_dup 4) (match_dup 5))]
d0aae509
RK
7835{
7836 int regno;
7837
f3536097 7838 if ((MEM_P (operands[0])
d0aae509 7839 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
f3536097 7840 || (MEM_P (operands[1])
d0aae509
RK
7841 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7842 FAIL;
7843
f5b9e7c9
NS
7844 switch (GET_CODE (operands[0]))
7845 {
7846 case REG:
7847 regno = REGNO (operands[0]);
7848 break;
7849 case SUBREG:
7850 regno = subreg_regno (operands[0]);
7851 break;
7852 case MEM:
7853 regno = -1;
7854 break;
7855 default:
7856 gcc_unreachable ();
7857 }
d0aae509
RK
7858
7859 if (regno == -1
7860 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
8e87e161
SC
7861 {
7862 operands[2] = operand_subword (operands[0], 0, 0, DFmode);
7863 operands[3] = operand_subword (operands[1], 0, 0, DFmode);
7864 operands[4] = operand_subword (operands[0], 1, 0, DFmode);
7865 operands[5] = operand_subword (operands[1], 1, 0, DFmode);
7866 }
7867 else
7868 {
7869 operands[2] = operand_subword (operands[0], 1, 0, DFmode);
7870 operands[3] = operand_subword (operands[1], 1, 0, DFmode);
7871 operands[4] = operand_subword (operands[0], 0, 0, DFmode);
7872 operands[5] = operand_subword (operands[1], 0, 0, DFmode);
7873 }
7874
7875 if (operands[2] == 0 || operands[3] == 0
7876 || operands[4] == 0 || operands[5] == 0)
7877 FAIL;
d9241861 7878})
8e87e161 7879
bc45ade3 7880(define_expand "movdf"
0d7e008e
SC
7881 [(set (match_operand:DF 0 "general_movdst_operand" "")
7882 (match_operand:DF 1 "general_movsrc_operand" ""))]
bc45ade3 7883 ""
1245df60 7884{
2ef6611e 7885 prepare_move_operands (operands, DFmode);
fa5322fa
AO
7886 if (TARGET_SHMEDIA)
7887 {
7888 if (TARGET_SHMEDIA_FPU)
7889 emit_insn (gen_movdf_media (operands[0], operands[1]));
7890 else
7891 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
7892 DONE;
7893 }
157371cf 7894 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
225e4f43
R
7895 {
7896 emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
225e4f43
R
7897 DONE;
7898 }
d9241861 7899})
1245df60 7900
0ac78517
R
7901;;This is incompatible with the way gcc uses subregs.
7902;;(define_insn "movv2sf_i"
7903;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
7904;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
7905;; "TARGET_SHMEDIA_FPU
7906;; && (fp_arith_reg_operand (operands[0], V2SFmode)
7907;; || fp_arith_reg_operand (operands[1], V2SFmode))"
7908;; "@
7909;; #
7910;; fld%M1.p %m1, %0
7911;; fst%M0.p %m0, %1"
7912;; [(set_attr "type" "*,fload_media,fstore_media")])
7913
7914(define_insn_and_split "movv2sf_i"
7915 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
735cb76e 7916 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
0ac78517
R
7917 "TARGET_SHMEDIA_FPU"
7918 "#"
7919 "TARGET_SHMEDIA_FPU && reload_completed"
7920 [(set (match_dup 0) (match_dup 1))]
0ac78517
R
7921{
7922 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
7923 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
d9241861 7924})
fa5322fa
AO
7925
7926(define_expand "movv2sf"
0ac78517
R
7927 [(set (match_operand:V2SF 0 "general_movdst_operand" "")
7928 (match_operand:V2SF 1 "nonimmediate_operand" ""))]
fa5322fa 7929 "TARGET_SHMEDIA_FPU"
fa5322fa 7930{
2ef6611e 7931 prepare_move_operands (operands, V2SFmode);
d9241861 7932})
fa5322fa 7933
0ac78517
R
7934(define_expand "addv2sf3"
7935 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7936 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7937 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7938 "TARGET_SHMEDIA_FPU"
0ac78517
R
7939{
7940 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
7941 DONE;
d9241861 7942})
0ac78517
R
7943
7944(define_expand "subv2sf3"
7945 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7946 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7947 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7948 "TARGET_SHMEDIA_FPU"
0ac78517
R
7949{
7950 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
7951 DONE;
d9241861 7952})
0ac78517
R
7953
7954(define_expand "mulv2sf3"
7955 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7956 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7957 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7958 "TARGET_SHMEDIA_FPU"
0ac78517
R
7959{
7960 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
7961 DONE;
d9241861 7962})
0ac78517
R
7963
7964(define_expand "divv2sf3"
7965 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7966 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7967 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7968 "TARGET_SHMEDIA_FPU"
0ac78517
R
7969{
7970 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
7971 DONE;
d9241861 7972})
0ac78517 7973
fa5322fa 7974(define_insn_and_split "*movv4sf_i"
18943792
KK
7975 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
7976 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
fa5322fa
AO
7977 "TARGET_SHMEDIA_FPU"
7978 "#"
7979 "&& reload_completed"
7980 [(const_int 0)]
fa5322fa
AO
7981{
7982 int i;
7983
7984 for (i = 0; i < 4/2; i++)
7985 {
7986 rtx x, y;
7987
f3536097 7988 if (MEM_P (operands[0]))
57d38024
R
7989 x = adjust_address (operands[0], V2SFmode,
7990 i * GET_MODE_SIZE (V2SFmode));
fa5322fa 7991 else
0ac78517 7992 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
fa5322fa 7993
f3536097 7994 if (MEM_P (operands[1]))
57d38024
R
7995 y = adjust_address (operands[1], V2SFmode,
7996 i * GET_MODE_SIZE (V2SFmode));
fa5322fa 7997 else
0ac78517 7998 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
fa5322fa
AO
7999
8000 emit_insn (gen_movv2sf_i (x, y));
8001 }
8002
8003 DONE;
d9241861 8004}
fa5322fa 8005 [(set_attr "length" "8")])
52702ae1 8006
fa5322fa 8007(define_expand "movv4sf"
0ac78517
R
8008 [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
8009 (match_operand:V4SF 1 "general_operand" ""))]
fa5322fa 8010 "TARGET_SHMEDIA_FPU"
fa5322fa 8011{
2ef6611e 8012 prepare_move_operands (operands, V4SFmode);
d9241861 8013})
fa5322fa
AO
8014
8015(define_insn_and_split "*movv16sf_i"
8016 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8017 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8018 "TARGET_SHMEDIA_FPU"
8019 "#"
8020 "&& reload_completed"
8021 [(const_int 0)]
fa5322fa
AO
8022{
8023 int i;
8024
8025 for (i = 0; i < 16/2; i++)
8026 {
8027 rtx x,y;
8028
f3536097 8029 if (MEM_P (operands[0]))
57d38024
R
8030 x = adjust_address (operands[0], V2SFmode,
8031 i * GET_MODE_SIZE (V2SFmode));
fa5322fa
AO
8032 else
8033 {
40779a72 8034 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
55a2c322 8035 alter_subreg (&x, true);
fa5322fa
AO
8036 }
8037
f3536097 8038 if (MEM_P (operands[1]))
57d38024
R
8039 y = adjust_address (operands[1], V2SFmode,
8040 i * GET_MODE_SIZE (V2SFmode));
fa5322fa
AO
8041 else
8042 {
40779a72 8043 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
55a2c322 8044 alter_subreg (&y, true);
fa5322fa
AO
8045 }
8046
8047 emit_insn (gen_movv2sf_i (x, y));
8048 }
8049
8050 DONE;
d9241861 8051}
fa5322fa 8052 [(set_attr "length" "32")])
52702ae1 8053
fa5322fa
AO
8054(define_expand "movv16sf"
8055 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8056 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8057 "TARGET_SHMEDIA_FPU"
fa5322fa 8058{
2ef6611e 8059 prepare_move_operands (operands, V16SFmode);
d9241861 8060})
fa5322fa
AO
8061
8062(define_insn "movsf_media"
8063 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
735cb76e 8064 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
fa5322fa
AO
8065 "TARGET_SHMEDIA_FPU
8066 && (register_operand (operands[0], SFmode)
d9da94a1 8067 || sh_register_operand (operands[1], SFmode))"
fa5322fa
AO
8068 "@
8069 fmov.s %1, %0
0ac78517 8070 fmov.ls %N1, %0
fa5322fa 8071 fmov.sl %1, %0
b6d33983 8072 add.l %1, r63, %0
fa5322fa
AO
8073 #
8074 fld%M1.s %m1, %0
8075 fst%M0.s %m0, %1
8076 ld%M1.l %m1, %0
d9da94a1 8077 st%M0.l %m0, %N1"
73a4d10b
R
8078 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8079 (set (attr "highpart")
68ed2b9c 8080 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
8081 (const_string "user")]
8082 (const_string "ignore")))])
fa5322fa
AO
8083
8084(define_insn "movsf_media_nofpu"
8085 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
735cb76e 8086 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
fa5322fa
AO
8087 "TARGET_SHMEDIA
8088 && (register_operand (operands[0], SFmode)
d9da94a1 8089 || sh_register_operand (operands[1], SFmode))"
fa5322fa 8090 "@
b6d33983 8091 add.l %1, r63, %0
fa5322fa
AO
8092 #
8093 ld%M1.l %m1, %0
d9da94a1 8094 st%M0.l %m0, %N1"
73a4d10b
R
8095 [(set_attr "type" "arith_media,*,load_media,store_media")
8096 (set (attr "highpart")
68ed2b9c 8097 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
8098 (const_string "user")]
8099 (const_string "ignore")))])
fa5322fa
AO
8100
8101(define_split
73a4d10b 8102 [(set (match_operand:SF 0 "arith_reg_dest" "")
fa5322fa 8103 (match_operand:SF 1 "immediate_operand" ""))]
0ac78517
R
8104 "TARGET_SHMEDIA && reload_completed
8105 && ! FP_REGISTER_P (true_regnum (operands[0]))"
fa5322fa 8106 [(set (match_dup 3) (match_dup 2))]
fa5322fa
AO
8107{
8108 long values;
8109 REAL_VALUE_TYPE value;
8110
8111 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
8112 REAL_VALUE_TO_TARGET_SINGLE (value, values);
8113 operands[2] = GEN_INT (values);
52702ae1 8114
fa5322fa 8115 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
d9241861 8116})
bc45ade3 8117
bc45ade3 8118(define_insn "movsf_i"
3e943b59 8119 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
735cb76e 8120 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))]
fa5322fa 8121 "TARGET_SH1
3a8699c7 8122 && (! TARGET_SH2E
fa5322fa 8123 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
f3536097
SZ
8124 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8125 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
1245df60
R
8126 && (arith_reg_operand (operands[0], SFmode)
8127 || arith_reg_operand (operands[1], SFmode))"
bc45ade3
SC
8128 "@
8129 mov %1,%0
735cb76e 8130 mov #0,%0
bc45ade3
SC
8131 mov.l %1,%0
8132 mov.l %1,%0
3e943b59 8133 mov.l %1,%0
b9654711 8134 lds %1,%0
0d7e008e 8135 sts %1,%0"
3e943b59 8136 [(set_attr "type" "move,move,pcload,load,store,move,move")])
bc45ade3 8137
4dff12bf
R
8138;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8139;; update_flow_info would not know where to put REG_EQUAL notes
8140;; when the destination changes mode.
45348d9e 8141(define_insn "movsf_ie"
7f74cc8d 8142 [(set (match_operand:SF 0 "general_movdst_operand"
a92facbb 8143 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
7f74cc8d 8144 (match_operand:SF 1 "general_movsrc_operand"
a92facbb
AO
8145 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8146 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c"))
735cb76e 8147 (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
3a8699c7 8148 "TARGET_SH2E
45348d9e 8149 && (arith_reg_operand (operands[0], SFmode)
c2d10707
AO
8150 || arith_reg_operand (operands[1], SFmode)
8151 || arith_reg_operand (operands[3], SImode)
8152 || (fpul_operand (operands[0], SFmode)
8153 && memory_operand (operands[1], SFmode)
8154 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
8155 || (fpul_operand (operands[1], SFmode)
8156 && memory_operand (operands[0], SFmode)
8157 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
45348d9e
JW
8158 "@
8159 fmov %1,%0
8160 mov %1,%0
8161 fldi0 %0
8162 fldi1 %0
7f74cc8d 8163 #
45348d9e
JW
8164 fmov.s %1,%0
8165 fmov.s %1,%0
8166 mov.l %1,%0
8167 mov.l %1,%0
3e943b59 8168 mov.l %1,%0
1245df60
R
8169 fsts fpul,%0
8170 flds %1,fpul
8171 lds.l %1,%0
8172 #
4dff12bf
R
8173 sts %1,%0
8174 lds %1,%0
a92facbb
AO
8175 sts.l %1,%0
8176 lds.l %1,%0
4dff12bf 8177 ! move optimized away"
78d310c2 8178 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
c49439f1 8179 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
6b2eeb54
KK
8180 (set_attr_alternative "length"
8181 [(const_int 2)
8182 (const_int 2)
8183 (const_int 2)
8184 (const_int 2)
8185 (const_int 4)
8186 (if_then_else
68ed2b9c 8187 (match_test "TARGET_SH2A")
6b2eeb54
KK
8188 (const_int 4) (const_int 2))
8189 (if_then_else
68ed2b9c 8190 (match_test "TARGET_SH2A")
6b2eeb54
KK
8191 (const_int 4) (const_int 2))
8192 (const_int 2)
9705d817 8193 (if_then_else
68ed2b9c 8194 (match_test "TARGET_SH2A")
9705d817
KK
8195 (const_int 4) (const_int 2))
8196 (if_then_else
68ed2b9c 8197 (match_test "TARGET_SH2A")
9705d817 8198 (const_int 4) (const_int 2))
6b2eeb54
KK
8199 (const_int 2)
8200 (const_int 2)
8201 (const_int 2)
8202 (const_int 4)
8203 (const_int 2)
8204 (const_int 2)
8205 (const_int 2)
8206 (const_int 2)
8207 (const_int 0)])
d64264ff
R
8208 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8209 (const_string "single")
7a61cf6f 8210 (const_string "single")))])
79664856 8211
1245df60
R
8212(define_split
8213 [(set (match_operand:SF 0 "register_operand" "")
8214 (match_operand:SF 1 "register_operand" ""))
e69d1422 8215 (use (match_operand:PSI 2 "fpscr_operand" ""))
4773afa4 8216 (clobber (reg:SI FPUL_REG))]
fa5322fa 8217 "TARGET_SH1"
4773afa4 8218 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
225e4f43 8219 (use (match_dup 2))
1245df60 8220 (clobber (scratch:SI))])
4773afa4 8221 (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
225e4f43 8222 (use (match_dup 2))
1245df60
R
8223 (clobber (scratch:SI))])]
8224 "")
8225
bc45ade3 8226(define_expand "movsf"
0d7e008e 8227 [(set (match_operand:SF 0 "general_movdst_operand" "")
3e943b59 8228 (match_operand:SF 1 "general_movsrc_operand" ""))]
bc45ade3 8229 ""
3e943b59 8230{
2ef6611e 8231 prepare_move_operands (operands, SFmode);
fa5322fa
AO
8232 if (TARGET_SHMEDIA)
8233 {
8234 if (TARGET_SHMEDIA_FPU)
8235 emit_insn (gen_movsf_media (operands[0], operands[1]));
8236 else
8237 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8238 DONE;
8239 }
3a8699c7 8240 if (TARGET_SH2E)
3e943b59 8241 {
225e4f43 8242 emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
3e943b59
JR
8243 DONE;
8244 }
d9241861 8245})
7f74cc8d 8246
225e4f43 8247(define_insn "mov_nop"
e69d1422 8248 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
3a8699c7 8249 "TARGET_SH2E"
225e4f43
R
8250 ""
8251 [(set_attr "length" "0")
8252 (set_attr "type" "nil")])
8253
8a99f6f9 8254(define_expand "reload_insf__frn"
c2d10707 8255 [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
7f74cc8d 8256 (match_operand:SF 1 "immediate_operand" "FQ"))
4773afa4 8257 (use (reg:PSI FPSCR_REG))
7f74cc8d 8258 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
fa5322fa 8259 "TARGET_SH1"
7f74cc8d 8260 "")
225e4f43 8261
8a99f6f9 8262(define_expand "reload_insi__i_fpul"
73a4d10b
R
8263 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
8264 (match_operand:SI 1 "immediate_operand" "i"))
225e4f43 8265 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
fa5322fa 8266 "TARGET_SH1"
225e4f43
R
8267 "")
8268
73a4d10b
R
8269(define_expand "ptabs"
8270 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
8271 "TARGET_SHMEDIA"
73a4d10b
R
8272{
8273 if (!TARGET_PT_FIXED)
8274 {
8275 rtx eq = operands[1];
8276
8277 /* ??? For canonical RTL we really should remove any CONST from EQ
8278 before wrapping it in the AND, and finally wrap the EQ into a
8279 const if is constant. However, for reload we must expose the
8280 input register or symbolic constant, and we can't have
8281 different insn structures outside of the operands for different
8282 alternatives of the same pattern. */
8283 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
8284 GEN_INT (3));
8285 operands[1]
8286 = (gen_rtx_IF_THEN_ELSE
8287 (PDImode,
8288 eq,
8289 gen_rtx_MEM (PDImode, operands[1]),
8290 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
8291 PDImode, operands[1])));
8292 }
d9241861 8293})
73a4d10b
R
8294
8295;; expanded by ptabs expander.
8296(define_insn "*extendsipdi_media"
8297 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8298 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
8299 "r,Csy")
8300 (const_int 3))
8301 (const_int 3))
8302 (mem:PDI (match_dup 1))
8303 (sign_extend:PDI (match_dup 1))))]
8304 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8305 "@
8306 ptabs %1, %0
8307 pt %1, %0"
8308 [(set_attr "type" "ptabs_media,pt_media")
8309 (set_attr "length" "4,*")])
8310
8311(define_insn "*truncdipdi_media"
8312 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8313 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
8314 "r,Csy")
8315 (const_int 3))
8316 (const_int 3))
8317 (mem:PDI (match_dup 1))
8318 (truncate:PDI (match_dup 1))))]
8319 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8320 "@
8321 ptabs %1, %0
8322 pt %1, %0"
8323 [(set_attr "type" "ptabs_media,pt_media")
8324 (set_attr "length" "4,*")])
8325
225e4f43
R
8326(define_insn "*movsi_y"
8327 [(set (match_operand:SI 0 "register_operand" "=y,y")
735cb76e 8328 (match_operand:SI 1 "immediate_operand" "Qi,I08"))
c77e04ae 8329 (clobber (match_scratch:SI 2 "=&z,r"))]
3a8699c7 8330 "TARGET_SH2E
225e4f43
R
8331 && (reload_in_progress || reload_completed)"
8332 "#"
8333 [(set_attr "length" "4")
8334 (set_attr "type" "pcload,move")])
8335
8336(define_split
997718c7
RH
8337 [(set (match_operand:SI 0 "register_operand" "")
8338 (match_operand:SI 1 "immediate_operand" ""))
8339 (clobber (match_operand:SI 2 "register_operand" ""))]
fa5322fa 8340 "TARGET_SH1"
225e4f43
R
8341 [(set (match_dup 2) (match_dup 1))
8342 (set (match_dup 0) (match_dup 2))]
8343 "")
bc45ade3
SC
8344\f
8345;; ------------------------------------------------------------------------
8346;; Define the real conditional branch instructions.
8347;; ------------------------------------------------------------------------
8348
b4eca9c8
OE
8349(define_expand "branch_true"
8350 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
8351 (label_ref (match_operand 0))
ef402c65 8352 (pc)))]
b4eca9c8 8353 "TARGET_SH1")
ef402c65 8354
b4eca9c8
OE
8355(define_expand "branch_false"
8356 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8357 (label_ref (match_operand 0))
cab4c510 8358 (pc)))]
b4eca9c8 8359 "TARGET_SH1")
cab4c510 8360
b4eca9c8
OE
8361(define_insn_and_split "*cbranch_t"
8362 [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
8363 (label_ref (match_operand 0))
ef402c65 8364 (pc)))]
f031c344 8365 "TARGET_SH1"
ef402c65 8366{
b4eca9c8 8367 return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
ef402c65 8368}
4aaf79c2 8369 "&& 1"
b4eca9c8
OE
8370 [(set (pc) (if_then_else (eq (reg:SI T_REG) (match_dup 2))
8371 (label_ref (match_dup 0))
cab4c510 8372 (pc)))]
cab4c510 8373{
b4eca9c8
OE
8374 /* Try to find missed test and branch combine opportunities which result
8375 in redundant T bit tests before conditional branches.
4aaf79c2
OE
8376 This is done not only after combine (and before reload) but in every
8377 split pass, because some opportunities are formed also after combine.
b4eca9c8
OE
8378 FIXME: Probably this would not be needed if CCmode was used
8379 together with TARGET_FIXED_CONDITION_CODE_REGS. */
8380
8381 const int treg_value = sh_eval_treg_value (operands[1]);
8382 operands[2] = NULL_RTX;
8383
8384 /* Scan the insns backwards for an insn that sets the T bit by testing a
8385 reg against zero like:
8386 (set (reg T_REG) (eq (reg) (const_int 0))) */
8387 rtx testing_insn = NULL_RTX;
8388 rtx tested_reg = NULL_RTX;
8389
26943929
OE
8390 set_of_reg s0 = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn,
8391 prev_nonnote_insn_bb);
8392 if (s0.set_src != NULL_RTX
8393 && GET_CODE (s0.set_src) == EQ
8394 && REG_P (XEXP (s0.set_src, 0))
8395 && satisfies_constraint_Z (XEXP (s0.set_src, 1)))
b4eca9c8 8396 {
26943929
OE
8397 testing_insn = s0.insn;
8398 tested_reg = XEXP (s0.set_src, 0);
b4eca9c8 8399 }
26943929 8400 else
b4eca9c8
OE
8401 FAIL;
8402
8403 /* Continue scanning the insns backwards and try to find the insn that
8404 sets the tested reg which we found above. If the reg is set by storing
8405 the T bit or the negated T bit we can eliminate the test insn before
8406 the branch. Notice that the branch condition has to be inverted if the
8407 test is eliminated. */
8408
8409 /* If the T bit is used between the testing insn and the brach insn
8410 leave it alone. */
8411 if (reg_used_between_p (get_t_reg_rtx (), testing_insn, curr_insn))
8412 FAIL;
8413
26943929 8414 while (true)
b4eca9c8 8415 {
4aaf79c2 8416 /* It's not safe to go beyond the current basic block after reload. */
26943929 8417 set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn,
4aaf79c2
OE
8418 reload_completed
8419 ? prev_nonnote_insn_bb
8420 : prev_nonnote_insn);
26943929 8421 if (s1.set_src == NULL_RTX)
b4eca9c8 8422 break;
b4eca9c8 8423
26943929
OE
8424 if (t_reg_operand (s1.set_src, VOIDmode))
8425 operands[2] = GEN_INT (treg_value ^ 1);
8426 else if (negt_reg_operand (s1.set_src, VOIDmode))
8427 operands[2] = GEN_INT (treg_value);
8428 else if (REG_P (s1.set_src))
b4eca9c8 8429 {
26943929
OE
8430 /* If it's a reg-reg copy follow the copied reg. This can
8431 happen e.g. when T bit store zero-extensions are
8432 eliminated. */
8433 tested_reg = s1.set_src;
8434 s0.insn = s1.insn;
8435 continue;
8436 }
b4eca9c8 8437
26943929
OE
8438 /* It's only safe to remove the testing insn if the T bit is not
8439 modified between the testing insn and the insn that stores the
8440 T bit. Notice that some T bit stores such as negc also modify
8441 the T bit. */
8442 if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn)
8443 || modified_in_p (get_t_reg_rtx (), s1.insn))
8444 operands[2] = NULL_RTX;
b4eca9c8 8445
26943929
OE
8446 break;
8447 }
b4eca9c8
OE
8448
8449 if (operands[2] == NULL_RTX)
8450 FAIL;
8451
8452 set_insn_deleted (testing_insn);
cab4c510
OE
8453}
8454 [(set_attr "type" "cbranch")])
8455
1245df60
R
8456;; Patterns to prevent reorg from re-combining a condbranch with a branch
8457;; which destination is too far away.
8458;; The const_int_operand is distinct for each branch target; it avoids
8459;; unwanted matches with redundant_insn.
8460(define_insn "block_branch_redirect"
e11cddec 8461 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
fa5322fa 8462 "TARGET_SH1"
1245df60
R
8463 ""
8464 [(set_attr "length" "0")])
bc45ade3 8465
1245df60
R
8466;; This one has the additional purpose to record a possible scratch register
8467;; for the following branch.
10f4f635
R
8468;; ??? Unfortunately, just setting the scratch register is not good enough,
8469;; because the insn then might be deemed dead and deleted. And we can't
8470;; make the use in the jump insn explicit because that would disable
8471;; delay slot scheduling from the target.
1245df60 8472(define_insn "indirect_jump_scratch"
e69d1422 8473 [(set (match_operand:SI 0 "register_operand" "=r")
73774972 8474 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
10f4f635 8475 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
fa5322fa 8476 "TARGET_SH1"
1245df60
R
8477 ""
8478 [(set_attr "length" "0")])
c608a684
R
8479
8480;; This one is used to preemt an insn from beyond the bra / braf / jmp
8481;; being pulled into the delay slot of a condbranch that has been made to
8482;; jump around the unconditional jump because it was out of range.
8483(define_insn "stuff_delay_slot"
8484 [(set (pc)
f60e5a20
KK
8485 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
8486 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
c608a684
R
8487 "TARGET_SH1"
8488 ""
8489 [(set_attr "length" "0")
8490 (set_attr "cond_delay_slot" "yes")])
bc45ade3
SC
8491\f
8492;; Conditional branch insns
8493
f90b7a5a
PB
8494(define_expand "cbranchint4_media"
8495 [(set (pc)
8496 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
8497 [(match_operand 1 "" "")
8498 (match_operand 2 "" "")])
8499 (match_operand 3 "" "")
8500 (pc)))]
8501 "TARGET_SHMEDIA"
f90b7a5a
PB
8502{
8503 enum machine_mode mode = GET_MODE (operands[1]);
8504 if (mode == VOIDmode)
8505 mode = GET_MODE (operands[2]);
8506 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
8507 {
8508 operands[1] = force_reg (mode, operands[1]);
8509 if (CONSTANT_P (operands[2])
8510 && (! satisfies_constraint_I06 (operands[2])))
8511 operands[2] = force_reg (mode, operands[2]);
8512 }
8513 else
8514 {
8515 if (operands[1] != const0_rtx)
8516 operands[1] = force_reg (mode, operands[1]);
8517 if (operands[2] != const0_rtx)
8518 operands[2] = force_reg (mode, operands[2]);
8519 }
8520 switch (GET_CODE (operands[0]))
8521 {
8522 case LEU:
8523 case LE:
8524 case LTU:
8525 case LT:
8526 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
8527 VOIDmode, operands[2], operands[1]);
8528 operands[1] = XEXP (operands[0], 0);
8529 operands[2] = XEXP (operands[0], 1);
8530 break;
8531 default:
8532 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
8533 VOIDmode, operands[1], operands[2]);
8534 break;
8535 }
8536 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
d9241861 8537})
f90b7a5a
PB
8538
8539(define_expand "cbranchfp4_media"
1245df60 8540 [(set (pc)
f90b7a5a
PB
8541 (if_then_else (match_operator 0 "sh_float_comparison_operator"
8542 [(match_operand 1 "" "")
8543 (match_operand 2 "" "")])
8544 (match_operand 3 "" "")
bc45ade3 8545 (pc)))]
fa5322fa 8546 "TARGET_SHMEDIA"
f90b7a5a 8547{
f90b7a5a
PB
8548 rtx tmp = gen_reg_rtx (SImode);
8549 rtx cmp;
8550 if (GET_CODE (operands[0]) == NE)
8551 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
8552 else
8553 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
8554 operands[1], operands[2]);
8555
8556 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
f90b7a5a
PB
8557
8558 if (GET_CODE (cmp) == GET_CODE (operands[0]))
42663bf1 8559 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
f90b7a5a 8560 else
42663bf1
PB
8561 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
8562 operands[1] = tmp;
f90b7a5a
PB
8563 operands[2] = const0_rtx;
8564 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
d9241861 8565})
bc45ade3 8566
c8cc4417 8567(define_insn "*beq_media_i"
1245df60 8568 [(set (pc)
c8cc4417
R
8569 (if_then_else (match_operator 3 "equality_comparison_operator"
8570 [(match_operand:DI 1 "arith_reg_operand" "r,r")
735cb76e 8571 (match_operand:DI 2 "arith_operand" "r,I06")])
73a4d10b
R
8572 (match_operand 0 "target_operand" "b,b")
8573 (pc)))]
8574 "TARGET_SHMEDIA"
8575 "@
8576 b%o3%' %1, %2, %0%>
8577 b%o3i%' %1, %2, %0%>"
8578 [(set_attr "type" "cbranch_media")])
8579
8580(define_insn "*beq_media_i32"
8581 [(set (pc)
8582 (if_then_else (match_operator 3 "equality_comparison_operator"
8583 [(match_operand:SI 1 "arith_reg_operand" "r,r")
8584 (match_operand:SI 2 "arith_operand" "r,I06")])
8585 (match_operand 0 "target_operand" "b,b")
1245df60 8586 (pc)))]
fa5322fa
AO
8587 "TARGET_SHMEDIA"
8588 "@
73a4d10b
R
8589 b%o3%' %1, %2, %0%>
8590 b%o3i%' %1, %2, %0%>"
c8cc4417 8591 [(set_attr "type" "cbranch_media")])
bc45ade3 8592
c8cc4417 8593(define_insn "*bgt_media_i"
fa5322fa 8594 [(set (pc)
c8cc4417
R
8595 (if_then_else (match_operator 3 "greater_comparison_operator"
8596 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8597 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
73a4d10b
R
8598 (match_operand 0 "target_operand" "b")
8599 (pc)))]
8600 "TARGET_SHMEDIA"
8601 "b%o3%' %N1, %N2, %0%>"
8602 [(set_attr "type" "cbranch_media")])
8603
8604(define_insn "*bgt_media_i32"
8605 [(set (pc)
8606 (if_then_else (match_operator 3 "greater_comparison_operator"
8607 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8608 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8609 (match_operand 0 "target_operand" "b")
fa5322fa
AO
8610 (pc)))]
8611 "TARGET_SHMEDIA"
73a4d10b 8612 "b%o3%' %N1, %N2, %0%>"
c8cc4417 8613 [(set_attr "type" "cbranch_media")])
fa5322fa 8614
73a4d10b
R
8615;; These are only needed to make invert_jump() happy - otherwise, jump
8616;; optimization will be silently disabled.
b6d33983 8617(define_insn "*blt_media_i"
fa5322fa 8618 [(set (pc)
c8cc4417 8619 (if_then_else (match_operator 3 "less_comparison_operator"
b6d33983
R
8620 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8621 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
73a4d10b 8622 (match_operand 0 "target_operand" "b")
fa5322fa
AO
8623 (pc)))]
8624 "TARGET_SHMEDIA"
73a4d10b
R
8625 "b%o3%' %N2, %N1, %0%>"
8626 [(set_attr "type" "cbranch_media")])
8627
8628(define_insn "*blt_media_i32"
8629 [(set (pc)
8630 (if_then_else (match_operator 3 "less_comparison_operator"
8631 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8632 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8633 (match_operand 0 "target_operand" "b")
8634 (pc)))]
8635 "TARGET_SHMEDIA"
8636 "b%o3%' %N2, %N1, %0%>"
c8cc4417 8637 [(set_attr "type" "cbranch_media")])
fa5322fa 8638
f90b7a5a
PB
8639;; combiner splitter for test-and-branch on single bit in register. This
8640;; is endian dependent because the non-paradoxical subreg looks different
8641;; on big endian.
8642(define_split
fa5322fa 8643 [(set (pc)
f90b7a5a
PB
8644 (if_then_else
8645 (match_operator 3 "equality_comparison_operator"
8646 [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
8647 "extend_reg_operand" "")
8648 0)
8649 (const_int 1)
8650 (match_operand 2
8651 "const_int_operand" "")) 0)
8652 (const_int 0)])
8653 (match_operand 0 "target_operand" "")
8654 (pc)))
8655 (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
8656 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
8657 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
8658 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
fa5322fa 8659{
f90b7a5a
PB
8660 operands[5] = GEN_INT (31 - INTVAL (operands[2]));
8661 operands[6] = (GET_CODE (operands[3]) == EQ
8662 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
8663 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
d9241861 8664})
fa5322fa 8665
f90b7a5a
PB
8666; operand 0 is the loop count pseudo register
8667; operand 1 is the number of loop iterations or 0 if it is unknown
8668; operand 2 is the maximum number of loop iterations
8669; operand 3 is the number of levels of enclosed loops
8670; operand 4 is the label to jump to at the top of the loop
8671
8672(define_expand "doloop_end"
8673 [(parallel [(set (pc) (if_then_else
8674 (ne:SI (match_operand:SI 0 "" "")
8675 (const_int 1))
8676 (label_ref (match_operand 4 "" ""))
8677 (pc)))
8678 (set (match_dup 0)
8679 (plus:SI (match_dup 0) (const_int -1)))
2407343c
JR
8680 (clobber (reg:SI T_REG))])
8681 (match_operand 5 "" "")]
f90b7a5a 8682 "TARGET_SH2"
fa5322fa 8683{
f90b7a5a
PB
8684 if (GET_MODE (operands[0]) != SImode)
8685 FAIL;
c3a76b2f 8686 emit_jump_insn (gen_doloop_end_split (operands[0], operands[4], operands[0]));
2407343c 8687 DONE;
d9241861 8688})
fa5322fa 8689
f90b7a5a 8690(define_insn_and_split "doloop_end_split"
fa5322fa 8691 [(set (pc)
077668e3 8692 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
f90b7a5a
PB
8693 (const_int 1))
8694 (label_ref (match_operand 1 "" ""))
8695 (pc)))
077668e3
BS
8696 (set (match_operand:SI 0 "arith_reg_dest" "=r")
8697 (plus (match_dup 2) (const_int -1)))
f90b7a5a
PB
8698 (clobber (reg:SI T_REG))]
8699 "TARGET_SH2"
8700 "#"
fa5322fa 8701 ""
f90b7a5a 8702 [(parallel [(set (reg:SI T_REG)
077668e3
BS
8703 (eq:SI (match_dup 2) (const_int 1)))
8704 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
f90b7a5a 8705 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
077668e3 8706 (label_ref (match_dup 1))
f90b7a5a 8707 (pc)))]
d9241861 8708 ""
f90b7a5a 8709 [(set_attr "type" "cbranch")])
fa5322fa 8710
f90b7a5a
PB
8711\f
8712;; ------------------------------------------------------------------------
8713;; Jump and linkage insns
8714;; ------------------------------------------------------------------------
bc45ade3 8715
fa5322fa 8716(define_insn "jump_compact"
bc45ade3
SC
8717 [(set (pc)
8718 (label_ref (match_operand 0 "" "")))]
6d4d15b8 8719 "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
bc45ade3 8720{
22e1ebf1 8721 /* The length is 16 if the delay slot is unfilled. */
1245df60 8722 if (get_attr_length(insn) > 4)
51aea58d 8723 return output_far_jump(insn, operands[0]);
bc45ade3 8724 else
d9241861
OE
8725 return "bra %l0%#";
8726}
bc45ade3
SC
8727 [(set_attr "type" "jump")
8728 (set_attr "needs_delay_slot" "yes")])
8729
10f4f635
R
8730;; ??? It would be much saner to explicitly use the scratch register
8731;; in the jump insn, and have indirect_jump_scratch only set it,
8732;; but fill_simple_delay_slots would refuse to do delay slot filling
8733;; from the target then, as it uses simplejump_p.
8734;;(define_insn "jump_compact_far"
8735;; [(set (pc)
8736;; (label_ref (match_operand 0 "" "")))
8737;; (use (match_operand 1 "register_operand" "r")]
8738;; "TARGET_SH1"
8739;; "* return output_far_jump(insn, operands[0], operands[1]);"
8740;; [(set_attr "type" "jump")
8741;; (set_attr "needs_delay_slot" "yes")])
8742
fa5322fa
AO
8743(define_insn "jump_media"
8744 [(set (pc)
73a4d10b 8745 (match_operand 0 "target_operand" "b"))]
fa5322fa 8746 "TARGET_SHMEDIA"
73a4d10b 8747 "blink %0, r63%>"
2ad65b0e 8748 [(set_attr "type" "jump_media")])
fa5322fa
AO
8749
8750(define_expand "jump"
8751 [(set (pc)
8752 (label_ref (match_operand 0 "" "")))]
8753 ""
fa5322fa
AO
8754{
8755 if (TARGET_SH1)
8e831557 8756 emit_jump_insn (gen_jump_compact (operands[0]));
fa5322fa
AO
8757 else if (TARGET_SHMEDIA)
8758 {
8759 if (reload_in_progress || reload_completed)
8760 FAIL;
73a4d10b 8761 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
8e831557 8762 operands[0])));
fa5322fa
AO
8763 }
8764 DONE;
d9241861 8765})
fa5322fa
AO
8766
8767(define_insn "force_mode_for_call"
8768 [(use (reg:PSI FPSCR_REG))]
8769 "TARGET_SHCOMPACT"
8770 ""
8771 [(set_attr "length" "0")
8772 (set (attr "fp_mode")
8773 (if_then_else (eq_attr "fpu_single" "yes")
8774 (const_string "single") (const_string "double")))])
8775
bc45ade3 8776(define_insn "calli"
aa684c94 8777 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
bc45ade3 8778 (match_operand 1 "" ""))
5d00b10a 8779 (use (reg:PSI FPSCR_REG))
4773afa4 8780 (clobber (reg:SI PR_REG))]
fa5322fa 8781 "TARGET_SH1"
d9241861
OE
8782{
8783 if (TARGET_SH2A && (dbr_sequence_length () == 0))
35ed5a70 8784 return "jsr/n @%0";
d9241861 8785 else
35ed5a70 8786 return "jsr @%0%#";
d9241861 8787}
ffae286a 8788 [(set_attr "type" "call")
d64264ff
R
8789 (set (attr "fp_mode")
8790 (if_then_else (eq_attr "fpu_single" "yes")
8791 (const_string "single") (const_string "double")))
73774972
EC
8792 (set_attr "needs_delay_slot" "yes")
8793 (set_attr "fp_set" "unknown")])
961c4780 8794
561642fa
AP
8795;; This is TBR relative jump instruction for SH2A architecture.
8796;; Its use is enabled assigning an attribute "function_vector"
8797;; and the vector number to a function during its declaration.
8798
8799(define_insn "calli_tbr_rel"
8800 [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
8801 (match_operand 1 "" ""))
8802 (use (reg:PSI FPSCR_REG))
8803 (clobber (reg:SI PR_REG))]
8804 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
561642fa
AP
8805{
8806 unsigned HOST_WIDE_INT vect_num;
8807 vect_num = sh2a_get_function_vector_number (operands[0]);
8808 operands[2] = GEN_INT (vect_num * 4);
8809
35ed5a70 8810 return "jsr/n @@(%O2,tbr)";
d9241861 8811}
561642fa
AP
8812 [(set_attr "type" "call")
8813 (set (attr "fp_mode")
8814 (if_then_else (eq_attr "fpu_single" "yes")
8815 (const_string "single") (const_string "double")))
8816 (set_attr "needs_delay_slot" "no")
8817 (set_attr "fp_set" "unknown")])
8818
1a66cd67
AO
8819;; This is a pc-rel call, using bsrf, for use with PIC.
8820
8821(define_insn "calli_pcrel"
8822 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8823 (match_operand 1 "" ""))
5d00b10a 8824 (use (reg:PSI FPSCR_REG))
2d01e445 8825 (use (reg:SI PIC_REG))
1a66cd67 8826 (use (match_operand 2 "" ""))
4773afa4 8827 (clobber (reg:SI PR_REG))]
eb69f95c 8828 "TARGET_SH2"
35ed5a70
OE
8829{
8830 return "bsrf %0" "\n"
8831 "%O2:%#";
8832}
1a66cd67
AO
8833 [(set_attr "type" "call")
8834 (set (attr "fp_mode")
8835 (if_then_else (eq_attr "fpu_single" "yes")
8836 (const_string "single") (const_string "double")))
73774972
EC
8837 (set_attr "needs_delay_slot" "yes")
8838 (set_attr "fp_set" "unknown")])
1a66cd67 8839
2d01e445
AO
8840(define_insn_and_split "call_pcrel"
8841 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
8842 (match_operand 1 "" ""))
8843 (use (reg:PSI FPSCR_REG))
8844 (use (reg:SI PIC_REG))
8845 (clobber (reg:SI PR_REG))
8846 (clobber (match_scratch:SI 2 "=r"))]
cb51ecd2 8847 "TARGET_SH2"
2d01e445
AO
8848 "#"
8849 "reload_completed"
8850 [(const_int 0)]
2d01e445 8851{
8e831557 8852 rtx lab = PATTERN (gen_call_site ());
2d01e445 8853
675ff4c7 8854 if (SYMBOL_REF_LOCAL_P (operands[0]))
2d01e445
AO
8855 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
8856 else
8857 emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
329b3cc3 8858 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
2d01e445 8859 DONE;
d9241861 8860}
2d01e445
AO
8861 [(set_attr "type" "call")
8862 (set (attr "fp_mode")
8863 (if_then_else (eq_attr "fpu_single" "yes")
8864 (const_string "single") (const_string "double")))
73774972
EC
8865 (set_attr "needs_delay_slot" "yes")
8866 (set_attr "fp_set" "unknown")])
2d01e445 8867
fa5322fa
AO
8868(define_insn "call_compact"
8869 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8870 (match_operand 1 "" ""))
8871 (match_operand 2 "immediate_operand" "n")
8872 (use (reg:SI R0_REG))
8873 (use (reg:SI R1_REG))
8874 (use (reg:PSI FPSCR_REG))
8875 (clobber (reg:SI PR_REG))]
8876 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8877 "jsr @%0%#"
8878 [(set_attr "type" "call")
8879 (set (attr "fp_mode")
8880 (if_then_else (eq_attr "fpu_single" "yes")
8881 (const_string "single") (const_string "double")))
8882 (set_attr "needs_delay_slot" "yes")])
8883
8884(define_insn "call_compact_rettramp"
8885 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8886 (match_operand 1 "" ""))
8887 (match_operand 2 "immediate_operand" "n")
8888 (use (reg:SI R0_REG))
8889 (use (reg:SI R1_REG))
8890 (use (reg:PSI FPSCR_REG))
8891 (clobber (reg:SI R10_REG))
8892 (clobber (reg:SI PR_REG))]
8893 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8894 "jsr @%0%#"
8895 [(set_attr "type" "call")
8896 (set (attr "fp_mode")
8897 (if_then_else (eq_attr "fpu_single" "yes")
8898 (const_string "single") (const_string "double")))
8899 (set_attr "needs_delay_slot" "yes")])
8900
8901(define_insn "call_media"
73a4d10b 8902 [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
fa5322fa
AO
8903 (match_operand 1 "" ""))
8904 (clobber (reg:DI PR_MEDIA_REG))]
8905 "TARGET_SHMEDIA"
2ad65b0e
SC
8906 "blink %0, r18"
8907 [(set_attr "type" "jump_media")])
fa5322fa 8908
bc45ade3
SC
8909(define_insn "call_valuei"
8910 [(set (match_operand 0 "" "=rf")
aa684c94 8911 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
bc45ade3 8912 (match_operand 2 "" "")))
5d00b10a 8913 (use (reg:PSI FPSCR_REG))
4773afa4 8914 (clobber (reg:SI PR_REG))]
fa5322fa 8915 "TARGET_SH1"
d9241861
OE
8916{
8917 if (TARGET_SH2A && (dbr_sequence_length () == 0))
35ed5a70 8918 return "jsr/n @%1";
d9241861 8919 else
35ed5a70 8920 return "jsr @%1%#";
d9241861 8921}
ffae286a 8922 [(set_attr "type" "call")
d64264ff
R
8923 (set (attr "fp_mode")
8924 (if_then_else (eq_attr "fpu_single" "yes")
8925 (const_string "single") (const_string "double")))
73774972
EC
8926 (set_attr "needs_delay_slot" "yes")
8927 (set_attr "fp_set" "unknown")])
bc45ade3 8928
561642fa 8929;; This is TBR relative jump instruction for SH2A architecture.
2eff0b9d 8930;; Its use is enabled by assigning an attribute "function_vector"
561642fa
AP
8931;; and the vector number to a function during its declaration.
8932
8933(define_insn "call_valuei_tbr_rel"
8934 [(set (match_operand 0 "" "=rf")
8935 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8936 (match_operand 2 "" "")))
8937 (use (reg:PSI FPSCR_REG))
8938 (clobber (reg:SI PR_REG))]
8939 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
561642fa
AP
8940{
8941 unsigned HOST_WIDE_INT vect_num;
8942 vect_num = sh2a_get_function_vector_number (operands[1]);
8943 operands[3] = GEN_INT (vect_num * 4);
8944
35ed5a70 8945 return "jsr/n @@(%O3,tbr)";
d9241861 8946}
561642fa
AP
8947 [(set_attr "type" "call")
8948 (set (attr "fp_mode")
8949 (if_then_else (eq_attr "fpu_single" "yes")
8950 (const_string "single") (const_string "double")))
8951 (set_attr "needs_delay_slot" "no")
8952 (set_attr "fp_set" "unknown")])
8953
1a66cd67
AO
8954(define_insn "call_valuei_pcrel"
8955 [(set (match_operand 0 "" "=rf")
8956 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8957 (match_operand 2 "" "")))
5d00b10a 8958 (use (reg:PSI FPSCR_REG))
2d01e445 8959 (use (reg:SI PIC_REG))
1a66cd67 8960 (use (match_operand 3 "" ""))
4773afa4 8961 (clobber (reg:SI PR_REG))]
eb69f95c 8962 "TARGET_SH2"
35ed5a70
OE
8963{
8964 return "bsrf %1" "\n"
8965 "%O3:%#";
8966}
1a66cd67
AO
8967 [(set_attr "type" "call")
8968 (set (attr "fp_mode")
8969 (if_then_else (eq_attr "fpu_single" "yes")
8970 (const_string "single") (const_string "double")))
73774972
EC
8971 (set_attr "needs_delay_slot" "yes")
8972 (set_attr "fp_set" "unknown")])
1a66cd67 8973
2d01e445
AO
8974(define_insn_and_split "call_value_pcrel"
8975 [(set (match_operand 0 "" "=rf")
8976 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8977 (match_operand 2 "" "")))
8978 (use (reg:PSI FPSCR_REG))
8979 (use (reg:SI PIC_REG))
8980 (clobber (reg:SI PR_REG))
8981 (clobber (match_scratch:SI 3 "=r"))]
cb51ecd2 8982 "TARGET_SH2"
2d01e445
AO
8983 "#"
8984 "reload_completed"
8985 [(const_int 0)]
2d01e445 8986{
8e831557 8987 rtx lab = PATTERN (gen_call_site ());
2d01e445 8988
675ff4c7 8989 if (SYMBOL_REF_LOCAL_P (operands[1]))
2d01e445
AO
8990 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
8991 else
8992 emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
8993 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
329b3cc3 8994 operands[2], copy_rtx (lab)));
2d01e445 8995 DONE;
d9241861 8996}
2d01e445
AO
8997 [(set_attr "type" "call")
8998 (set (attr "fp_mode")
8999 (if_then_else (eq_attr "fpu_single" "yes")
9000 (const_string "single") (const_string "double")))
73774972
EC
9001 (set_attr "needs_delay_slot" "yes")
9002 (set_attr "fp_set" "unknown")])
2d01e445 9003
fa5322fa
AO
9004(define_insn "call_value_compact"
9005 [(set (match_operand 0 "" "=rf")
9006 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9007 (match_operand 2 "" "")))
9008 (match_operand 3 "immediate_operand" "n")
9009 (use (reg:SI R0_REG))
9010 (use (reg:SI R1_REG))
9011 (use (reg:PSI FPSCR_REG))
9012 (clobber (reg:SI PR_REG))]
9013 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9014 "jsr @%1%#"
9015 [(set_attr "type" "call")
9016 (set (attr "fp_mode")
9017 (if_then_else (eq_attr "fpu_single" "yes")
9018 (const_string "single") (const_string "double")))
9019 (set_attr "needs_delay_slot" "yes")])
9020
9021(define_insn "call_value_compact_rettramp"
9022 [(set (match_operand 0 "" "=rf")
9023 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9024 (match_operand 2 "" "")))
9025 (match_operand 3 "immediate_operand" "n")
9026 (use (reg:SI R0_REG))
9027 (use (reg:SI R1_REG))
9028 (use (reg:PSI FPSCR_REG))
9029 (clobber (reg:SI R10_REG))
9030 (clobber (reg:SI PR_REG))]
9031 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9032 "jsr @%1%#"
9033 [(set_attr "type" "call")
9034 (set (attr "fp_mode")
9035 (if_then_else (eq_attr "fpu_single" "yes")
9036 (const_string "single") (const_string "double")))
9037 (set_attr "needs_delay_slot" "yes")])
9038
9039(define_insn "call_value_media"
9040 [(set (match_operand 0 "" "=rf")
73a4d10b 9041 (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
fa5322fa
AO
9042 (match_operand 2 "" "")))
9043 (clobber (reg:DI PR_MEDIA_REG))]
9044 "TARGET_SHMEDIA"
2ad65b0e
SC
9045 "blink %1, r18"
9046 [(set_attr "type" "jump_media")])
fa5322fa 9047
bc45ade3 9048(define_expand "call"
51aea58d
JW
9049 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9050 (match_operand 1 "" ""))
fa5322fa 9051 (match_operand 2 "" "")
5d00b10a 9052 (use (reg:PSI FPSCR_REG))
4773afa4 9053 (clobber (reg:SI PR_REG))])]
bc45ade3 9054 ""
827bdee4 9055{
fa5322fa
AO
9056 if (TARGET_SHMEDIA)
9057 {
73a4d10b 9058 operands[0] = shmedia_prepare_call_address (operands[0], 0);
fa5322fa
AO
9059 emit_call_insn (gen_call_media (operands[0], operands[1]));
9060 DONE;
9061 }
9062 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9063 {
9064 rtx cookie_rtx = operands[2];
9065 long cookie = INTVAL (cookie_rtx);
9066 rtx func = XEXP (operands[0], 0);
9067 rtx r0, r1;
9068
9069 if (flag_pic)
9070 {
675ff4c7 9071 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
fa5322fa
AO
9072 {
9073 rtx reg = gen_reg_rtx (Pmode);
9074
9075 emit_insn (gen_symGOTPLT2reg (reg, func));
9076 func = reg;
9077 }
9078 else
9079 func = legitimize_pic_address (func, Pmode, 0);
9080 }
9081
9082 r0 = gen_rtx_REG (SImode, R0_REG);
9083 r1 = gen_rtx_REG (SImode, R1_REG);
9084
9085 /* Since such a call function may use all call-clobbered
9086 registers, we force a mode switch earlier, so that we don't
9087 run out of registers when adjusting fpscr for the call. */
9088 emit_insn (gen_force_mode_for_call ());
9089
73a4d10b 9090 operands[0]
d9241861 9091 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
fa5322fa
AO
9092 operands[0] = force_reg (SImode, operands[0]);
9093
9094 emit_move_insn (r0, func);
9095 emit_move_insn (r1, cookie_rtx);
9096
9097 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9098 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9099 operands[2]));
9100 else
9101 emit_call_insn (gen_call_compact (operands[0], operands[1],
9102 operands[2]));
9103
9104 DONE;
9105 }
9106 else if (TARGET_SHCOMPACT && flag_pic
9107 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
675ff4c7 9108 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
fa5322fa
AO
9109 {
9110 rtx reg = gen_reg_rtx (Pmode);
9111
9112 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9113 XEXP (operands[0], 0) = reg;
9114 }
561642fa 9115 if (!flag_pic && TARGET_SH2A
f3536097 9116 && MEM_P (operands[0])
561642fa
AP
9117 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9118 {
9119 if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9120 {
9121 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9122 operands[1]));
9123 DONE;
9124 }
9125 }
cb51ecd2 9126 if (flag_pic && TARGET_SH2
f3536097 9127 && MEM_P (operands[0])
827bdee4
AO
9128 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9129 {
2d01e445 9130 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
827bdee4
AO
9131 DONE;
9132 }
9133 else
61f71b34 9134 {
827bdee4 9135 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
61f71b34
DD
9136 operands[1] = operands[2];
9137 }
fa5322fa
AO
9138
9139 emit_call_insn (gen_calli (operands[0], operands[1]));
9140 DONE;
d9241861 9141})
fa5322fa
AO
9142
9143(define_insn "call_pop_compact"
9144 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9145 (match_operand 1 "" ""))
9146 (match_operand 2 "immediate_operand" "n")
9147 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9148 (match_operand 3 "immediate_operand" "n")))
9149 (use (reg:SI R0_REG))
9150 (use (reg:SI R1_REG))
9151 (use (reg:PSI FPSCR_REG))
9152 (clobber (reg:SI PR_REG))]
9153 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9154 "jsr @%0%#"
9155 [(set_attr "type" "call")
9156 (set (attr "fp_mode")
9157 (if_then_else (eq_attr "fpu_single" "yes")
9158 (const_string "single") (const_string "double")))
9159 (set_attr "needs_delay_slot" "yes")])
9160
9161(define_insn "call_pop_compact_rettramp"
9162 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9163 (match_operand 1 "" ""))
9164 (match_operand 2 "immediate_operand" "n")
9165 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9166 (match_operand 3 "immediate_operand" "n")))
9167 (use (reg:SI R0_REG))
9168 (use (reg:SI R1_REG))
9169 (use (reg:PSI FPSCR_REG))
9170 (clobber (reg:SI R10_REG))
9171 (clobber (reg:SI PR_REG))]
9172 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9173 "jsr @%0%#"
9174 [(set_attr "type" "call")
9175 (set (attr "fp_mode")
9176 (if_then_else (eq_attr "fpu_single" "yes")
9177 (const_string "single") (const_string "double")))
9178 (set_attr "needs_delay_slot" "yes")])
9179
9180(define_expand "call_pop"
9181 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9182 (match_operand 1 "" ""))
9183 (match_operand 2 "" "")
9184 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9185 (match_operand 3 "" "")))])]
9186 "TARGET_SHCOMPACT"
fa5322fa 9187{
f5b9e7c9
NS
9188 rtx cookie_rtx;
9189 long cookie;
9190 rtx func;
9191 rtx r0, r1;
fa5322fa 9192
f5b9e7c9
NS
9193 gcc_assert (operands[2] && INTVAL (operands[2]));
9194 cookie_rtx = operands[2];
9195 cookie = INTVAL (cookie_rtx);
9196 func = XEXP (operands[0], 0);
fa5322fa 9197
f5b9e7c9
NS
9198 if (flag_pic)
9199 {
9200 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9201 {
9202 rtx reg = gen_reg_rtx (Pmode);
9203 emit_insn (gen_symGOTPLT2reg (reg, func));
9204 func = reg;
fa5322fa 9205 }
f5b9e7c9
NS
9206 else
9207 func = legitimize_pic_address (func, Pmode, 0);
9208 }
fa5322fa 9209
f5b9e7c9
NS
9210 r0 = gen_rtx_REG (SImode, R0_REG);
9211 r1 = gen_rtx_REG (SImode, R1_REG);
fa5322fa 9212
f5b9e7c9
NS
9213 /* Since such a call function may use all call-clobbered
9214 registers, we force a mode switch earlier, so that we don't
9215 run out of registers when adjusting fpscr for the call. */
9216 emit_insn (gen_force_mode_for_call ());
fa5322fa 9217
d9241861 9218 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
73a4d10b 9219 SFUNC_GOT);
f5b9e7c9 9220 operands[0] = force_reg (SImode, operands[0]);
fa5322fa 9221
f5b9e7c9
NS
9222 emit_move_insn (r0, func);
9223 emit_move_insn (r1, cookie_rtx);
fa5322fa 9224
f5b9e7c9
NS
9225 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9226 emit_call_insn (gen_call_pop_compact_rettramp
9227 (operands[0], operands[1], operands[2], operands[3]));
9228 else
9229 emit_call_insn (gen_call_pop_compact
9230 (operands[0], operands[1], operands[2], operands[3]));
fa5322fa 9231
f5b9e7c9 9232 DONE;
d9241861 9233})
bc45ade3
SC
9234
9235(define_expand "call_value"
51aea58d
JW
9236 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9237 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9238 (match_operand 2 "" "")))
fa5322fa 9239 (match_operand 3 "" "")
5d00b10a 9240 (use (reg:PSI FPSCR_REG))
4773afa4 9241 (clobber (reg:SI PR_REG))])]
bc45ade3 9242 ""
827bdee4 9243{
fa5322fa
AO
9244 if (TARGET_SHMEDIA)
9245 {
73a4d10b 9246 operands[1] = shmedia_prepare_call_address (operands[1], 0);
fa5322fa
AO
9247 emit_call_insn (gen_call_value_media (operands[0], operands[1],
9248 operands[2]));
9249 DONE;
9250 }
9251 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9252 {
9253 rtx cookie_rtx = operands[3];
9254 long cookie = INTVAL (cookie_rtx);
9255 rtx func = XEXP (operands[1], 0);
9256 rtx r0, r1;
9257
9258 if (flag_pic)
9259 {
675ff4c7 9260 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
fa5322fa
AO
9261 {
9262 rtx reg = gen_reg_rtx (Pmode);
9263
9264 emit_insn (gen_symGOTPLT2reg (reg, func));
9265 func = reg;
9266 }
9267 else
9268 func = legitimize_pic_address (func, Pmode, 0);
9269 }
9270
9271 r0 = gen_rtx_REG (SImode, R0_REG);
9272 r1 = gen_rtx_REG (SImode, R1_REG);
9273
9274 /* Since such a call function may use all call-clobbered
9275 registers, we force a mode switch earlier, so that we don't
9276 run out of registers when adjusting fpscr for the call. */
9277 emit_insn (gen_force_mode_for_call ());
9278
73a4d10b 9279 operands[1]
d9241861 9280 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
fa5322fa
AO
9281 operands[1] = force_reg (SImode, operands[1]);
9282
9283 emit_move_insn (r0, func);
9284 emit_move_insn (r1, cookie_rtx);
9285
9286 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9287 emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9288 operands[1],
9289 operands[2],
9290 operands[3]));
9291 else
9292 emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9293 operands[2], operands[3]));
9294
9295 DONE;
9296 }
9297 else if (TARGET_SHCOMPACT && flag_pic
9298 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
675ff4c7 9299 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
fa5322fa
AO
9300 {
9301 rtx reg = gen_reg_rtx (Pmode);
9302
9303 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9304 XEXP (operands[1], 0) = reg;
9305 }
561642fa 9306 if (!flag_pic && TARGET_SH2A
f3536097 9307 && MEM_P (operands[1])
561642fa
AP
9308 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9309 {
9310 if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9311 {
9312 emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9313 XEXP (operands[1], 0), operands[2]));
9314 DONE;
9315 }
9316 }
cb51ecd2 9317 if (flag_pic && TARGET_SH2
f3536097 9318 && MEM_P (operands[1])
827bdee4
AO
9319 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9320 {
2d01e445
AO
9321 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
9322 operands[2]));
827bdee4
AO
9323 DONE;
9324 }
9325 else
9326 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
fa5322fa
AO
9327
9328 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
9329 DONE;
d9241861 9330})
bc45ade3 9331
5db5a888 9332(define_insn "sibcalli"
cb51ecd2 9333 [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
5db5a888
AO
9334 (match_operand 1 "" ""))
9335 (use (reg:PSI FPSCR_REG))
9336 (return)]
fa5322fa 9337 "TARGET_SH1"
5db5a888
AO
9338 "jmp @%0%#"
9339 [(set_attr "needs_delay_slot" "yes")
cc0744d1
AO
9340 (set (attr "fp_mode")
9341 (if_then_else (eq_attr "fpu_single" "yes")
9342 (const_string "single") (const_string "double")))
5db5a888
AO
9343 (set_attr "type" "jump_ind")])
9344
9345(define_insn "sibcalli_pcrel"
cb51ecd2 9346 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
5db5a888
AO
9347 (match_operand 1 "" ""))
9348 (use (match_operand 2 "" ""))
9349 (use (reg:PSI FPSCR_REG))
9350 (return)]
9351 "TARGET_SH2"
35ed5a70
OE
9352{
9353 return "braf %0" "\n"
9354 "%O2:%#";
9355}
5db5a888 9356 [(set_attr "needs_delay_slot" "yes")
cc0744d1
AO
9357 (set (attr "fp_mode")
9358 (if_then_else (eq_attr "fpu_single" "yes")
9359 (const_string "single") (const_string "double")))
5db5a888
AO
9360 (set_attr "type" "jump_ind")])
9361
73a4d10b
R
9362;; This uses an unspec to describe that the symbol_ref is very close.
9363(define_insn "sibcalli_thunk"
9364 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
9365 UNSPEC_THUNK))
9366 (match_operand 1 "" ""))
9367 (use (reg:PSI FPSCR_REG))
9368 (return)]
9369 "TARGET_SH1"
9370 "bra %O0"
9371 [(set_attr "needs_delay_slot" "yes")
9372 (set (attr "fp_mode")
9373 (if_then_else (eq_attr "fpu_single" "yes")
9374 (const_string "single") (const_string "double")))
9375 (set_attr "type" "jump")
9376 (set_attr "length" "2")])
9377
5db5a888
AO
9378(define_insn_and_split "sibcall_pcrel"
9379 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9380 (match_operand 1 "" ""))
9381 (use (reg:PSI FPSCR_REG))
cb51ecd2 9382 (clobber (match_scratch:SI 2 "=k"))
5db5a888 9383 (return)]
cb51ecd2 9384 "TARGET_SH2"
5db5a888
AO
9385 "#"
9386 "reload_completed"
9387 [(const_int 0)]
5db5a888 9388{
8e831557 9389 rtx lab = PATTERN (gen_call_site ());
5db5a888
AO
9390 rtx call_insn;
9391
fa5322fa
AO
9392 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9393 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
329b3cc3 9394 copy_rtx (lab)));
fa5322fa
AO
9395 SIBLING_CALL_P (call_insn) = 1;
9396 DONE;
d9241861 9397}
fa5322fa
AO
9398 [(set_attr "needs_delay_slot" "yes")
9399 (set (attr "fp_mode")
9400 (if_then_else (eq_attr "fpu_single" "yes")
9401 (const_string "single") (const_string "double")))
9402 (set_attr "type" "jump_ind")])
9403
9404(define_insn "sibcall_compact"
9405 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
9406 (match_operand 1 "" ""))
9407 (return)
e69d1422 9408 (use (match_operand:SI 2 "register_operand" "z,x"))
fa5322fa
AO
9409 (use (reg:SI R1_REG))
9410 (use (reg:PSI FPSCR_REG))
9411 ;; We want to make sure the `x' above will only match MACH_REG
9412 ;; because sibcall_epilogue may clobber MACL_REG.
9413 (clobber (reg:SI MACL_REG))]
9414 "TARGET_SHCOMPACT"
35ed5a70
OE
9415{
9416 static const char* alt[] =
9417 {
9418 "jmp @%0%#",
9419
9420 "jmp @%0" "\n"
9421 " sts %2,r0"
9422 };
9423 return alt[which_alternative];
9424}
fa5322fa
AO
9425 [(set_attr "needs_delay_slot" "yes,no")
9426 (set_attr "length" "2,4")
9427 (set (attr "fp_mode") (const_string "single"))
9428 (set_attr "type" "jump_ind")])
9429
9430(define_insn "sibcall_media"
73a4d10b 9431 [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
fa5322fa 9432 (match_operand 1 "" ""))
7d73a2ba 9433 (use (reg:SI PR_MEDIA_REG))
fa5322fa
AO
9434 (return)]
9435 "TARGET_SHMEDIA"
2ad65b0e
SC
9436 "blink %0, r63"
9437 [(set_attr "type" "jump_media")])
fa5322fa
AO
9438
9439(define_expand "sibcall"
9440 [(parallel
9441 [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9442 (match_operand 1 "" ""))
9443 (match_operand 2 "" "")
9444 (use (reg:PSI FPSCR_REG))
9445 (return)])]
9446 ""
fa5322fa
AO
9447{
9448 if (TARGET_SHMEDIA)
9449 {
73a4d10b 9450 operands[0] = shmedia_prepare_call_address (operands[0], 1);
fa5322fa
AO
9451 emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
9452 DONE;
9453 }
9454 else if (TARGET_SHCOMPACT && operands[2]
9455 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9456 {
9457 rtx cookie_rtx = operands[2];
9458 long cookie = INTVAL (cookie_rtx);
9459 rtx func = XEXP (operands[0], 0);
9460 rtx mach, r1;
9461
9462 if (flag_pic)
9463 {
675ff4c7 9464 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
fa5322fa
AO
9465 {
9466 rtx reg = gen_reg_rtx (Pmode);
9467
9468 emit_insn (gen_symGOT2reg (reg, func));
9469 func = reg;
9470 }
9471 else
9472 func = legitimize_pic_address (func, Pmode, 0);
9473 }
5db5a888 9474
fa5322fa
AO
9475 /* FIXME: if we could tell whether all argument registers are
9476 already taken, we could decide whether to force the use of
9477 MACH_REG or to stick to R0_REG. Unfortunately, there's no
9478 simple way to tell. We could use the CALL_COOKIE, but we
9479 can't currently tell a register used for regular argument
9480 passing from one that is unused. If we leave it up to reload
9481 to decide which register to use, it seems to always choose
9482 R0_REG, which leaves no available registers in SIBCALL_REGS
9483 to hold the address of the trampoline. */
9484 mach = gen_rtx_REG (SImode, MACH_REG);
9485 r1 = gen_rtx_REG (SImode, R1_REG);
9486
9487 /* Since such a call function may use all call-clobbered
9488 registers, we force a mode switch earlier, so that we don't
9489 run out of registers when adjusting fpscr for the call. */
9490 emit_insn (gen_force_mode_for_call ());
9491
73a4d10b 9492 operands[0]
d9241861 9493 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
fa5322fa
AO
9494 operands[0] = force_reg (SImode, operands[0]);
9495
9496 /* We don't need a return trampoline, since the callee will
9497 return directly to the upper caller. */
9498 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9499 {
9500 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9501 cookie_rtx = GEN_INT (cookie);
9502 }
9503
9504 emit_move_insn (mach, func);
9505 emit_move_insn (r1, cookie_rtx);
9506
9507 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
9508 DONE;
9509 }
9510 else if (TARGET_SHCOMPACT && flag_pic
9511 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
675ff4c7 9512 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
fa5322fa
AO
9513 {
9514 rtx reg = gen_reg_rtx (Pmode);
9515
9516 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
9517 XEXP (operands[0], 0) = reg;
9518 }
cb51ecd2 9519 if (flag_pic && TARGET_SH2
f3536097 9520 && MEM_P (operands[0])
5db5a888
AO
9521 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9522 /* The PLT needs the PIC register, but the epilogue would have
9523 to restore it, so we can only use PC-relative PIC calls for
9524 static functions. */
675ff4c7 9525 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
5db5a888
AO
9526 {
9527 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
9528 DONE;
9529 }
9530 else
9531 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
fa5322fa
AO
9532
9533 emit_call_insn (gen_sibcalli (operands[0], operands[1]));
9534 DONE;
d9241861 9535})
5db5a888 9536
6fb5fa3c
DB
9537(define_insn "sibcall_valuei"
9538 [(set (match_operand 0 "" "=rf")
9539 (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
9540 (match_operand 2 "" "")))
9541 (use (reg:PSI FPSCR_REG))
9542 (return)]
9543 "TARGET_SH1"
9544 "jmp @%1%#"
9545 [(set_attr "needs_delay_slot" "yes")
9546 (set (attr "fp_mode")
9547 (if_then_else (eq_attr "fpu_single" "yes")
9548 (const_string "single") (const_string "double")))
9549 (set_attr "type" "jump_ind")])
9550
9551(define_insn "sibcall_valuei_pcrel"
9552 [(set (match_operand 0 "" "=rf")
9553 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
9554 (match_operand 2 "" "")))
9555 (use (match_operand 3 "" ""))
9556 (use (reg:PSI FPSCR_REG))
9557 (return)]
9558 "TARGET_SH2"
35ed5a70
OE
9559{
9560 return "braf %1" "\n"
9561 "%O3:%#";
9562}
6fb5fa3c
DB
9563 [(set_attr "needs_delay_slot" "yes")
9564 (set (attr "fp_mode")
9565 (if_then_else (eq_attr "fpu_single" "yes")
9566 (const_string "single") (const_string "double")))
9567 (set_attr "type" "jump_ind")])
9568
9569(define_insn_and_split "sibcall_value_pcrel"
9570 [(set (match_operand 0 "" "=rf")
9571 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
fa5322fa 9572 (match_operand 2 "" "")))
6fb5fa3c
DB
9573 (use (reg:PSI FPSCR_REG))
9574 (clobber (match_scratch:SI 3 "=k"))
9575 (return)]
9576 "TARGET_SH2"
9577 "#"
9578 "reload_completed"
9579 [(const_int 0)]
6fb5fa3c
DB
9580{
9581 rtx lab = PATTERN (gen_call_site ());
9582 rtx call_insn;
9583
9584 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9585 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
9586 operands[3],
9587 operands[2],
9588 copy_rtx (lab)));
9589 SIBLING_CALL_P (call_insn) = 1;
9590 DONE;
d9241861 9591}
6fb5fa3c
DB
9592 [(set_attr "needs_delay_slot" "yes")
9593 (set (attr "fp_mode")
9594 (if_then_else (eq_attr "fpu_single" "yes")
9595 (const_string "single") (const_string "double")))
9596 (set_attr "type" "jump_ind")])
9597
9598(define_insn "sibcall_value_compact"
9599 [(set (match_operand 0 "" "=rf,rf")
9600 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
9601 (match_operand 2 "" "")))
9602 (return)
9603 (use (match_operand:SI 3 "register_operand" "z,x"))
9604 (use (reg:SI R1_REG))
9605 (use (reg:PSI FPSCR_REG))
9606 ;; We want to make sure the `x' above will only match MACH_REG
9607 ;; because sibcall_epilogue may clobber MACL_REG.
9608 (clobber (reg:SI MACL_REG))]
9609 "TARGET_SHCOMPACT"
35ed5a70
OE
9610{
9611 static const char* alt[] =
9612 {
9613 "jmp @%1%#",
9614
9615 "jmp @%1" "\n"
9616 " sts %3,r0"
9617 };
9618 return alt[which_alternative];
9619}
6fb5fa3c
DB
9620 [(set_attr "needs_delay_slot" "yes,no")
9621 (set_attr "length" "2,4")
9622 (set (attr "fp_mode") (const_string "single"))
9623 (set_attr "type" "jump_ind")])
9624
9625(define_insn "sibcall_value_media"
9626 [(set (match_operand 0 "" "=rf")
9627 (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
9628 (match_operand 2 "" "")))
9629 (use (reg:SI PR_MEDIA_REG))
9630 (return)]
9631 "TARGET_SHMEDIA"
9632 "blink %1, r63"
9633 [(set_attr "type" "jump_media")])
9634
9635(define_expand "sibcall_value"
9636 [(parallel
9637 [(set (match_operand 0 "arith_reg_operand" "")
9638 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9639 (match_operand 2 "" "")))
9640 (match_operand 3 "" "")
9641 (use (reg:PSI FPSCR_REG))
9642 (return)])]
5db5a888 9643 ""
5db5a888 9644{
6fb5fa3c
DB
9645 if (TARGET_SHMEDIA)
9646 {
9647 operands[1] = shmedia_prepare_call_address (operands[1], 1);
9648 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
9649 operands[2]));
9650 DONE;
9651 }
9652 else if (TARGET_SHCOMPACT && operands[3]
9653 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9654 {
9655 rtx cookie_rtx = operands[3];
9656 long cookie = INTVAL (cookie_rtx);
9657 rtx func = XEXP (operands[1], 0);
9658 rtx mach, r1;
9659
9660 if (flag_pic)
9661 {
9662 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9663 {
9664 rtx reg = gen_reg_rtx (Pmode);
9665
9666 emit_insn (gen_symGOT2reg (reg, func));
9667 func = reg;
9668 }
9669 else
9670 func = legitimize_pic_address (func, Pmode, 0);
9671 }
9672
9673 /* FIXME: if we could tell whether all argument registers are
9674 already taken, we could decide whether to force the use of
9675 MACH_REG or to stick to R0_REG. Unfortunately, there's no
9676 simple way to tell. We could use the CALL_COOKIE, but we
9677 can't currently tell a register used for regular argument
9678 passing from one that is unused. If we leave it up to reload
9679 to decide which register to use, it seems to always choose
9680 R0_REG, which leaves no available registers in SIBCALL_REGS
9681 to hold the address of the trampoline. */
9682 mach = gen_rtx_REG (SImode, MACH_REG);
9683 r1 = gen_rtx_REG (SImode, R1_REG);
9684
9685 /* Since such a call function may use all call-clobbered
9686 registers, we force a mode switch earlier, so that we don't
9687 run out of registers when adjusting fpscr for the call. */
9688 emit_insn (gen_force_mode_for_call ());
9689
9690 operands[1]
d9241861 9691 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
6fb5fa3c
DB
9692 operands[1] = force_reg (SImode, operands[1]);
9693
9694 /* We don't need a return trampoline, since the callee will
9695 return directly to the upper caller. */
9696 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9697 {
9698 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9699 cookie_rtx = GEN_INT (cookie);
9700 }
9701
9702 emit_move_insn (mach, func);
9703 emit_move_insn (r1, cookie_rtx);
9704
9705 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
9706 operands[2], mach));
9707 DONE;
9708 }
9709 else if (TARGET_SHCOMPACT && flag_pic
9710 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9711 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9712 {
9713 rtx reg = gen_reg_rtx (Pmode);
9714
9715 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
9716 XEXP (operands[1], 0) = reg;
9717 }
9718 if (flag_pic && TARGET_SH2
f3536097 9719 && MEM_P (operands[1])
6fb5fa3c
DB
9720 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9721 /* The PLT needs the PIC register, but the epilogue would have
9722 to restore it, so we can only use PC-relative PIC calls for
9723 static functions. */
9724 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9725 {
9726 emit_call_insn (gen_sibcall_value_pcrel (operands[0],
9727 XEXP (operands[1], 0),
9728 operands[2]));
9729 DONE;
9730 }
9731 else
9732 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9733
9734 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
5db5a888 9735 DONE;
d9241861 9736})
5db5a888 9737
fa5322fa
AO
9738(define_insn "call_value_pop_compact"
9739 [(set (match_operand 0 "" "=rf")
9740 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9741 (match_operand 2 "" "")))
9742 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9743 (match_operand 4 "immediate_operand" "n")))
9744 (match_operand 3 "immediate_operand" "n")
9745 (use (reg:SI R0_REG))
9746 (use (reg:SI R1_REG))
9747 (use (reg:PSI FPSCR_REG))
9748 (clobber (reg:SI PR_REG))]
9749 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9750 "jsr @%1%#"
9751 [(set_attr "type" "call")
9752 (set (attr "fp_mode")
9753 (if_then_else (eq_attr "fpu_single" "yes")
9754 (const_string "single") (const_string "double")))
9755 (set_attr "needs_delay_slot" "yes")])
9756
9757(define_insn "call_value_pop_compact_rettramp"
9758 [(set (match_operand 0 "" "=rf")
9759 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9760 (match_operand 2 "" "")))
9761 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9762 (match_operand 4 "immediate_operand" "n")))
9763 (match_operand 3 "immediate_operand" "n")
9764 (use (reg:SI R0_REG))
9765 (use (reg:SI R1_REG))
9766 (use (reg:PSI FPSCR_REG))
9767 (clobber (reg:SI R10_REG))
9768 (clobber (reg:SI PR_REG))]
9769 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9770 "jsr @%1%#"
9771 [(set_attr "type" "call")
9772 (set (attr "fp_mode")
9773 (if_then_else (eq_attr "fpu_single" "yes")
9774 (const_string "single") (const_string "double")))
9775 (set_attr "needs_delay_slot" "yes")])
9776
9777(define_expand "call_value_pop"
9778 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9779 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9780 (match_operand 2 "" "")))
9781 (match_operand 3 "" "")
9782 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9783 (match_operand 4 "" "")))])]
9784 "TARGET_SHCOMPACT"
fa5322fa 9785{
f5b9e7c9
NS
9786 rtx cookie_rtx;
9787 long cookie;
9788 rtx func;
9789 rtx r0, r1;
fa5322fa 9790
f5b9e7c9
NS
9791 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
9792 cookie_rtx = operands[3];
9793 cookie = INTVAL (cookie_rtx);
9794 func = XEXP (operands[1], 0);
fa5322fa 9795
f5b9e7c9
NS
9796 if (flag_pic)
9797 {
9798 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9799 {
9800 rtx reg = gen_reg_rtx (Pmode);
fa5322fa 9801
f5b9e7c9
NS
9802 emit_insn (gen_symGOTPLT2reg (reg, func));
9803 func = reg;
9804 }
9805 else
9806 func = legitimize_pic_address (func, Pmode, 0);
9807 }
fa5322fa 9808
f5b9e7c9
NS
9809 r0 = gen_rtx_REG (SImode, R0_REG);
9810 r1 = gen_rtx_REG (SImode, R1_REG);
fa5322fa 9811
f5b9e7c9
NS
9812 /* Since such a call function may use all call-clobbered
9813 registers, we force a mode switch earlier, so that we don't
9814 run out of registers when adjusting fpscr for the call. */
9815 emit_insn (gen_force_mode_for_call ());
fa5322fa 9816
d9241861 9817 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
73a4d10b 9818 SFUNC_GOT);
f5b9e7c9 9819 operands[1] = force_reg (SImode, operands[1]);
fa5322fa 9820
f5b9e7c9
NS
9821 emit_move_insn (r0, func);
9822 emit_move_insn (r1, cookie_rtx);
9823
9824 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9825 emit_call_insn (gen_call_value_pop_compact_rettramp
fa5322fa
AO
9826 (operands[0], operands[1], operands[2],
9827 operands[3], operands[4]));
f5b9e7c9
NS
9828 else
9829 emit_call_insn (gen_call_value_pop_compact
fa5322fa
AO
9830 (operands[0], operands[1], operands[2],
9831 operands[3], operands[4]));
9832
f5b9e7c9 9833 DONE;
d9241861 9834})
fa5322fa 9835
5db5a888
AO
9836(define_expand "sibcall_epilogue"
9837 [(return)]
9838 ""
5db5a888 9839{
fcf8632e 9840 sh_expand_epilogue (true);
fa5322fa
AO
9841 if (TARGET_SHCOMPACT)
9842 {
9843 rtx insn, set;
9844
9845 /* If epilogue clobbers r0, preserve it in macl. */
9846 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
9847 if ((set = single_set (insn))
f3536097 9848 && REG_P (SET_DEST (set))
fa5322fa
AO
9849 && REGNO (SET_DEST (set)) == R0_REG)
9850 {
9851 rtx r0 = gen_rtx_REG (SImode, R0_REG);
9852 rtx tmp = gen_rtx_REG (SImode, MACL_REG);
fa5322fa
AO
9853
9854 /* We can't tell at this point whether the sibcall is a
9855 sibcall_compact and, if it is, whether it uses r0 or
9856 mach as operand 2, so let the instructions that
9857 preserve r0 be optimized away if r0 turns out to be
9858 dead. */
6fb5fa3c
DB
9859 emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
9860 emit_move_insn (r0, tmp);
fa5322fa
AO
9861 break;
9862 }
9863 }
5db5a888 9864 DONE;
d9241861 9865})
5db5a888 9866
fa5322fa 9867(define_insn "indirect_jump_compact"
bc45ade3 9868 [(set (pc)
aa684c94 9869 (match_operand:SI 0 "arith_reg_operand" "r"))]
fa5322fa 9870 "TARGET_SH1"
b9654711 9871 "jmp @%0%#"
1245df60
R
9872 [(set_attr "needs_delay_slot" "yes")
9873 (set_attr "type" "jump_ind")])
a1a0806a 9874
fa5322fa
AO
9875(define_expand "indirect_jump"
9876 [(set (pc)
9877 (match_operand 0 "register_operand" ""))]
9878 ""
fa5322fa 9879{
73a4d10b
R
9880 if (GET_MODE (operands[0]) != Pmode)
9881 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
d9241861 9882})
fa5322fa 9883
1245df60 9884;; The use of operand 1 / 2 helps us distinguish case table jumps
f1ffca1c
JW
9885;; which can be present in structured code from indirect jumps which can not
9886;; be present in structured code. This allows -fprofile-arcs to work.
9887
1245df60
R
9888;; For SH1 processors.
9889(define_insn "casesi_jump_1"
f1ffca1c 9890 [(set (pc)
1245df60 9891 (match_operand:SI 0 "register_operand" "r"))
f1ffca1c 9892 (use (label_ref (match_operand 1 "" "")))]
fa5322fa 9893 "TARGET_SH1"
1245df60
R
9894 "jmp @%0%#"
9895 [(set_attr "needs_delay_slot" "yes")
9896 (set_attr "type" "jump_ind")])
9897
9898;; For all later processors.
9899(define_insn "casesi_jump_2"
9900 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
eb3881bf 9901 (label_ref (match_operand 1 "" ""))))
1245df60 9902 (use (label_ref (match_operand 2 "" "")))]
e6dfd05f
AO
9903 "TARGET_SH2
9904 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
1245df60
R
9905 "braf %0%#"
9906 [(set_attr "needs_delay_slot" "yes")
9907 (set_attr "type" "jump_ind")])
9908
fa5322fa 9909(define_insn "casesi_jump_media"
73a4d10b 9910 [(set (pc) (match_operand 0 "target_reg_operand" "b"))
fa5322fa
AO
9911 (use (label_ref (match_operand 1 "" "")))]
9912 "TARGET_SHMEDIA"
2ad65b0e
SC
9913 "blink %0, r63"
9914 [(set_attr "type" "jump_media")])
52702ae1 9915
a1a0806a
JW
9916;; Call subroutine returning any type.
9917;; ??? This probably doesn't work.
9918
9919(define_expand "untyped_call"
9920 [(parallel [(call (match_operand 0 "" "")
9921 (const_int 0))
9922 (match_operand 1 "" "")
9923 (match_operand 2 "" "")])]
157371cf 9924 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
a1a0806a
JW
9925{
9926 int i;
9927
fa5322fa 9928 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
a1a0806a
JW
9929
9930 for (i = 0; i < XVECLEN (operands[2], 0); i++)
9931 {
9932 rtx set = XVECEXP (operands[2], 0, i);
9933 emit_move_insn (SET_DEST (set), SET_SRC (set));
9934 }
9935
9936 /* The optimizer does not know that the call sets the function value
9937 registers we stored in the result block. We avoid problems by
9938 claiming that all hard registers are used and clobbered at this
9939 point. */
9940 emit_insn (gen_blockage ());
9941
9942 DONE;
d9241861 9943})
bc45ade3
SC
9944\f
9945;; ------------------------------------------------------------------------
9946;; Misc insns
9947;; ------------------------------------------------------------------------
9948
51bd623f 9949(define_insn "dect"
4773afa4 9950 [(set (reg:SI T_REG)
077668e3
BS
9951 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
9952 (set (match_operand:SI 0 "arith_reg_dest" "=r")
9953 (plus:SI (match_dup 1) (const_int -1)))]
51bd623f 9954 "TARGET_SH2"
1245df60
R
9955 "dt %0"
9956 [(set_attr "type" "arith")])
bc45ade3
SC
9957
9958(define_insn "nop"
9959 [(const_int 0)]
9960 ""
51bd623f 9961 "nop")
0d7e008e 9962
1245df60
R
9963;; Load address of a label. This is only generated by the casesi expand,
9964;; and by machine_dependent_reorg (fixing up fp moves).
9965;; This must use unspec, because this only works for labels that are
9966;; within range,
0d7e008e
SC
9967
9968(define_insn "mova"
4773afa4 9969 [(set (reg:SI R0_REG)
e69d1422 9970 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
fa5322fa 9971 "TARGET_SH1"
0d7e008e 9972 "mova %O0,r0"
1245df60
R
9973 [(set_attr "in_delay_slot" "no")
9974 (set_attr "type" "arith")])
0d7e008e 9975
18dbd950 9976;; machine_dependent_reorg will make this a `mova'.
43c05634
AO
9977(define_insn "mova_const"
9978 [(set (reg:SI R0_REG)
e69d1422 9979 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
fa5322fa 9980 "TARGET_SH1"
43c05634
AO
9981 "#"
9982 [(set_attr "in_delay_slot" "no")
9983 (set_attr "type" "arith")])
9984
1a66cd67 9985(define_expand "GOTaddr2picreg"
4773afa4 9986 [(set (reg:SI R0_REG)
e69d1422
R
9987 (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
9988 UNSPEC_MOVA))
615cd49b 9989 (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
4773afa4 9990 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
d9241861 9991 ""
1a66cd67 9992{
f5c7290e
RS
9993 if (TARGET_VXWORKS_RTP)
9994 {
9995 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
9996 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
9997 emit_insn (gen_vxworks_picreg (gott_base, gott_index));
9998 DONE;
9999 }
10000
fa5322fa 10001 operands[0] = gen_rtx_REG (Pmode, PIC_REG);
1a66cd67 10002 operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
fa5322fa 10003
fa5322fa
AO
10004 if (TARGET_SHMEDIA)
10005 {
73a4d10b
R
10006 rtx tr = gen_rtx_REG (Pmode, TR0_REG);
10007 rtx pic = operands[0];
8e831557 10008 rtx lab = PATTERN (gen_call_site ());
fa5322fa
AO
10009 rtx insn, equiv;
10010
10011 equiv = operands[1];
dc3ba671
RS
10012 operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
10013 UNSPEC_PCREL_SYMOFF);
10014 operands[1] = gen_rtx_CONST (Pmode, operands[1]);
fa5322fa 10015
73a4d10b
R
10016 if (Pmode == SImode)
10017 {
10018 emit_insn (gen_movsi_const (pic, operands[1]));
329b3cc3 10019 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
73a4d10b 10020 }
fa5322fa 10021 else
73a4d10b
R
10022 {
10023 emit_insn (gen_movdi_const (pic, operands[1]));
329b3cc3 10024 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
73a4d10b 10025 }
fa5322fa
AO
10026
10027 insn = emit_move_insn (operands[0], tr);
52702ae1 10028
bd94cb6e 10029 set_unique_reg_note (insn, REG_EQUAL, equiv);
fa5322fa
AO
10030
10031 DONE;
10032 }
d9241861 10033})
1a66cd67 10034
f5c7290e
RS
10035;; A helper for GOTaddr2picreg to finish up the initialization of the
10036;; PIC register.
10037
10038(define_expand "vxworks_picreg"
10039 [(set (reg:SI PIC_REG)
10040 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
10041 (set (reg:SI R0_REG)
10042 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
10043 (set (reg:SI PIC_REG)
10044 (mem:SI (reg:SI PIC_REG)))
10045 (set (reg:SI PIC_REG)
10046 (mem:SI (plus:SI (reg:SI PIC_REG)
10047 (reg:SI R0_REG))))]
10048 "TARGET_VXWORKS_RTP")
10049
fa5322fa 10050(define_insn "*ptb"
73a4d10b
R
10051 [(set (match_operand 0 "target_reg_operand" "=b")
10052 (const (unspec [(match_operand 1 "" "Csy")]
fa5322fa
AO
10053 UNSPEC_DATALABEL)))]
10054 "TARGET_SHMEDIA && flag_pic
32a7ab3d 10055 && satisfies_constraint_Csy (operands[1])"
fa5322fa 10056 "ptb/u datalabel %1, %0"
73a4d10b 10057 [(set_attr "type" "ptabs_media")
fa5322fa
AO
10058 (set_attr "length" "*")])
10059
73a4d10b
R
10060(define_insn "ptrel_si"
10061 [(set (match_operand:SI 0 "target_reg_operand" "=b")
10062 (plus:SI (match_operand:SI 1 "register_operand" "r")
10063 (pc)))
10064 (match_operand:SI 2 "" "")]
10065 "TARGET_SHMEDIA"
10066 "%O2: ptrel/u %1, %0"
10067 [(set_attr "type" "ptabs_media")])
10068
10069(define_insn "ptrel_di"
e69d1422
R
10070 [(set (match_operand:DI 0 "target_reg_operand" "=b")
10071 (plus:DI (match_operand:DI 1 "register_operand" "r")
fa5322fa
AO
10072 (pc)))
10073 (match_operand:DI 2 "" "")]
10074 "TARGET_SHMEDIA"
10075 "%O2: ptrel/u %1, %0"
2ad65b0e 10076 [(set_attr "type" "ptabs_media")])
fa5322fa 10077
001643af
KK
10078(define_expand "builtin_setjmp_receiver"
10079 [(match_operand 0 "" "")]
10080 "flag_pic"
001643af
KK
10081{
10082 emit_insn (gen_GOTaddr2picreg ());
10083 DONE;
d9241861 10084})
001643af 10085
2d01e445
AO
10086(define_expand "call_site"
10087 [(unspec [(match_dup 0)] UNSPEC_CALLER)]
fa5322fa 10088 "TARGET_SH1"
2d01e445
AO
10089{
10090 static HOST_WIDE_INT i = 0;
10091 operands[0] = GEN_INT (i);
10092 i++;
d9241861 10093})
2d01e445 10094
af178daf
KK
10095;; op0 = op1 + r12 but hide it before reload completed. See the comment
10096;; in symGOT_load expand.
10097
10098(define_insn_and_split "chk_guard_add"
10099 [(set (match_operand:SI 0 "register_operand" "=&r")
10100 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
10101 (reg:SI PIC_REG)]
10102 UNSPEC_CHKADD))]
10103 "TARGET_SH1"
10104 "#"
10105 "TARGET_SH1 && reload_completed"
10106 [(set (match_dup 0) (reg:SI PIC_REG))
10107 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
10108 ""
10109 [(set_attr "type" "arith")])
10110
1a66cd67
AO
10111(define_expand "sym_label2reg"
10112 [(set (match_operand:SI 0 "" "")
dc3ba671
RS
10113 (const:SI (unspec:SI [(match_operand:SI 1 "" "")
10114 (const (plus:SI (match_operand:SI 2 "" "")
10115 (const_int 2)))]
10116 UNSPEC_SYMOFF)))]
fa5322fa 10117 "TARGET_SH1" "")
1a66cd67 10118
e1d71275
AO
10119(define_expand "symGOT_load"
10120 [(set (match_dup 2) (match_operand 1 "" ""))
10121 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
10122 (set (match_operand 0 "" "") (mem (match_dup 3)))]
10123 ""
e1d71275 10124{
535b951f 10125 rtx mem;
e1d71275 10126
b3a13419
ILT
10127 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10128 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
e1d71275 10129
fa5322fa
AO
10130 if (TARGET_SHMEDIA)
10131 {
10132 rtx reg = operands[2];
52702ae1 10133
73a4d10b
R
10134 if (Pmode == DImode)
10135 {
10136 if (flag_pic > 1)
10137 emit_insn (gen_movdi_const_32bit (reg, operands[1]));
10138 else
10139 emit_insn (gen_movdi_const_16bit (reg, operands[1]));
10140 }
fa5322fa 10141 else
73a4d10b
R
10142 {
10143 if (flag_pic > 1)
10144 emit_insn (gen_movsi_const (reg, operands[1]));
10145 else
10146 emit_insn (gen_movsi_const_16bit (reg, operands[1]));
10147 }
fa5322fa
AO
10148 }
10149 else
10150 emit_move_insn (operands[2], operands[1]);
e1d71275 10151
439211a0 10152 /* When stack protector inserts codes after the result is set to
af178daf
KK
10153 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec
10154 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
439211a0
KK
10155 when rX is a GOT address for the guard symbol. Ugly but doesn't
10156 matter because this is a rare situation. */
10157 if (!TARGET_SHMEDIA
10158 && flag_stack_protect
10159 && GET_CODE (operands[1]) == CONST
10160 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
10161 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
10162 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
d9241861 10163 "__stack_chk_guard") == 0)
af178daf
KK
10164 emit_insn (gen_chk_guard_add (operands[3], operands[2]));
10165 else
10166 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
10167 gen_rtx_REG (Pmode, PIC_REG)));
439211a0 10168
57d38024
R
10169 /* N.B. This is not constant for a GOTPLT relocation. */
10170 mem = gen_rtx_MEM (Pmode, operands[3]);
10171 MEM_NOTRAP_P (mem) = 1;
10172 /* ??? Should we have a special alias set for the GOT? */
535b951f 10173 emit_move_insn (operands[0], mem);
e1d71275 10174
e1d71275 10175 DONE;
d9241861 10176})
e1d71275
AO
10177
10178(define_expand "sym2GOT"
10179 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
10180 ""
10181 "")
10182
1a66cd67 10183(define_expand "symGOT2reg"
e1d71275 10184 [(match_operand 0 "" "") (match_operand 1 "" "")]
1a66cd67 10185 ""
1a66cd67 10186{
e1d71275
AO
10187 rtx gotsym, insn;
10188
10189 gotsym = gen_sym2GOT (operands[1]);
10190 PUT_MODE (gotsym, Pmode);
10191 insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
10192
389fdba0 10193 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
e1d71275
AO
10194
10195 DONE;
d9241861 10196})
1a66cd67 10197
fa5322fa
AO
10198(define_expand "symGOTPLT2reg"
10199 [(match_operand 0 "" "") (match_operand 1 "" "")]
10200 ""
fa5322fa 10201{
42201282
R
10202 rtx pltsym = gen_rtx_CONST (Pmode,
10203 gen_rtx_UNSPEC (Pmode,
10204 gen_rtvec (1, operands[1]),
10205 UNSPEC_GOTPLT));
10206 emit_insn (gen_symGOT_load (operands[0], pltsym));
fa5322fa 10207 DONE;
d9241861 10208})
fa5322fa 10209
e1d71275
AO
10210(define_expand "sym2GOTOFF"
10211 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10212 ""
10213 "")
10214
1a66cd67 10215(define_expand "symGOTOFF2reg"
e1d71275 10216 [(match_operand 0 "" "") (match_operand 1 "" "")]
1a66cd67 10217 ""
1a66cd67 10218{
e1d71275 10219 rtx gotoffsym, insn;
b3a13419
ILT
10220 rtx t = (!can_create_pseudo_p ()
10221 ? operands[0]
45312d9d 10222 : gen_reg_rtx (GET_MODE (operands[0])));
e1d71275
AO
10223
10224 gotoffsym = gen_sym2GOTOFF (operands[1]);
10225 PUT_MODE (gotoffsym, Pmode);
10226 emit_move_insn (t, gotoffsym);
10227 insn = emit_move_insn (operands[0],
10228 gen_rtx_PLUS (Pmode, t,
10229 gen_rtx_REG (Pmode, PIC_REG)));
10230
bd94cb6e 10231 set_unique_reg_note (insn, REG_EQUAL, operands[1]);
e1d71275
AO
10232
10233 DONE;
d9241861 10234})
1a66cd67
AO
10235
10236(define_expand "symPLT_label2reg"
10237 [(set (match_operand:SI 0 "" "")
dc3ba671
RS
10238 (const:SI
10239 (unspec:SI
10240 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10241 (const:SI (plus:SI (match_operand:SI 2 "" "")
10242 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
6915629f
AO
10243 ;; Even though the PIC register is not really used by the call
10244 ;; sequence in which this is expanded, the PLT code assumes the PIC
10245 ;; register is set, so we must not skip its initialization. Since
10246 ;; we only use this expand as part of calling sequences, and never
10247 ;; to take the address of a function, this is the best point to
10248 ;; insert the (use). Using the PLT to take the address of a
10249 ;; function would be wrong, not only because the PLT entry could
10250 ;; then be called from a function that doesn't initialize the PIC
10251 ;; register to the proper GOT, but also because pointers to the
10252 ;; same function might not compare equal, should they be set by
10253 ;; different shared libraries.
10254 (use (reg:SI PIC_REG))]
fa5322fa
AO
10255 "TARGET_SH1"
10256 "")
10257
10258(define_expand "sym2PIC"
10259 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
6915629f
AO
10260 ""
10261 "")
1a66cd67 10262
463f02cd
KK
10263;; TLS code generation.
10264;; ??? this should be a define_insn_and_split
10265;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10266;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10267;; for details.
10268
10269(define_insn "tls_global_dynamic"
10270 [(set (match_operand:SI 0 "register_operand" "=&z")
73a4d10b 10271 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
07ea92d3 10272 UNSPEC_TLSGD))
13ecc9e0 10273 (const_int 0)))
463f02cd
KK
10274 (use (reg:PSI FPSCR_REG))
10275 (use (reg:SI PIC_REG))
10276 (clobber (reg:SI PR_REG))
10277 (clobber (scratch:SI))]
10278 "TARGET_SH1"
d9241861
OE
10279{
10280 return "mov.l 1f,r4" "\n"
10281 " mova 2f,r0" "\n"
10282 " mov.l 2f,r1" "\n"
10283 " add r0,r1" "\n"
10284 " jsr @r1" "\n"
10285 " add r12,r4" "\n"
10286 " bra 3f" "\n"
10287 " nop" "\n"
10288 " .align 2" "\n"
10289 "1: .long %a1@TLSGD" "\n"
10290 "2: .long __tls_get_addr@PLT" "\n"
10291 "3:";
10292}
463f02cd
KK
10293 [(set_attr "type" "tls_load")
10294 (set_attr "length" "26")])
10295
10296(define_insn "tls_local_dynamic"
10297 [(set (match_operand:SI 0 "register_operand" "=&z")
73a4d10b 10298 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
07ea92d3 10299 UNSPEC_TLSLDM))
13ecc9e0 10300 (const_int 0)))
463f02cd
KK
10301 (use (reg:PSI FPSCR_REG))
10302 (use (reg:SI PIC_REG))
10303 (clobber (reg:SI PR_REG))
10304 (clobber (scratch:SI))]
10305 "TARGET_SH1"
d9241861
OE
10306{
10307 return "mov.l 1f,r4" "\n"
10308 " mova 2f,r0" "\n"
10309 " mov.l 2f,r1" "\n"
10310 " add r0,r1" "\n"
10311 " jsr @r1" "\n"
10312 " add r12,r4" "\n"
10313 " bra 3f" "\n"
10314 " nop" "\n"
10315 " .align 2" "\n"
10316 "1: .long %a1@TLSLDM" "\n"
10317 "2: .long __tls_get_addr@PLT" "\n"
10318 "3:";
10319}
463f02cd
KK
10320 [(set_attr "type" "tls_load")
10321 (set_attr "length" "26")])
10322
10323(define_expand "sym2DTPOFF"
10324 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
10325 ""
10326 "")
10327
10328(define_expand "symDTPOFF2reg"
10329 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
10330 ""
463f02cd 10331{
535b951f 10332 rtx dtpoffsym;
b3a13419
ILT
10333 rtx t = (!can_create_pseudo_p ()
10334 ? operands[0]
45312d9d 10335 : gen_reg_rtx (GET_MODE (operands[0])));
463f02cd
KK
10336
10337 dtpoffsym = gen_sym2DTPOFF (operands[1]);
10338 PUT_MODE (dtpoffsym, Pmode);
10339 emit_move_insn (t, dtpoffsym);
535b951f 10340 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
463f02cd 10341 DONE;
d9241861 10342})
463f02cd
KK
10343
10344(define_expand "sym2GOTTPOFF"
10345 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
10346 ""
10347 "")
10348
10349(define_insn "tls_initial_exec"
10350 [(set (match_operand:SI 0 "register_operand" "=&r")
10351 (unspec:SI [(match_operand:SI 1 "" "")]
10352 UNSPEC_TLSIE))
10353 (use (reg:SI GBR_REG))
10354 (use (reg:SI PIC_REG))
10355 (clobber (reg:SI R0_REG))]
10356 ""
d9241861
OE
10357{
10358 return "mov.l 1f,r0" "\n"
10359 " stc gbr,%0" "\n"
10360 " mov.l @(r0,r12),r0" "\n"
10361 " bra 2f" "\n"
10362 " add r0,%0" "\n"
10363 " .align 2" "\n"
10364 "1: .long %a1" "\n"
10365 "2:";
10366}
463f02cd
KK
10367 [(set_attr "type" "tls_load")
10368 (set_attr "length" "16")])
10369
10370(define_expand "sym2TPOFF"
10371 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
10372 ""
10373 "")
10374
10375(define_expand "symTPOFF2reg"
10376 [(match_operand 0 "" "") (match_operand 1 "" "")]
10377 ""
463f02cd 10378{
535b951f 10379 rtx tpoffsym;
463f02cd
KK
10380
10381 tpoffsym = gen_sym2TPOFF (operands[1]);
10382 PUT_MODE (tpoffsym, Pmode);
535b951f 10383 emit_move_insn (operands[0], tpoffsym);
463f02cd 10384 DONE;
d9241861 10385})
463f02cd 10386
7d11d296
OE
10387;;------------------------------------------------------------------------------
10388;; Thread pointer getter and setter.
10389;;
10390;; On SH the thread pointer is kept in the GBR.
10391;; These patterns are usually expanded from the respective built-in functions.
0b622253 10392(define_expand "get_thread_pointersi"
7d11d296
OE
10393 [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))]
10394 "TARGET_SH1")
10395
10396;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
10397(define_insn "store_gbr"
10398 [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))]
463f02cd
KK
10399 ""
10400 "stc gbr,%0"
10401 [(set_attr "type" "tls_load")])
10402
0b622253 10403(define_expand "set_thread_pointersi"
7d11d296
OE
10404 [(set (reg:SI GBR_REG)
10405 (unspec_volatile:SI [(match_operand:SI 0 "register_operand")]
10406 UNSPECV_GBR))]
10407 "TARGET_SH1")
10408
10409(define_insn "load_gbr"
10410 [(set (reg:SI GBR_REG)
10411 (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
10412 UNSPECV_GBR))]
10413 "TARGET_SH1"
10414 "ldc %0,gbr"
10415 [(set_attr "type" "move")])
10416
fce1e5fb
OE
10417;;------------------------------------------------------------------------------
10418;; Thread pointer relative memory loads and stores.
10419;;
10420;; On SH there are GBR displacement address modes which can be utilized to
10421;; access memory behind the thread pointer.
10422;; Since we do not allow using GBR for general purpose memory accesses, these
10423;; GBR addressing modes are formed by the combine pass.
10424;; This could be done with fewer patterns than below by using a mem predicate
10425;; for the GBR mem, but then reload would try to reload addresses with a
10426;; zero displacement for some strange reason.
10427
10428(define_insn "*mov<mode>_gbr_load"
10429 [(set (match_operand:QIHISI 0 "register_operand" "=z")
10430 (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10431 (match_operand:QIHISI 1 "gbr_displacement"))))]
10432 "TARGET_SH1"
10433 "mov.<bwl> @(%O1,gbr),%0"
10434 [(set_attr "type" "load")])
10435
10436(define_insn "*mov<mode>_gbr_load"
10437 [(set (match_operand:QIHISI 0 "register_operand" "=z")
10438 (mem:QIHISI (reg:SI GBR_REG)))]
10439 "TARGET_SH1"
10440 "mov.<bwl> @(0,gbr),%0"
10441 [(set_attr "type" "load")])
10442
10443(define_insn "*mov<mode>_gbr_load"
10444 [(set (match_operand:SI 0 "register_operand" "=z")
10445 (sign_extend:SI
10446 (mem:QIHI (plus:SI (reg:SI GBR_REG)
10447 (match_operand:QIHI 1 "gbr_displacement")))))]
10448 "TARGET_SH1"
10449 "mov.<bw> @(%O1,gbr),%0"
10450 [(set_attr "type" "load")])
10451
10452(define_insn "*mov<mode>_gbr_load"
10453 [(set (match_operand:SI 0 "register_operand" "=z")
10454 (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
10455 "TARGET_SH1"
10456 "mov.<bw> @(0,gbr),%0"
10457 [(set_attr "type" "load")])
10458
10459(define_insn "*mov<mode>_gbr_store"
10460 [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10461 (match_operand:QIHISI 0 "gbr_displacement")))
10462 (match_operand:QIHISI 1 "register_operand" "z"))]
10463 "TARGET_SH1"
10464 "mov.<bwl> %1,@(%O0,gbr)"
10465 [(set_attr "type" "store")])
10466
10467(define_insn "*mov<mode>_gbr_store"
10468 [(set (mem:QIHISI (reg:SI GBR_REG))
10469 (match_operand:QIHISI 0 "register_operand" "z"))]
10470 "TARGET_SH1"
10471 "mov.<bwl> %0,@(0,gbr)"
10472 [(set_attr "type" "store")])
10473
14df3f36
OE
10474;; DImode memory accesses have to be split in two SImode accesses.
10475;; Split them before reload, so that it gets a better chance to figure out
10476;; how to deal with the R0 restriction for the individual SImode accesses.
10477;; Do not match this insn during or after reload because it can't be split
10478;; afterwards.
10479(define_insn_and_split "*movdi_gbr_load"
10480 [(set (match_operand:DI 0 "register_operand")
10481 (match_operand:DI 1 "gbr_address_mem"))]
10482 "TARGET_SH1 && can_create_pseudo_p ()"
10483 "#"
10484 "&& 1"
10485 [(set (match_dup 3) (match_dup 5))
10486 (set (match_dup 4) (match_dup 6))]
10487{
10488 /* Swap low/high part load order on little endian, so that the result reg
10489 of the second load can be used better. */
10490 int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
10491 operands[3 + off] = gen_lowpart (SImode, operands[0]);
10492 operands[5 + off] = gen_lowpart (SImode, operands[1]);
10493 operands[4 - off] = gen_highpart (SImode, operands[0]);
10494 operands[6 - off] = gen_highpart (SImode, operands[1]);
10495})
10496
10497(define_insn_and_split "*movdi_gbr_store"
10498 [(set (match_operand:DI 0 "gbr_address_mem")
10499 (match_operand:DI 1 "register_operand"))]
10500 "TARGET_SH1 && can_create_pseudo_p ()"
10501 "#"
10502 "&& 1"
10503 [(set (match_dup 3) (match_dup 5))
10504 (set (match_dup 4) (match_dup 6))]
10505{
10506 /* Swap low/high part store order on big endian, so that stores of function
10507 call results can save a reg copy. */
10508 int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
10509 operands[3 + off] = gen_lowpart (SImode, operands[0]);
10510 operands[5 + off] = gen_lowpart (SImode, operands[1]);
10511 operands[4 - off] = gen_highpart (SImode, operands[0]);
10512 operands[6 - off] = gen_highpart (SImode, operands[1]);
10513})
10514
fce1e5fb
OE
10515;; Sometimes memory accesses do not get combined with the store_gbr insn,
10516;; in particular when the displacements are in the range of the regular move
10517;; insns. Thus, in the first split pass after the combine pass we search
10518;; for missed opportunities and try to fix them up ourselves.
10519;; If an equivalent GBR address can be determined the load / store is split
10520;; into one of the GBR load / store patterns.
10521;; All of that must happen before reload (GBR address modes use R0 as the
10522;; other operand) and there's no point of doing it if the GBR is not
10523;; referenced in a function at all.
10524(define_split
14df3f36
OE
10525 [(set (match_operand:QIHISIDI 0 "register_operand")
10526 (match_operand:QIHISIDI 1 "memory_operand"))]
fce1e5fb
OE
10527 "TARGET_SH1 && !reload_in_progress && !reload_completed
10528 && df_regs_ever_live_p (GBR_REG)"
10529 [(set (match_dup 0) (match_dup 1))]
10530{
10531 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10532 if (gbr_mem != NULL_RTX)
14df3f36 10533 operands[1] = replace_equiv_address (operands[1], gbr_mem);
fce1e5fb
OE
10534 else
10535 FAIL;
10536})
10537
10538(define_split
10539 [(set (match_operand:SI 0 "register_operand")
10540 (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10541 "TARGET_SH1 && !reload_in_progress && !reload_completed
10542 && df_regs_ever_live_p (GBR_REG)"
10543 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
10544{
10545 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10546 if (gbr_mem != NULL_RTX)
14df3f36 10547 operands[1] = replace_equiv_address (operands[1], gbr_mem);
fce1e5fb
OE
10548 else
10549 FAIL;
10550})
10551
10552;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
10553;; Split those so that a GBR load can be used.
10554(define_split
10555 [(set (match_operand:SI 0 "register_operand")
10556 (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10557 "TARGET_SH2A && !reload_in_progress && !reload_completed
10558 && df_regs_ever_live_p (GBR_REG)"
10559 [(set (match_dup 2) (match_dup 1))
10560 (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
10561{
10562 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10563 if (gbr_mem != NULL_RTX)
10564 {
10565 operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
14df3f36 10566 operands[1] = replace_equiv_address (operands[1], gbr_mem);
fce1e5fb
OE
10567 }
10568 else
10569 FAIL;
10570})
10571
10572(define_split
14df3f36
OE
10573 [(set (match_operand:QIHISIDI 0 "memory_operand")
10574 (match_operand:QIHISIDI 1 "register_operand"))]
fce1e5fb
OE
10575 "TARGET_SH1 && !reload_in_progress && !reload_completed
10576 && df_regs_ever_live_p (GBR_REG)"
10577 [(set (match_dup 0) (match_dup 1))]
10578{
10579 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
10580 if (gbr_mem != NULL_RTX)
14df3f36 10581 operands[0] = replace_equiv_address (operands[0], gbr_mem);
fce1e5fb
OE
10582 else
10583 FAIL;
10584})
10585
7d11d296 10586;;------------------------------------------------------------------------------
0d7e008e
SC
10587;; case instruction for switch statements.
10588
10589;; Operand 0 is index
10590;; operand 1 is the minimum bound
10591;; operand 2 is the maximum bound - minimum bound + 1
10592;; operand 3 is CODE_LABEL for the table;
10593;; operand 4 is the CODE_LABEL to go to if index out of range.
10594
10595(define_expand "casesi"
1245df60
R
10596 [(match_operand:SI 0 "arith_reg_operand" "")
10597 (match_operand:SI 1 "arith_reg_operand" "")
10598 (match_operand:SI 2 "arith_reg_operand" "")
10599 (match_operand 3 "" "") (match_operand 4 "" "")]
10600 ""
1245df60
R
10601{
10602 rtx reg = gen_reg_rtx (SImode);
10603 rtx reg2 = gen_reg_rtx (SImode);
fa5322fa
AO
10604 if (TARGET_SHMEDIA)
10605 {
10606 rtx reg = gen_reg_rtx (DImode);
10607 rtx reg2 = gen_reg_rtx (DImode);
73a4d10b
R
10608 rtx reg3 = gen_reg_rtx (Pmode);
10609 rtx reg4 = gen_reg_rtx (Pmode);
10610 rtx reg5 = gen_reg_rtx (Pmode);
f90b7a5a 10611 rtx load, test;
fa5322fa
AO
10612
10613 operands[0] = convert_modes (DImode, SImode, operands[0], 0);
10614 operands[1] = convert_modes (DImode, SImode, operands[1], 0);
10615 operands[2] = convert_modes (DImode, SImode, operands[2], 1);
10616
f90b7a5a
PB
10617 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
10618 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4]));
fa5322fa 10619 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
f90b7a5a
PB
10620 test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
10621 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
fa5322fa
AO
10622 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
10623 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
73a4d10b
R
10624 (Pmode, operands[3])));
10625 /* Messy: can we subreg to clean this up? */
10626 if (Pmode == DImode)
10627 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
10628 else
10629 load = gen_casesi_load_media (reg4,
10630 gen_rtx_SUBREG (DImode, reg3, 0),
10631 reg2, operands[3]);
10632 PUT_MODE (SET_SRC (load), Pmode);
10633 emit_insn (load);
10634 /* ??? The following add could be eliminated if we used ptrel. */
10635 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
fa5322fa
AO
10636 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
10637 emit_barrier ();
10638 DONE;
10639 }
1245df60
R
10640 operands[1] = copy_to_mode_reg (SImode, operands[1]);
10641 operands[2] = copy_to_mode_reg (SImode, operands[2]);
10642 /* If optimizing, casesi_worker depends on the mode of the instruction
10643 before label it 'uses' - operands[3]. */
10644 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
10645 reg));
10646 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
10647 if (TARGET_SH2)
eb3881bf 10648 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
1245df60 10649 else
eb3881bf 10650 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
1245df60
R
10651 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
10652 operands[3], but to lab. We will fix this up in
10653 machine_dependent_reorg. */
10654 emit_barrier ();
10655 DONE;
d9241861 10656})
1245df60
R
10657
10658(define_expand "casesi_0"
10659 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
10660 (set (match_dup 4) (minus:SI (match_dup 4)
0d7e008e 10661 (match_operand:SI 1 "arith_operand" "")))
4773afa4 10662 (set (reg:SI T_REG)
1245df60 10663 (gtu:SI (match_dup 4)
22e1ebf1 10664 (match_operand:SI 2 "arith_reg_operand" "")))
0d7e008e 10665 (set (pc)
4773afa4 10666 (if_then_else (ne (reg:SI T_REG)
7c225e88 10667 (const_int 0))
1245df60
R
10668 (label_ref (match_operand 3 "" ""))
10669 (pc)))]
fa5322fa 10670 "TARGET_SH1"
1245df60 10671 "")
0d7e008e 10672
1245df60
R
10673;; ??? reload might clobber r0 if we use it explicitly in the RTL before
10674;; reload; using a R0_REGS pseudo reg is likely to give poor code.
10675;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
10676
10677(define_insn "casesi_worker_0"
10678 [(set (match_operand:SI 0 "register_operand" "=r,r")
e69d1422 10679 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
4773afa4 10680 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
1245df60
R
10681 (clobber (match_scratch:SI 3 "=X,1"))
10682 (clobber (match_scratch:SI 4 "=&z,z"))]
fa5322fa 10683 "TARGET_SH1"
1245df60
R
10684 "#")
10685
10686(define_split
10687 [(set (match_operand:SI 0 "register_operand" "")
e69d1422
R
10688 (unspec:SI [(match_operand:SI 1 "register_operand" "")
10689 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
1245df60
R
10690 (clobber (match_scratch:SI 3 ""))
10691 (clobber (match_scratch:SI 4 ""))]
fa5322fa 10692 "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
e69d1422 10693 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
1245df60 10694 (parallel [(set (match_dup 0)
e69d1422
R
10695 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10696 (label_ref (match_dup 2))] UNSPEC_CASESI))
1245df60 10697 (clobber (match_dup 3))])
4773afa4 10698 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
d9241861
OE
10699{
10700 if (GET_CODE (operands[2]) == CODE_LABEL)
10701 LABEL_NUSES (operands[2])++;
10702})
1245df60
R
10703
10704(define_split
10705 [(set (match_operand:SI 0 "register_operand" "")
e69d1422
R
10706 (unspec:SI [(match_operand:SI 1 "register_operand" "")
10707 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
1245df60
R
10708 (clobber (match_scratch:SI 3 ""))
10709 (clobber (match_scratch:SI 4 ""))]
10710 "TARGET_SH2 && reload_completed"
e69d1422 10711 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
1245df60 10712 (parallel [(set (match_dup 0)
615cd49b 10713 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
e69d1422 10714 (label_ref (match_dup 2))] UNSPEC_CASESI))
1245df60 10715 (clobber (match_dup 3))])]
d9241861
OE
10716{
10717 if (GET_CODE (operands[2]) == CODE_LABEL)
10718 LABEL_NUSES (operands[2])++;
10719})
1245df60 10720
078c8b08 10721(define_insn "casesi_worker_1"
1245df60 10722 [(set (match_operand:SI 0 "register_operand" "=r,r")
e69d1422
R
10723 (unspec:SI [(reg:SI R0_REG)
10724 (match_operand:SI 1 "register_operand" "0,r")
10725 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
1245df60 10726 (clobber (match_scratch:SI 3 "=X,1"))]
fa5322fa 10727 "TARGET_SH1"
ffae286a 10728{
33f7f353
JR
10729 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10730
f5b9e7c9 10731 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
33f7f353
JR
10732
10733 switch (GET_MODE (diff_vec))
1245df60
R
10734 {
10735 case SImode:
35ed5a70
OE
10736 return "shll2 %1" "\n"
10737 " mov.l @(r0,%1),%0";
1245df60 10738 case HImode:
35ed5a70
OE
10739 return "add %1,%1" "\n"
10740 " mov.w @(r0,%1),%0";
1245df60 10741 case QImode:
33f7f353 10742 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
35ed5a70
OE
10743 return "mov.b @(r0,%1),%0" "\n"
10744 " extu.b %0,%0";
10745 else
10746 return "mov.b @(r0,%1),%0";
10747
1245df60 10748 default:
f5b9e7c9 10749 gcc_unreachable ();
1245df60 10750 }
d9241861 10751}
51bd623f 10752 [(set_attr "length" "4")])
0d7e008e 10753
078c8b08
R
10754(define_insn "casesi_worker_2"
10755 [(set (match_operand:SI 0 "register_operand" "=r,r")
10756 (unspec:SI [(reg:SI R0_REG)
10757 (match_operand:SI 1 "register_operand" "0,r")
10758 (label_ref (match_operand 2 "" ""))
10759 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
10760 (clobber (match_operand:SI 4 "" "=X,1"))]
10761 "TARGET_SH2 && reload_completed && flag_pic"
078c8b08
R
10762{
10763 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
f5b9e7c9 10764 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
078c8b08
R
10765
10766 switch (GET_MODE (diff_vec))
10767 {
10768 case SImode:
35ed5a70
OE
10769 return "shll2 %1" "\n"
10770 " add r0,%1" "\n"
10771 " mova %O3,r0" "\n"
10772 " mov.l @(r0,%1),%0";
078c8b08 10773 case HImode:
35ed5a70
OE
10774 return "add %1,%1" "\n"
10775 " add r0,%1" "\n"
10776 " mova %O3,r0" "\n"
10777 " mov.w @(r0,%1),%0";
078c8b08
R
10778 case QImode:
10779 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
35ed5a70
OE
10780 return "add r0,%1" "\n"
10781 " mova %O3,r0" "\n"
10782 " mov.b @(r0,%1),%0" "\n"
10783 " extu.b %0,%0";
078c8b08 10784 else
35ed5a70
OE
10785 return "add r0,%1" "\n"
10786 " mova %O3,r0" "\n"
10787 " mov.b @(r0,%1),%0";
078c8b08 10788 default:
f5b9e7c9 10789 gcc_unreachable ();
078c8b08 10790 }
d9241861 10791}
078c8b08
R
10792 [(set_attr "length" "8")])
10793
fa5322fa 10794(define_insn "casesi_shift_media"
73a4d10b 10795 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
51214775
R
10796 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
10797 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
10798 UNSPEC_CASESI)))]
fa5322fa 10799 "TARGET_SHMEDIA"
fa5322fa
AO
10800{
10801 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10802
f5b9e7c9 10803 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
fa5322fa
AO
10804
10805 switch (GET_MODE (diff_vec))
10806 {
10807 case SImode:
d9241861 10808 return "shlli %1, 2, %0";
fa5322fa 10809 case HImode:
d9241861 10810 return "shlli %1, 1, %0";
fa5322fa
AO
10811 case QImode:
10812 if (rtx_equal_p (operands[0], operands[1]))
d9241861
OE
10813 return "";
10814 return "add %1, r63, %0";
fa5322fa 10815 default:
f5b9e7c9 10816 gcc_unreachable ();
fa5322fa 10817 }
d9241861 10818}
2ad65b0e 10819 [(set_attr "type" "arith_media")])
fa5322fa
AO
10820
10821(define_insn "casesi_load_media"
73a4d10b
R
10822 [(set (match_operand 0 "any_arith_reg_dest" "=r")
10823 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
10824 (match_operand:DI 2 "arith_reg_operand" "r")
10825 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
fa5322fa 10826 "TARGET_SHMEDIA"
fa5322fa
AO
10827{
10828 rtx diff_vec = PATTERN (next_real_insn (operands[3]));
10829
f5b9e7c9 10830 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
fa5322fa
AO
10831
10832 switch (GET_MODE (diff_vec))
10833 {
10834 case SImode:
d9241861 10835 return "ldx.l %1, %2, %0";
fa5322fa
AO
10836 case HImode:
10837#if 0
10838 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
d9241861 10839 return "ldx.uw %1, %2, %0";
fa5322fa 10840#endif
d9241861 10841 return "ldx.w %1, %2, %0";
fa5322fa
AO
10842 case QImode:
10843 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
d9241861
OE
10844 return "ldx.ub %1, %2, %0";
10845 return "ldx.b %1, %2, %0";
fa5322fa 10846 default:
f5b9e7c9 10847 gcc_unreachable ();
fa5322fa 10848 }
d9241861 10849}
2ad65b0e 10850 [(set_attr "type" "load_media")])
fa5322fa 10851
fcf8632e
CB
10852(define_expand "simple_return"
10853 [(simple_return)]
10854 "sh_can_use_simple_return_p ()")
10855
afbc2905
R
10856(define_expand "return"
10857 [(return)]
fcf8632e 10858 "reload_completed && epilogue_completed"
fa5322fa
AO
10859{
10860 if (TARGET_SHMEDIA)
10861 {
10862 emit_jump_insn (gen_return_media ());
10863 DONE;
10864 }
10865
10866 if (TARGET_SHCOMPACT
38173d38 10867 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
fa5322fa
AO
10868 {
10869 emit_jump_insn (gen_shcompact_return_tramp ());
10870 DONE;
10871 }
d9241861 10872})
afbc2905 10873
fcf8632e
CB
10874(define_insn "*<code>_i"
10875 [(any_return)]
fa5322fa 10876 "TARGET_SH1 && ! (TARGET_SHCOMPACT
38173d38 10877 && (crtl->args.info.call_cookie
fa5322fa 10878 & CALL_COOKIE_RET_TRAMP (1)))
a6ab9fc0 10879 && reload_completed
d16202ba 10880 && ! sh_cfun_trap_exit_p ()"
d9241861
OE
10881{
10882 if (TARGET_SH2A && (dbr_sequence_length () == 0)
10883 && !current_function_interrupt)
10884 return "rts/n";
10885 else
10886 return "%@ %#";
10887}
10888 [(set_attr "type" "return")
51bd623f 10889 (set_attr "needs_delay_slot" "yes")])
b9654711 10890
a6ab9fc0
R
10891;; trapa has no delay slot.
10892(define_insn "*return_trapa"
10893 [(return)]
10894 "TARGET_SH1 && !TARGET_SHCOMPACT
10895 && reload_completed"
10896 "%@"
10897 [(set_attr "type" "return")])
10898
fa5322fa
AO
10899(define_expand "shcompact_return_tramp"
10900 [(return)]
10901 "TARGET_SHCOMPACT
38173d38 10902 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
fa5322fa
AO
10903{
10904 rtx reg = gen_rtx_REG (Pmode, R0_REG);
fa5322fa 10905
d9241861 10906 function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
fa5322fa
AO
10907 emit_jump_insn (gen_shcompact_return_tramp_i ());
10908 DONE;
d9241861 10909})
fa5322fa
AO
10910
10911(define_insn "shcompact_return_tramp_i"
10912 [(parallel [(return) (use (reg:SI R0_REG))])]
10913 "TARGET_SHCOMPACT
38173d38 10914 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
fa5322fa
AO
10915 "jmp @r0%#"
10916 [(set_attr "type" "jump_ind")
10917 (set_attr "needs_delay_slot" "yes")])
10918
10919(define_insn "return_media_i"
73a4d10b 10920 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
fa5322fa 10921 "TARGET_SHMEDIA && reload_completed"
2ad65b0e
SC
10922 "blink %0, r63"
10923 [(set_attr "type" "jump_media")])
fa5322fa 10924
1bf93c14
R
10925(define_insn "return_media_rte"
10926 [(return)]
10927 "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
10928 "rte"
10929 [(set_attr "type" "jump_media")])
10930
fa5322fa
AO
10931(define_expand "return_media"
10932 [(return)]
10933 "TARGET_SHMEDIA && reload_completed"
fa5322fa
AO
10934{
10935 int tr_regno = sh_media_register_for_return ();
10936 rtx tr;
10937
1bf93c14
R
10938 if (current_function_interrupt)
10939 {
10940 emit_jump_insn (gen_return_media_rte ());
10941 DONE;
10942 }
fa5322fa
AO
10943 if (tr_regno < 0)
10944 {
73a4d10b 10945 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
fa5322fa 10946
f5b9e7c9 10947 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
fa5322fa 10948 tr_regno = TR0_REG;
73a4d10b 10949 tr = gen_rtx_REG (Pmode, tr_regno);
fa5322fa
AO
10950 emit_move_insn (tr, r18);
10951 }
10952 else
73a4d10b 10953 tr = gen_rtx_REG (Pmode, tr_regno);
fa5322fa
AO
10954
10955 emit_jump_insn (gen_return_media_i (tr));
10956 DONE;
d9241861 10957})
fa5322fa
AO
10958
10959(define_insn "shcompact_preserve_incoming_args"
e69d1422
R
10960 [(set (match_operand:SI 0 "register_operand" "+r")
10961 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
fa5322fa
AO
10962 "TARGET_SHCOMPACT"
10963 ""
10964 [(set_attr "length" "0")])
10965
10966(define_insn "shcompact_incoming_args"
e69d1422
R
10967 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
10968 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
10969 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
10970 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
10971 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
10972 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
10973 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
10974 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
fa5322fa 10975 (set (mem:BLK (reg:SI MACL_REG))
e69d1422 10976 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
fa5322fa
AO
10977 (use (reg:SI R0_REG))
10978 (clobber (reg:SI R0_REG))
10979 (clobber (reg:SI MACL_REG))
10980 (clobber (reg:SI MACH_REG))
10981 (clobber (reg:SI PR_REG))]
10982 "TARGET_SHCOMPACT"
10983 "jsr @r0%#"
10984 [(set_attr "needs_delay_slot" "yes")])
10985
10986(define_insn "shmedia_save_restore_regs_compact"
10987 [(set (reg:SI SP_REG)
10988 (plus:SI (reg:SI SP_REG)
10989 (match_operand:SI 0 "immediate_operand" "i")))
10990 (use (reg:SI R0_REG))
10991 (clobber (reg:SI PR_REG))]
10992 "TARGET_SHCOMPACT
10993 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
10994 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
10995 "jsr @r0%#"
10996 [(set_attr "needs_delay_slot" "yes")])
10997
b9654711
SC
10998(define_expand "prologue"
10999 [(const_int 0)]
11000 ""
68965312
OE
11001{
11002 sh_expand_prologue ();
11003 DONE;
11004})
b9654711
SC
11005
11006(define_expand "epilogue"
11007 [(return)]
11008 ""
68965312
OE
11009{
11010 sh_expand_epilogue (false);
7d9f9bd1
KK
11011 if (TARGET_SHMEDIA
11012 || (TARGET_SHCOMPACT
11013 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
11014 {
11015 emit_jump_insn (gen_return ());
11016 DONE;
11017 }
68965312 11018})
b9654711 11019
4977bab6 11020(define_expand "eh_return"
34dc173c 11021 [(use (match_operand 0 "register_operand" ""))]
4977bab6
ZW
11022 ""
11023{
45dc67b7 11024 rtx ra = operands[0];
4977bab6
ZW
11025
11026 if (TARGET_SHMEDIA64)
11027 emit_insn (gen_eh_set_ra_di (ra));
11028 else
11029 emit_insn (gen_eh_set_ra_si (ra));
11030
4977bab6
ZW
11031 DONE;
11032})
11033
11034;; Clobber the return address on the stack. We can't expand this
11035;; until we know where it will be put in the stack frame.
11036
11037(define_insn "eh_set_ra_si"
6fb5fa3c
DB
11038 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
11039 UNSPECV_EH_RETURN)
4977bab6
ZW
11040 (clobber (match_scratch:SI 1 "=&r"))]
11041 "! TARGET_SHMEDIA64"
11042 "#")
11043
11044(define_insn "eh_set_ra_di"
6fb5fa3c
DB
11045 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
11046 UNSPECV_EH_RETURN)
4977bab6
ZW
11047 (clobber (match_scratch:DI 1 "=&r"))]
11048 "TARGET_SHMEDIA64"
11049 "#")
11050
11051(define_split
6fb5fa3c
DB
11052 [(unspec_volatile [(match_operand 0 "register_operand" "")]
11053 UNSPECV_EH_RETURN)
4977bab6
ZW
11054 (clobber (match_scratch 1 ""))]
11055 "reload_completed"
11056 [(const_int 0)]
4977bab6
ZW
11057{
11058 sh_set_return_address (operands[0], operands[1]);
11059 DONE;
d9241861 11060})
4977bab6 11061
b9654711 11062(define_insn "blockage"
4773afa4 11063 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
b9654711
SC
11064 ""
11065 ""
11066 [(set_attr "length" "0")])
bc45ade3 11067\f
91a19652
N
11068;; Define movml instructions for SH2A target. Currently they are
11069;; used to push and pop all banked registers only.
11070
11071(define_insn "movml_push_banked"
11072 [(set (match_operand:SI 0 "register_operand" "=r")
11073 (plus (match_dup 0) (const_int -32)))
11074 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
11075 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
11076 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
11077 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
11078 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
11079 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
11080 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
11081 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
11082 "TARGET_SH2A && REGNO (operands[0]) == 15"
35ed5a70 11083 "movml.l r7,@-r15"
91a19652
N
11084 [(set_attr "in_delay_slot" "no")])
11085
11086(define_insn "movml_pop_banked"
11087 [(set (match_operand:SI 0 "register_operand" "=r")
11088 (plus (match_dup 0) (const_int 32)))
11089 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
11090 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
11091 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
11092 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
11093 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
11094 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
11095 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
11096 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
11097 "TARGET_SH2A && REGNO (operands[0]) == 15"
35ed5a70 11098 "movml.l @r15+,r7"
91a19652
N
11099 [(set_attr "in_delay_slot" "no")])
11100\f
bc45ade3
SC
11101;; ------------------------------------------------------------------------
11102;; Scc instructions
11103;; ------------------------------------------------------------------------
11104
0d7e008e 11105(define_insn "movt"
73a4d10b 11106 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
f031c344 11107 (match_operand:SI 1 "t_reg_operand"))]
fa5322fa 11108 "TARGET_SH1"
1245df60
R
11109 "movt %0"
11110 [(set_attr "type" "arith")])
bc45ade3 11111
9747719a
OE
11112(define_insn "movrt"
11113 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
78ff60c1 11114 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
9747719a
OE
11115 "TARGET_SH2A"
11116 "movrt %0"
11117 [(set_attr "type" "arith")])
11118
f90b7a5a
PB
11119(define_expand "cstore4_media"
11120 [(set (match_operand:SI 0 "register_operand" "=r")
11121 (match_operator:SI 1 "sh_float_comparison_operator"
11122 [(match_operand 2 "logical_operand" "")
11123 (match_operand 3 "cmp_operand" "")]))]
11124 "TARGET_SHMEDIA"
fa5322fa 11125{
f90b7a5a
PB
11126 enum machine_mode mode = GET_MODE (operands[2]);
11127 enum rtx_code code = GET_CODE (operands[1]);
11128 bool invert, swap;
11129 if (mode == VOIDmode)
11130 mode = GET_MODE (operands[3]);
11131 if (operands[2] == const0_rtx)
fa5322fa 11132 {
f90b7a5a
PB
11133 if (code == EQ || code == NE)
11134 operands[2] = operands[3], operands[3] = const0_rtx;
fa5322fa 11135 }
f90b7a5a
PB
11136 else
11137 operands[2] = force_reg (mode, operands[2]);
11138 if (operands[3] != const0_rtx)
11139 operands[3] = force_reg (mode, operands[3]);
fa5322fa 11140
f90b7a5a 11141 switch (code)
fa5322fa 11142 {
f90b7a5a
PB
11143 case GEU:
11144 case GE:
11145 swap = invert = !FLOAT_MODE_P (mode);
11146 break;
fa5322fa 11147
f90b7a5a
PB
11148 case LEU:
11149 case LE:
11150 swap = FLOAT_MODE_P (mode), invert = !swap;
11151 break;
fa5322fa 11152
f90b7a5a
PB
11153 case LTU:
11154 case LT:
11155 swap = true, invert = false;
11156 break;
537426e7 11157
f90b7a5a
PB
11158 case GTU:
11159 case GT:
11160 case EQ:
11161 case UNORDERED:
11162 swap = invert = false;
11163 break;
537426e7 11164
f90b7a5a
PB
11165 case NE:
11166 swap = invert = true;
11167 break;
fa5322fa 11168
f90b7a5a
PB
11169 default:
11170 gcc_unreachable ();
11171 }
bc45ade3 11172
f90b7a5a 11173 if (swap)
fa5322fa 11174 {
f90b7a5a
PB
11175 rtx tem = operands[2];
11176 operands[2] = operands[3];
11177 operands[3] = tem;
11178 code = swap_condition (code);
fa5322fa 11179 }
bc45ade3 11180
f90b7a5a 11181 if (invert)
fa5322fa 11182 {
f90b7a5a
PB
11183 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
11184 code = reverse_condition (code);
11185 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11186 emit_insn (gen_cstore4_media (tem, operands[1],
11187 operands[2], operands[3]));
11188 code = EQ;
11189 operands[2] = tem;
11190 operands[3] = const0_rtx;
fa5322fa
AO
11191 }
11192
f90b7a5a 11193 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
d9241861 11194})
bc45ade3 11195
f90b7a5a
PB
11196(define_expand "cstoresi4"
11197 [(set (match_operand:SI 0 "register_operand" "=r")
11198 (match_operator:SI 1 "comparison_operator"
11199 [(match_operand:SI 2 "cmpsi_operand" "")
11200 (match_operand:SI 3 "arith_operand" "")]))]
11201 "TARGET_SH1 || TARGET_SHMEDIA"
d9241861
OE
11202{
11203 if (TARGET_SHMEDIA)
fa5322fa 11204 {
f90b7a5a
PB
11205 emit_insn (gen_cstore4_media (operands[0], operands[1],
11206 operands[2], operands[3]));
fa5322fa
AO
11207 DONE;
11208 }
bc45ade3 11209
10c17a58 11210 if (sh_expand_t_scc (operands))
f90b7a5a 11211 DONE;
537426e7 11212
f90b7a5a
PB
11213 if (! currently_expanding_to_rtl)
11214 FAIL;
11215
11216 sh_emit_compare_and_set (operands, SImode);
11217 DONE;
d9241861 11218})
bc45ade3 11219
f90b7a5a
PB
11220(define_expand "cstoredi4"
11221 [(set (match_operand:SI 0 "register_operand" "=r")
11222 (match_operator:SI 1 "comparison_operator"
11223 [(match_operand:DI 2 "arith_operand" "")
11224 (match_operand:DI 3 "arith_operand" "")]))]
11225 "TARGET_SH2 || TARGET_SHMEDIA"
d9241861
OE
11226{
11227 if (TARGET_SHMEDIA)
fa5322fa 11228 {
f90b7a5a
PB
11229 emit_insn (gen_cstore4_media (operands[0], operands[1],
11230 operands[2], operands[3]));
fa5322fa
AO
11231 DONE;
11232 }
fa5322fa 11233
10c17a58 11234 if (sh_expand_t_scc (operands))
f90b7a5a 11235 DONE;
fa5322fa 11236
f90b7a5a
PB
11237 if (! currently_expanding_to_rtl)
11238 FAIL;
11239
11240 sh_emit_compare_and_set (operands, DImode);
11241 DONE;
d9241861 11242})
fa5322fa 11243
9747719a
OE
11244;; Move the complement of the T reg to a reg.
11245;; On SH2A the movrt insn can be used.
11246;; On anything else than SH2A this has to be done with multiple instructions.
11247;; One obvious way would be:
11248;; cmp/eq ...
11249;; movt r0
11250;; xor #1,r0
11251;;
11252;; However, this puts pressure on r0 in most cases and thus the following is
11253;; more appealing:
11254;; cmp/eq ...
11255;; mov #-1,temp
11256;; negc temp,dest
11257;;
11258;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11259;; becomes a one instruction operation. Moreover, care must be taken that
11260;; the insn can still be combined with inverted compare and branch code
07c0b560
OE
11261;; around it. On the other hand, if a function returns the complement of
11262;; a previous comparison result in the T bit, the xor #1,r0 approach might
11263;; lead to better code.
8bca10f4 11264
f90b7a5a 11265(define_expand "movnegt"
07c0b560 11266 [(set (match_operand:SI 0 "arith_reg_dest" "")
78ff60c1
OE
11267 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11268 "TARGET_SH1"
8bca10f4 11269{
07c0b560 11270 if (TARGET_SH2A)
78ff60c1 11271 emit_insn (gen_movrt (operands[0], operands[1]));
07c0b560
OE
11272 else
11273 {
11274 rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
78ff60c1 11275 emit_insn (gen_movrt_negc (operands[0], operands[1], val));
07c0b560
OE
11276 }
11277 DONE;
9747719a 11278})
8bca10f4 11279
07c0b560 11280(define_insn "movrt_negc"
9747719a 11281 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
78ff60c1 11282 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
07c0b560 11283 (set (reg:SI T_REG) (const_int 1))
78ff60c1 11284 (use (match_operand:SI 2 "arith_reg_operand" "r"))]
fa5322fa 11285 "TARGET_SH1"
78ff60c1 11286 "negc %2,%0"
07c0b560
OE
11287 [(set_attr "type" "arith")])
11288
78ff60c1
OE
11289;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
11290;; pattern can be used by the combine pass. Using a scratch reg for the
11291;; -1 constant results in slightly better register allocations compared to
11292;; generating a pseudo reg before reload.
11293(define_insn_and_split "*movrt_negc"
11294 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11295 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11296 (clobber (match_scratch:SI 2 "=r"))
11297 (clobber (reg:SI T_REG))]
11298 "TARGET_SH1 && ! TARGET_SH2A"
11299 "#"
11300 "&& reload_completed"
11301 [(set (match_dup 2) (const_int -1))
11302 (parallel
11303 [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
11304 (set (reg:SI T_REG) (const_int 1))
11305 (use (match_dup 2))])])
11306
b4eca9c8
OE
11307;; Store the negated T bit in a reg using r0 and xor. This one doesn't
11308;; clobber the T bit, which is useful when storing the T bit and the
11309;; negated T bit in parallel. On SH2A the movrt insn can be used for that.
11310;; Usually we don't want this insn to be matched, except for cases where the
11311;; T bit clobber is really not appreciated. Hence the extra use on T_REG.
11312(define_insn_and_split "movrt_xor"
11313 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11314 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11315 (use (reg:SI T_REG))]
11316 "TARGET_SH1 && !TARGET_SH2A"
11317 "#"
11318 "&& reload_completed"
11319 [(set (match_dup 0) (reg:SI T_REG))
11320 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
11321
11322;; Store the T bit and the negated T bit in two regs in parallel. There is
11323;; no real insn to do that, but specifying this pattern will give combine
11324;; some opportunities.
11325(define_insn_and_split "*movt_movrt"
11326 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11327 (match_operand:SI 1 "negt_reg_operand"))
11328 (set (match_operand:SI 2 "arith_reg_dest")
11329 (match_operand:SI 3 "t_reg_operand"))])]
11330 "TARGET_SH1"
11331 "#"
11332 "&& 1"
11333 [(const_int 0)]
11334{
11335 rtx i = TARGET_SH2A
11336 ? gen_movrt (operands[0], get_t_reg_rtx ())
11337 : gen_movrt_xor (operands[0], get_t_reg_rtx ());
11338
11339 emit_insn (i);
11340 emit_insn (gen_movt (operands[2], get_t_reg_rtx ()));
11341 DONE;
11342})
11343
11344(define_insn_and_split "*movt_movrt"
11345 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11346 (match_operand:SI 1 "t_reg_operand"))
11347 (set (match_operand:SI 2 "arith_reg_dest")
11348 (match_operand:SI 3 "negt_reg_operand"))])]
11349 "TARGET_SH1"
11350 "#"
11351 "&& 1"
11352 [(parallel [(set (match_dup 2) (match_dup 3))
11353 (set (match_dup 0) (match_dup 1))])])
78ff60c1 11354
91ba65f2
OE
11355;; Use negc to store the T bit in a MSB of a reg in the following way:
11356;; T = 1: 0x80000000 -> reg
11357;; T = 0: 0x7FFFFFFF -> reg
11358;; This works because 0 - 0x80000000 = 0x80000000.
11359(define_insn_and_split "*mov_t_msb_neg"
11360 [(set (match_operand:SI 0 "arith_reg_dest")
11361 (minus:SI (const_int -2147483648) ;; 0x80000000
11362 (match_operand 1 "t_reg_operand")))
11363 (clobber (reg:SI T_REG))]
11364 "TARGET_SH1"
11365 "#"
11366 "&& can_create_pseudo_p ()"
11367 [(set (match_dup 2) (const_int -2147483648))
11368 (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
11369 (reg:SI T_REG)))
11370 (clobber (reg:SI T_REG))])]
11371{
11372 operands[2] = gen_reg_rtx (SImode);
11373})
11374
11375;; These are essentially the same as above, but with the inverted T bit.
11376;; Combine recognizes the split patterns, but does not take them sometimes
11377;; if the T_REG clobber is specified. Instead it tries to split out the
11378;; T bit negation. Since these splits are supposed to be taken only by
11379;; combine, it will see the T_REG clobber of the *mov_t_msb_neg insn, so this
11380;; should be fine.
11381(define_split
11382 [(set (match_operand:SI 0 "arith_reg_dest")
11383 (plus:SI (match_operand 1 "negt_reg_operand")
11384 (const_int 2147483647)))] ;; 0x7fffffff
11385 "TARGET_SH1 && can_create_pseudo_p ()"
11386 [(parallel [(set (match_dup 0)
11387 (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11388 (clobber (reg:SI T_REG))])])
11389
11390(define_split
11391 [(set (match_operand:SI 0 "arith_reg_dest")
11392 (if_then_else:SI (match_operand 1 "t_reg_operand")
11393 (const_int 2147483647) ;; 0x7fffffff
11394 (const_int -2147483648)))] ;; 0x80000000
11395 "TARGET_SH1 && can_create_pseudo_p ()"
11396 [(parallel [(set (match_dup 0)
11397 (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11398 (clobber (reg:SI T_REG))])])
11399
f031c344 11400;; The *negnegt pattern helps the combine pass to figure out how to fold
07c0b560
OE
11401;; an explicit double T bit negation.
11402(define_insn_and_split "*negnegt"
11403 [(set (reg:SI T_REG)
f031c344
OE
11404 (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
11405 "TARGET_SH1"
07c0b560
OE
11406 "#"
11407 ""
11408 [(const_int 0)])
11409
be8cbce1
OE
11410;; Store T bit as all zeros or ones in a reg.
11411(define_insn "mov_neg_si_t"
11412 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11413 (neg:SI (match_operand 1 "t_reg_operand" "")))]
11414 "TARGET_SH1"
11415 "subc %0,%0"
11416 [(set_attr "type" "arith")])
11417
11418;; Store negated T bit as all zeros or ones in a reg.
11419;; Use the following sequence:
11420;; subc Rn,Rn ! Rn = Rn - Rn - T; T = T
11421;; not Rn,Rn ! Rn = 0 - Rn
11422(define_split
11423 [(set (match_operand:SI 0 "arith_reg_dest" "")
11424 (neg:SI (match_operand 1 "negt_reg_operand" "")))]
11425 "TARGET_SH1"
11426 [(set (match_dup 0) (neg:SI (reg:SI T_REG)))
11427 (set (match_dup 0) (not:SI (match_dup 0)))])
11428
f031c344 11429;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
07c0b560
OE
11430(define_insn_and_split "*movtt"
11431 [(set (reg:SI T_REG)
f031c344
OE
11432 (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
11433 "TARGET_SH1"
07c0b560
OE
11434 "#"
11435 ""
11436 [(const_int 0)])
11437
cab4c510 11438(define_insn_and_split "nott"
78ff60c1
OE
11439 [(set (reg:SI T_REG)
11440 (xor:SI (match_operand:SI 0 "t_reg_operand" "") (const_int 1)))]
cab4c510
OE
11441 "TARGET_SH1"
11442{
11443 gcc_assert (TARGET_SH2A);
11444 return "nott";
11445}
11446 "! TARGET_SH2A && can_create_pseudo_p ()"
11447 [(set (match_dup 0) (reg:SI T_REG))
11448 (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
11449{
11450 operands[0] = gen_reg_rtx (SImode);
11451})
11452
78040535
OE
11453;; Store T bit as MSB in a reg.
11454;; T = 0: 0x00000000 -> reg
11455;; T = 1: 0x80000000 -> reg
11456(define_insn_and_split "*movt_msb"
11457 [(set (match_operand:SI 0 "arith_reg_dest")
11458 (mult:SI (match_operand:SI 1 "t_reg_operand")
11459 (const_int -2147483648))) ;; 0xffffffff80000000
11460 (clobber (reg:SI T_REG))]
11461 "TARGET_SH1"
11462 "#"
11463 "&& 1"
11464 [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
11465
11466;; Store inverted T bit as MSB in a reg.
11467;; T = 0: 0x80000000 -> reg
11468;; T = 1: 0x00000000 -> reg
11469;; On SH2A we can get away without clobbering the T_REG.
11470(define_insn_and_split "*negt_msb"
11471 [(set (match_operand:SI 0 "arith_reg_dest")
11472 (match_operand:SI 1 "negt_reg_shl31_operand"))]
11473 "TARGET_SH2A"
11474 "#"
11475 "&& can_create_pseudo_p ()"
11476 [(const_int 0)]
11477{
11478 rtx tmp = gen_reg_rtx (SImode);
11479 emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
11480 emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
11481 DONE;
11482})
11483
11484(define_insn_and_split "*negt_msb"
11485 [(set (match_operand:SI 0 "arith_reg_dest")
11486 (match_operand:SI 1 "negt_reg_shl31_operand"))
11487 (clobber (reg:SI T_REG))]
11488 "TARGET_SH1 && !TARGET_SH2A"
11489 "#"
11490 "&& can_create_pseudo_p ()"
11491 [(const_int 0)]
11492{
11493 rtx tmp = gen_reg_rtx (SImode);
11494 emit_move_insn (tmp, get_t_reg_rtx ());
11495 emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
11496 emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
11497 DONE;
11498})
11499
67748550
OE
11500;; The *cset_zero patterns convert optimizations such as
11501;; "if (test) x = 0;" to "x &= -(test == 0);"
11502;; back to conditional branch sequences if zero-displacement branches
11503;; are enabled.
11504;; FIXME: These patterns can be removed when conditional execution patterns
11505;; are implemented, since ifcvt will not perform these optimizations if
11506;; conditional execution is supported.
11507(define_insn "*cset_zero"
11508 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11509 (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
11510 (const_int -1))
11511 (match_operand:SI 2 "arith_reg_operand" "0")))]
11512 "TARGET_SH1 && TARGET_ZDCBRANCH"
11513{
11514 return "bf 0f" "\n"
11515 " mov #0,%0" "\n"
11516 "0:";
11517}
11518 [(set_attr "type" "arith") ;; poor approximation
11519 (set_attr "length" "4")])
11520
11521(define_insn "*cset_zero"
11522 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11523 (if_then_else:SI (match_operand:SI 1 "t_reg_operand")
11524 (match_operand:SI 2 "arith_reg_operand" "0")
11525 (const_int 0)))]
11526 "TARGET_SH1 && TARGET_ZDCBRANCH"
11527{
11528 return "bt 0f" "\n"
11529 " mov #0,%0" "\n"
11530 "0:";
11531}
11532 [(set_attr "type" "arith") ;; poor approximation
11533 (set_attr "length" "4")])
11534
f90b7a5a
PB
11535(define_expand "cstoresf4"
11536 [(set (match_operand:SI 0 "register_operand" "=r")
11537 (match_operator:SI 1 "sh_float_comparison_operator"
11538 [(match_operand:SF 2 "arith_operand" "")
11539 (match_operand:SF 3 "arith_operand" "")]))]
11540 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
d9241861
OE
11541{
11542 if (TARGET_SHMEDIA)
11543 {
11544 emit_insn (gen_cstore4_media (operands[0], operands[1],
11545 operands[2], operands[3]));
11546 DONE;
11547 }
f90b7a5a 11548
d9241861
OE
11549 if (! currently_expanding_to_rtl)
11550 FAIL;
f90b7a5a 11551
d9241861
OE
11552 sh_emit_compare_and_set (operands, SFmode);
11553 DONE;
11554})
f90b7a5a
PB
11555
11556(define_expand "cstoredf4"
11557 [(set (match_operand:SI 0 "register_operand" "=r")
11558 (match_operator:SI 1 "sh_float_comparison_operator"
11559 [(match_operand:DF 2 "arith_operand" "")
11560 (match_operand:DF 3 "arith_operand" "")]))]
11561 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
d9241861
OE
11562{
11563 if (TARGET_SHMEDIA)
11564 {
11565 emit_insn (gen_cstore4_media (operands[0], operands[1],
11566 operands[2], operands[3]));
11567 DONE;
11568 }
11569
11570 if (! currently_expanding_to_rtl)
11571 FAIL;
f90b7a5a 11572
d9241861
OE
11573 sh_emit_compare_and_set (operands, DFmode);
11574 DONE;
11575})
f90b7a5a 11576
0d7e008e
SC
11577;; -------------------------------------------------------------------------
11578;; Instructions to cope with inline literal tables
11579;; -------------------------------------------------------------------------
11580
11581; 2 byte integer in line
b9654711 11582
0d7e008e 11583(define_insn "consttable_2"
b91455de
KK
11584 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11585 (match_operand 1 "" "")]
4773afa4 11586 UNSPECV_CONST2)]
0d7e008e 11587 ""
0d7e008e 11588{
b91455de 11589 if (operands[1] != const0_rtx)
c8af3574 11590 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
d9241861
OE
11591 return "";
11592}
0d7e008e
SC
11593 [(set_attr "length" "2")
11594 (set_attr "in_delay_slot" "no")])
11595
11596; 4 byte integer in line
11597
11598(define_insn "consttable_4"
b91455de
KK
11599 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11600 (match_operand 1 "" "")]
4773afa4 11601 UNSPECV_CONST4)]
0d7e008e 11602 ""
0d7e008e 11603{
b91455de 11604 if (operands[1] != const0_rtx)
8d8f087a
KK
11605 {
11606 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
11607 mark_symbol_refs_as_used (operands[0]);
11608 }
d9241861
OE
11609 return "";
11610}
0d7e008e
SC
11611 [(set_attr "length" "4")
11612 (set_attr "in_delay_slot" "no")])
11613
11614; 8 byte integer in line
11615
11616(define_insn "consttable_8"
b91455de
KK
11617 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11618 (match_operand 1 "" "")]
4773afa4 11619 UNSPECV_CONST8)]
0d7e008e 11620 ""
0d7e008e 11621{
b91455de 11622 if (operands[1] != const0_rtx)
c8af3574 11623 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
d9241861
OE
11624 return "";
11625}
0d7e008e
SC
11626 [(set_attr "length" "8")
11627 (set_attr "in_delay_slot" "no")])
11628
3e943b59
JR
11629; 4 byte floating point
11630
11631(define_insn "consttable_sf"
b91455de
KK
11632 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
11633 (match_operand 1 "" "")]
4773afa4 11634 UNSPECV_CONST4)]
3e943b59 11635 ""
3e943b59 11636{
b91455de
KK
11637 if (operands[1] != const0_rtx)
11638 {
85654444
ZW
11639 REAL_VALUE_TYPE d;
11640 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11641 assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
b91455de 11642 }
d9241861
OE
11643 return "";
11644}
3e943b59
JR
11645 [(set_attr "length" "4")
11646 (set_attr "in_delay_slot" "no")])
11647
11648; 8 byte floating point
11649
11650(define_insn "consttable_df"
b91455de
KK
11651 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
11652 (match_operand 1 "" "")]
4773afa4 11653 UNSPECV_CONST8)]
3e943b59 11654 ""
3e943b59 11655{
b91455de
KK
11656 if (operands[1] != const0_rtx)
11657 {
85654444
ZW
11658 REAL_VALUE_TYPE d;
11659 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11660 assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
b91455de 11661 }
d9241861
OE
11662 return "";
11663}
3e943b59
JR
11664 [(set_attr "length" "8")
11665 (set_attr "in_delay_slot" "no")])
11666
1245df60
R
11667;; Alignment is needed for some constant tables; it may also be added for
11668;; Instructions at the start of loops, or after unconditional branches.
11669;; ??? We would get more accurate lengths if we did instruction
11670;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
11671;; here is too conservative.
11672
0d7e008e
SC
11673; align to a two byte boundary
11674
33f7f353 11675(define_expand "align_2"
4773afa4 11676 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
0d7e008e 11677 ""
33f7f353 11678 "")
0d7e008e
SC
11679
11680; align to a four byte boundary
1245df60
R
11681;; align_4 and align_log are instructions for the starts of loops, or
11682;; after unconditional branches, which may take up extra room.
11683
11684(define_expand "align_4"
4773afa4 11685 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
1245df60
R
11686 ""
11687 "")
11688
11689; align to a cache line boundary
0d7e008e 11690
1245df60 11691(define_insn "align_log"
4773afa4 11692 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
0d7e008e 11693 ""
33f7f353
JR
11694 ""
11695 [(set_attr "length" "0")
1245df60 11696 (set_attr "in_delay_slot" "no")])
0d7e008e
SC
11697
11698; emitted at the end of the literal table, used to emit the
11699; 32bit branch labels if needed.
11700
11701(define_insn "consttable_end"
4773afa4 11702 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
0d7e008e 11703 ""
d9241861
OE
11704{
11705 return output_jump_label_table ();
11706}
0d7e008e
SC
11707 [(set_attr "in_delay_slot" "no")])
11708
b91455de
KK
11709; emitted at the end of the window in the literal table.
11710
11711(define_insn "consttable_window_end"
11712 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
11713 ""
11714 ""
11715 [(set_attr "length" "0")
11716 (set_attr "in_delay_slot" "no")])
11717
0d7e008e
SC
11718;; -------------------------------------------------------------------------
11719;; Misc
11720;; -------------------------------------------------------------------------
11721
07a45e5c 11722;; String/block move insn.
0d7e008e 11723
70128ad9 11724(define_expand "movmemsi"
0d7e008e
SC
11725 [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
11726 (mem:BLK (match_operand:BLK 1 "" "")))
11727 (use (match_operand:SI 2 "nonmemory_operand" ""))
11728 (use (match_operand:SI 3 "immediate_operand" ""))
4773afa4
AO
11729 (clobber (reg:SI PR_REG))
11730 (clobber (reg:SI R4_REG))
11731 (clobber (reg:SI R5_REG))
11732 (clobber (reg:SI R0_REG))])]
fa5322fa 11733 "TARGET_SH1 && ! TARGET_SH5"
0d7e008e
SC
11734{
11735 if(expand_block_move (operands))
11736 DONE;
11737 else FAIL;
d9241861 11738})
0d7e008e
SC
11739
11740(define_insn "block_move_real"
4773afa4
AO
11741 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11742 (mem:BLK (reg:SI R5_REG)))
0d7e008e 11743 (use (match_operand:SI 0 "arith_reg_operand" "r"))
4773afa4
AO
11744 (clobber (reg:SI PR_REG))
11745 (clobber (reg:SI R0_REG))])]
fa5322fa 11746 "TARGET_SH1 && ! TARGET_HARD_SH4"
0d7e008e 11747 "jsr @%0%#"
22e1ebf1 11748 [(set_attr "type" "sfunc")
0d7e008e
SC
11749 (set_attr "needs_delay_slot" "yes")])
11750
11751(define_insn "block_lump_real"
4773afa4
AO
11752 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11753 (mem:BLK (reg:SI R5_REG)))
0d7e008e 11754 (use (match_operand:SI 0 "arith_reg_operand" "r"))
4773afa4
AO
11755 (use (reg:SI R6_REG))
11756 (clobber (reg:SI PR_REG))
11757 (clobber (reg:SI T_REG))
11758 (clobber (reg:SI R4_REG))
11759 (clobber (reg:SI R5_REG))
11760 (clobber (reg:SI R6_REG))
11761 (clobber (reg:SI R0_REG))])]
fa5322fa 11762 "TARGET_SH1 && ! TARGET_HARD_SH4"
225e4f43
R
11763 "jsr @%0%#"
11764 [(set_attr "type" "sfunc")
11765 (set_attr "needs_delay_slot" "yes")])
11766
11767(define_insn "block_move_real_i4"
4773afa4
AO
11768 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11769 (mem:BLK (reg:SI R5_REG)))
225e4f43 11770 (use (match_operand:SI 0 "arith_reg_operand" "r"))
4773afa4
AO
11771 (clobber (reg:SI PR_REG))
11772 (clobber (reg:SI R0_REG))
11773 (clobber (reg:SI R1_REG))
11774 (clobber (reg:SI R2_REG))])]
225e4f43
R
11775 "TARGET_HARD_SH4"
11776 "jsr @%0%#"
11777 [(set_attr "type" "sfunc")
11778 (set_attr "needs_delay_slot" "yes")])
11779
11780(define_insn "block_lump_real_i4"
4773afa4
AO
11781 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11782 (mem:BLK (reg:SI R5_REG)))
225e4f43 11783 (use (match_operand:SI 0 "arith_reg_operand" "r"))
4773afa4
AO
11784 (use (reg:SI R6_REG))
11785 (clobber (reg:SI PR_REG))
11786 (clobber (reg:SI T_REG))
11787 (clobber (reg:SI R4_REG))
11788 (clobber (reg:SI R5_REG))
11789 (clobber (reg:SI R6_REG))
11790 (clobber (reg:SI R0_REG))
11791 (clobber (reg:SI R1_REG))
11792 (clobber (reg:SI R2_REG))
11793 (clobber (reg:SI R3_REG))])]
225e4f43 11794 "TARGET_HARD_SH4"
0d7e008e 11795 "jsr @%0%#"
22e1ebf1 11796 [(set_attr "type" "sfunc")
0d7e008e 11797 (set_attr "needs_delay_slot" "yes")])
45348d9e
JW
11798\f
11799;; -------------------------------------------------------------------------
11800;; Floating point instructions.
11801;; -------------------------------------------------------------------------
11802
11803;; ??? All patterns should have a type attribute.
11804
225e4f43
R
11805(define_expand "movpsi"
11806 [(set (match_operand:PSI 0 "register_operand" "")
11807 (match_operand:PSI 1 "general_movsrc_operand" ""))]
157371cf 11808 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43
R
11809 "")
11810
11811;; The c / m alternative is a fake to guide reload to load directly into
11812;; fpscr, since reload doesn't know how to use post-increment.
1bb99877 11813;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
225e4f43
R
11814;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
11815;; predicate after reload.
c49439f1
R
11816;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
11817;; like a mac -> gpr move.
225e4f43 11818(define_insn "fpu_switch"
7144b2d8
DD
11819 [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
11820 (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
603ff6b5 11821 "TARGET_SH2E
ecfdeaeb
AO
11822 && (! reload_completed
11823 || true_regnum (operands[0]) != FPSCR_REG
f3536097 11824 || !MEM_P (operands[1])
ecfdeaeb 11825 || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
225e4f43
R
11826 "@
11827 ! precision stays the same
11828 lds.l %1,fpscr
11829 mov.l %1,%0
11830 #
11831 lds %1,fpscr
11832 mov %1,%0
11833 mov.l %1,%0
7144b2d8
DD
11834 sts fpscr,%0
11835 sts.l fpscr,%0"
11836 [(set_attr "length" "0,2,2,4,2,2,2,2,2")
78d310c2 11837 (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
225e4f43 11838
24c2fde2 11839(define_peephole2
4773afa4 11840 [(set (reg:PSI FPSCR_REG)
c1b92d09 11841 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
24c2fde2
RH
11842 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
11843 [(const_int 0)]
225e4f43 11844{
24c2fde2 11845 rtx fpscr, mem, new_insn;
57d38024 11846
24c2fde2 11847 fpscr = SET_DEST (PATTERN (curr_insn));
57d38024 11848 mem = SET_SRC (PATTERN (curr_insn));
24c2fde2
RH
11849 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
11850
11851 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
b757d36f 11852 add_reg_note (new_insn, REG_INC, operands[0]);
24c2fde2
RH
11853 DONE;
11854})
225e4f43
R
11855
11856(define_split
4773afa4 11857 [(set (reg:PSI FPSCR_REG)
c1b92d09 11858 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
24c2fde2 11859 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
6fb5fa3c 11860 && (flag_peephole2 ? epilogue_completed : reload_completed)"
24c2fde2 11861 [(const_int 0)]
225e4f43 11862{
24c2fde2 11863 rtx fpscr, mem, new_insn;
57d38024 11864
24c2fde2 11865 fpscr = SET_DEST (PATTERN (curr_insn));
57d38024 11866 mem = SET_SRC (PATTERN (curr_insn));
24c2fde2
RH
11867 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
11868
11869 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
b757d36f 11870 add_reg_note (new_insn, REG_INC, operands[0]);
24c2fde2
RH
11871
11872 if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
11873 emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
11874 DONE;
11875})
225e4f43
R
11876
11877;; ??? This uses the fp unit, but has no type indicating that.
11878;; If we did that, this would either give a bogus latency or introduce
11879;; a bogus FIFO constraint.
11880;; Since this insn is currently only used for prologues/epilogues,
11881;; it is probably best to claim no function unit, which matches the
11882;; current setting.
11883(define_insn "toggle_sz"
4773afa4
AO
11884 [(set (reg:PSI FPSCR_REG)
11885 (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
157371cf 11886 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
73774972 11887 "fschg"
78d310c2 11888 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
312209c6
AO
11889
11890;; There's no way we can use it today, since optimize mode switching
11891;; doesn't enable us to know from which mode we're switching to the
11892;; mode it requests, to tell whether we can use a relative mode switch
11893;; (like toggle_pr) or an absolute switch (like loading fpscr from
11894;; memory).
11895(define_insn "toggle_pr"
11896 [(set (reg:PSI FPSCR_REG)
11897 (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
11898 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
11899 "fpchg"
78d310c2 11900 [(set_attr "type" "fpscr_toggle")])
225e4f43
R
11901
11902(define_expand "addsf3"
fa5322fa
AO
11903 [(set (match_operand:SF 0 "arith_reg_operand" "")
11904 (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
11905 (match_operand:SF 2 "arith_reg_operand" "")))]
3a8699c7 11906 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
fa5322fa 11907{
3a8699c7 11908 if (TARGET_SH2E)
fa5322fa
AO
11909 {
11910 expand_sf_binop (&gen_addsf3_i, operands);
11911 DONE;
11912 }
d9241861 11913})
fa5322fa
AO
11914
11915(define_insn "*addsf3_media"
11916 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11917 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
11918 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
11919 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
11920 "fadd.s %1, %2, %0"
11921 [(set_attr "type" "fparith_media")])
225e4f43 11922
0ac78517
R
11923(define_insn_and_split "unary_sf_op"
11924 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11925 (vec_select:V2SF
11926 (vec_concat:V2SF
11927 (vec_select:SF
11928 (match_dup 0)
11929 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
11930 (match_operator:SF 2 "unary_float_operator"
11931 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11932 (parallel [(match_operand 4
11933 "const_int_operand" "n")]))]))
11934 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
11935 "TARGET_SHMEDIA_FPU"
11936 "#"
11937 "TARGET_SHMEDIA_FPU && reload_completed"
11938 [(set (match_dup 5) (match_dup 6))]
0ac78517
R
11939{
11940 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11941 rtx op1 = gen_rtx_REG (SFmode,
11942 (true_regnum (operands[1])
11943 + (INTVAL (operands[4]) ^ endian)));
11944
11945 operands[7] = gen_rtx_REG (SFmode,
11946 (true_regnum (operands[0])
11947 + (INTVAL (operands[3]) ^ endian)));
1c563bed 11948 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
d9241861 11949}
0ac78517
R
11950 [(set_attr "type" "fparith_media")])
11951
f8be3f56 11952(define_insn_and_split "binary_sf_op0"
0ac78517 11953 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
f8be3f56
KK
11954 (vec_concat:V2SF
11955 (match_operator:SF 3 "binary_float_operator"
11956 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11957 (parallel [(const_int 0)]))
11958 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
11959 (parallel [(const_int 0)]))])
11960 (vec_select:SF
11961 (match_dup 0)
11962 (parallel [(const_int 1)]))))]
11963 "TARGET_SHMEDIA_FPU"
11964 "#"
11965 "&& reload_completed"
11966 [(set (match_dup 4) (match_dup 5))]
f8be3f56
KK
11967{
11968 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11969 rtx op1 = gen_rtx_REG (SFmode,
11970 true_regnum (operands[1]) + endian);
11971 rtx op2 = gen_rtx_REG (SFmode,
11972 true_regnum (operands[2]) + endian);
11973
11974 operands[4] = gen_rtx_REG (SFmode,
11975 true_regnum (operands[0]) + endian);
11976 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
d9241861 11977}
f8be3f56
KK
11978 [(set_attr "type" "fparith_media")])
11979
11980(define_insn_and_split "binary_sf_op1"
11981 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11982 (vec_concat:V2SF
0ac78517
R
11983 (vec_select:SF
11984 (match_dup 0)
f8be3f56 11985 (parallel [(const_int 0)]))
0ac78517
R
11986 (match_operator:SF 3 "binary_float_operator"
11987 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
f8be3f56 11988 (parallel [(const_int 1)]))
0ac78517 11989 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
f8be3f56
KK
11990 (parallel [(const_int 1)]))])))]
11991 "TARGET_SHMEDIA_FPU"
0ac78517 11992 "#"
a93d1ba2 11993 "&& reload_completed"
f8be3f56 11994 [(set (match_dup 4) (match_dup 5))]
0ac78517
R
11995{
11996 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
d9241861
OE
11997 rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
11998 rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
0ac78517 11999
d9241861 12000 operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
f8be3f56 12001 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
d9241861 12002}
0ac78517
R
12003 [(set_attr "type" "fparith_media")])
12004
225e4f43 12005(define_insn "addsf3_i"
73a4d10b
R
12006 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12007 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12008 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
225e4f43 12009 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
3a8699c7 12010 "TARGET_SH2E"
c1aef54d 12011 "fadd %2,%0"
d64264ff
R
12012 [(set_attr "type" "fp")
12013 (set_attr "fp_mode" "single")])
45348d9e 12014
225e4f43 12015(define_expand "subsf3"
fa5322fa
AO
12016 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12017 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12018 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
3a8699c7 12019 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
fa5322fa 12020{
3a8699c7 12021 if (TARGET_SH2E)
fa5322fa
AO
12022 {
12023 expand_sf_binop (&gen_subsf3_i, operands);
12024 DONE;
12025 }
d9241861 12026})
fa5322fa
AO
12027
12028(define_insn "*subsf3_media"
12029 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12030 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12031 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12032 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12033 "fsub.s %1, %2, %0"
12034 [(set_attr "type" "fparith_media")])
225e4f43
R
12035
12036(define_insn "subsf3_i"
66c0b347
R
12037 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12038 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
12039 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
225e4f43 12040 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
3a8699c7 12041 "TARGET_SH2E"
c1aef54d 12042 "fsub %2,%0"
d64264ff
R
12043 [(set_attr "type" "fp")
12044 (set_attr "fp_mode" "single")])
45348d9e 12045
225e4f43 12046(define_expand "mulsf3"
fa5322fa
AO
12047 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12048 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12049 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
3a8699c7 12050 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
5734aefd
OE
12051{
12052 if (TARGET_SH2E)
12053 {
12054 emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2],
12055 get_fpscr_rtx ()));
12056 DONE;
12057 }
12058})
225e4f43 12059
fa5322fa
AO
12060(define_insn "*mulsf3_media"
12061 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12062 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12063 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12064 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12065 "fmul.s %1, %2, %0"
12066 [(set_attr "type" "fparith_media")])
fa5322fa 12067
5734aefd 12068(define_insn "mulsf3_i"
4b9580a5
R
12069 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12070 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
12071 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
225e4f43 12072 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
3a8699c7 12073 "TARGET_SH2E"
c1aef54d 12074 "fmul %2,%0"
d64264ff
R
12075 [(set_attr "type" "fp")
12076 (set_attr "fp_mode" "single")])
45348d9e 12077
159b4b2f
OE
12078;; FMA (fused multiply-add) patterns
12079(define_expand "fmasf4"
12080 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12081 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
12082 (match_operand:SF 2 "fp_arith_reg_operand" "")
12083 (match_operand:SF 3 "fp_arith_reg_operand" "")))]
12084 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12085{
12086 if (TARGET_SH2E)
12087 {
12088 emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
12089 operands[3], get_fpscr_rtx ()));
12090 DONE;
12091 }
12092})
fa5322fa 12093
159b4b2f 12094(define_insn "fmasf4_i"
4b9580a5 12095 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
159b4b2f
OE
12096 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
12097 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12098 (match_operand:SF 3 "fp_arith_reg_operand" "0")))
225e4f43 12099 (use (match_operand:PSI 4 "fpscr_operand" "c"))]
159b4b2f
OE
12100 "TARGET_SH2E"
12101 "fmac %1,%2,%0"
d64264ff
R
12102 [(set_attr "type" "fp")
12103 (set_attr "fp_mode" "single")])
45348d9e 12104
159b4b2f
OE
12105(define_insn "fmasf4_media"
12106 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12107 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12108 (match_operand:SF 2 "fp_arith_reg_operand" "f")
12109 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
12110 "TARGET_SHMEDIA_FPU"
12111 "fmac.s %1, %2, %0"
12112 [(set_attr "type" "fparith_media")])
12113
225e4f43 12114(define_expand "divsf3"
fa5322fa
AO
12115 [(set (match_operand:SF 0 "arith_reg_operand" "")
12116 (div:SF (match_operand:SF 1 "arith_reg_operand" "")
12117 (match_operand:SF 2 "arith_reg_operand" "")))]
3a8699c7 12118 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
fa5322fa 12119{
3a8699c7 12120 if (TARGET_SH2E)
fa5322fa
AO
12121 {
12122 expand_sf_binop (&gen_divsf3_i, operands);
12123 DONE;
12124 }
d9241861 12125})
fa5322fa
AO
12126
12127(define_insn "*divsf3_media"
12128 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12129 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
12130 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12131 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12132 "fdiv.s %1, %2, %0"
12133 [(set_attr "type" "fdiv_media")])
225e4f43
R
12134
12135(define_insn "divsf3_i"
73a4d10b 12136 [(set (match_operand:SF 0 "arith_reg_dest" "=f")
45348d9e 12137 (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
225e4f43
R
12138 (match_operand:SF 2 "arith_reg_operand" "f")))
12139 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
3a8699c7 12140 "TARGET_SH2E"
c1aef54d 12141 "fdiv %2,%0"
d64264ff
R
12142 [(set_attr "type" "fdiv")
12143 (set_attr "fp_mode" "single")])
45348d9e 12144
fa5322fa
AO
12145(define_insn "floatdisf2"
12146 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12147 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12148 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12149 "float.qs %1, %0"
12150 [(set_attr "type" "fpconv_media")])
fa5322fa 12151
1245df60 12152(define_expand "floatsisf2"
4b9580a5
R
12153 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12154 (float:SF (match_operand:SI 1 "fpul_operand" "")))]
3a8699c7 12155 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
225e4f43 12156{
157371cf 12157 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
225e4f43 12158 {
0c4c9b16 12159 emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
225e4f43
R
12160 DONE;
12161 }
d9241861 12162})
225e4f43 12163
fa5322fa
AO
12164(define_insn "*floatsisf2_media"
12165 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12166 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12167 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12168 "float.ls %1, %0"
12169 [(set_attr "type" "fpconv_media")])
fa5322fa 12170
225e4f43 12171(define_insn "floatsisf2_i4"
4b9580a5
R
12172 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12173 (float:SF (match_operand:SI 1 "fpul_operand" "y")))
0c4c9b16 12174 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12175 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
0c4c9b16 12176 "float %1,%0"
d64264ff
R
12177 [(set_attr "type" "fp")
12178 (set_attr "fp_mode" "single")])
45348d9e 12179
0f805606 12180(define_insn "*floatsisf2_ie"
4b9580a5
R
12181 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12182 (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
157371cf 12183 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
0f805606
BS
12184 "float %1,%0"
12185 [(set_attr "type" "fp")])
45348d9e 12186
fa5322fa 12187(define_insn "fix_truncsfdi2"
73a4d10b 12188 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
fa5322fa
AO
12189 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12190 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12191 "ftrc.sq %1, %0"
12192 [(set_attr "type" "fpconv_media")])
fa5322fa 12193
1245df60 12194(define_expand "fix_truncsfsi2"
4b9580a5
R
12195 [(set (match_operand:SI 0 "fpul_operand" "=y")
12196 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
3a8699c7 12197 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
225e4f43 12198{
157371cf 12199 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
225e4f43 12200 {
0c4c9b16 12201 emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
225e4f43
R
12202 DONE;
12203 }
d9241861 12204})
225e4f43 12205
fa5322fa
AO
12206(define_insn "*fix_truncsfsi2_media"
12207 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12208 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12209 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12210 "ftrc.sl %1, %0"
12211 [(set_attr "type" "fpconv_media")])
fa5322fa 12212
225e4f43 12213(define_insn "fix_truncsfsi2_i4"
4b9580a5
R
12214 [(set (match_operand:SI 0 "fpul_operand" "=y")
12215 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
0c4c9b16 12216 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12217 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
0c4c9b16 12218 "ftrc %1,%0"
c49439f1 12219 [(set_attr "type" "ftrc_s")
d64264ff 12220 (set_attr "fp_mode" "single")])
225e4f43 12221
0c4c9b16
BS
12222;; ??? This pattern is used nowhere. fix_truncsfsi2 always expands to
12223;; fix_truncsfsi2_i4.
12224;; (define_insn "fix_truncsfsi2_i4_2"
12225;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12226;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
5d00b10a 12227;; (use (reg:PSI FPSCR_REG))
4773afa4 12228;; (clobber (reg:SI FPUL_REG))]
0c4c9b16
BS
12229;; "TARGET_SH4"
12230;; "#"
12231;; [(set_attr "length" "4")
12232;; (set_attr "fp_mode" "single")])
12233
12234;;(define_split
12235;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12236;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12237;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
4773afa4 12238;; (clobber (reg:SI FPUL_REG))]
0c4c9b16 12239;; "TARGET_SH4"
4773afa4 12240;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
0c4c9b16 12241;; (use (match_dup 2))])
4773afa4 12242;; (set (match_dup 0) (reg:SI FPUL_REG))])
45348d9e 12243
1245df60 12244(define_insn "*fixsfsi"
4b9580a5
R
12245 [(set (match_operand:SI 0 "fpul_operand" "=y")
12246 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
157371cf 12247 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
0c4c9b16 12248 "ftrc %1,%0"
1245df60 12249 [(set_attr "type" "fp")])
45348d9e 12250
1245df60 12251(define_insn "cmpgtsf_t"
4773afa4
AO
12252 [(set (reg:SI T_REG)
12253 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12254 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
157371cf 12255 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
c1aef54d 12256 "fcmp/gt %1,%0"
78d310c2 12257 [(set_attr "type" "fp_cmp")
d64264ff 12258 (set_attr "fp_mode" "single")])
45348d9e 12259
1245df60 12260(define_insn "cmpeqsf_t"
4773afa4
AO
12261 [(set (reg:SI T_REG)
12262 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12263 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
157371cf 12264 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
c1aef54d 12265 "fcmp/eq %1,%0"
78d310c2 12266 [(set_attr "type" "fp_cmp")
d64264ff 12267 (set_attr "fp_mode" "single")])
45348d9e 12268
1245df60 12269(define_insn "ieee_ccmpeqsf_t"
4773afa4
AO
12270 [(set (reg:SI T_REG)
12271 (ior:SI (reg:SI T_REG)
4b9580a5
R
12272 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12273 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
157371cf 12274 "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
d9241861
OE
12275{
12276 return output_ieee_ccmpeq (insn, operands);
12277}
1245df60
R
12278 [(set_attr "length" "4")])
12279
12280
225e4f43 12281(define_insn "cmpgtsf_t_i4"
4773afa4
AO
12282 [(set (reg:SI T_REG)
12283 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12284 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
225e4f43 12285 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12286 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
225e4f43 12287 "fcmp/gt %1,%0"
78d310c2 12288 [(set_attr "type" "fp_cmp")
d64264ff 12289 (set_attr "fp_mode" "single")])
225e4f43
R
12290
12291(define_insn "cmpeqsf_t_i4"
4773afa4
AO
12292 [(set (reg:SI T_REG)
12293 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12294 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
225e4f43 12295 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12296 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
225e4f43 12297 "fcmp/eq %1,%0"
78d310c2 12298 [(set_attr "type" "fp_cmp")
d64264ff 12299 (set_attr "fp_mode" "single")])
225e4f43
R
12300
12301(define_insn "*ieee_ccmpeqsf_t_4"
4773afa4
AO
12302 [(set (reg:SI T_REG)
12303 (ior:SI (reg:SI T_REG)
4b9580a5
R
12304 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12305 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
225e4f43 12306 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12307 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
d9241861
OE
12308{
12309 return output_ieee_ccmpeq (insn, operands);
12310}
d64264ff
R
12311 [(set_attr "length" "4")
12312 (set_attr "fp_mode" "single")])
225e4f43 12313
fa5322fa 12314(define_insn "cmpeqsf_media"
73a4d10b
R
12315 [(set (match_operand:SI 0 "register_operand" "=r")
12316 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12317 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12318 "TARGET_SHMEDIA_FPU"
12319 "fcmpeq.s %1, %2, %0"
12320 [(set_attr "type" "fcmp_media")])
12321
fa5322fa 12322(define_insn "cmpgtsf_media"
537426e7
KK
12323 [(set (match_operand:SI 0 "register_operand" "=r")
12324 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
fa5322fa
AO
12325 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12326 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12327 "fcmpgt.s %1, %2, %0"
12328 [(set_attr "type" "fcmp_media")])
fa5322fa
AO
12329
12330(define_insn "cmpgesf_media"
537426e7
KK
12331 [(set (match_operand:SI 0 "register_operand" "=r")
12332 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
fa5322fa
AO
12333 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12334 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12335 "fcmpge.s %1, %2, %0"
12336 [(set_attr "type" "fcmp_media")])
fa5322fa
AO
12337
12338(define_insn "cmpunsf_media"
537426e7
KK
12339 [(set (match_operand:SI 0 "register_operand" "=r")
12340 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
fa5322fa
AO
12341 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12342 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12343 "fcmpun.s %1, %2, %0"
12344 [(set_attr "type" "fcmp_media")])
fa5322fa 12345
f90b7a5a
PB
12346(define_expand "cbranchsf4"
12347 [(set (pc)
12348 (if_then_else (match_operator 0 "sh_float_comparison_operator"
12349 [(match_operand:SF 1 "arith_operand" "")
12350 (match_operand:SF 2 "arith_operand" "")])
12351 (match_operand 3 "" "")
12352 (pc)))]
3a8699c7 12353 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
45348d9e 12354{
f90b7a5a
PB
12355 if (TARGET_SHMEDIA)
12356 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12357 operands[3]));
12358 else
12359 sh_emit_compare_and_branch (operands, SFmode);
45348d9e 12360 DONE;
d9241861 12361})
b9654711 12362
225e4f43 12363(define_expand "negsf2"
fa5322fa
AO
12364 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12365 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
3a8699c7 12366 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
fa5322fa 12367{
3a8699c7 12368 if (TARGET_SH2E)
fa5322fa
AO
12369 {
12370 expand_sf_unop (&gen_negsf2_i, operands);
12371 DONE;
12372 }
d9241861 12373})
fa5322fa
AO
12374
12375(define_insn "*negsf2_media"
12376 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12377 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12378 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12379 "fneg.s %1, %0"
12380 [(set_attr "type" "fmove_media")])
225e4f43
R
12381
12382(define_insn "negsf2_i"
4b9580a5
R
12383 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12384 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
225e4f43 12385 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
3a8699c7 12386 "TARGET_SH2E"
c1aef54d 12387 "fneg %0"
d64264ff
R
12388 [(set_attr "type" "fmove")
12389 (set_attr "fp_mode" "single")])
45348d9e 12390
225e4f43 12391(define_expand "sqrtsf2"
fa5322fa
AO
12392 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12393 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12394 "TARGET_SH3E || TARGET_SHMEDIA_FPU"
fa5322fa
AO
12395{
12396 if (TARGET_SH3E)
12397 {
12398 expand_sf_unop (&gen_sqrtsf2_i, operands);
12399 DONE;
12400 }
d9241861 12401})
fa5322fa
AO
12402
12403(define_insn "*sqrtsf2_media"
12404 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12405 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12406 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12407 "fsqrt.s %1, %0"
12408 [(set_attr "type" "fdiv_media")])
225e4f43
R
12409
12410(define_insn "sqrtsf2_i"
4b9580a5
R
12411 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12412 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
225e4f43 12413 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
45348d9e 12414 "TARGET_SH3E"
c1aef54d 12415 "fsqrt %0"
d64264ff
R
12416 [(set_attr "type" "fdiv")
12417 (set_attr "fp_mode" "single")])
45348d9e 12418
312209c6
AO
12419(define_insn "rsqrtsf2"
12420 [(set (match_operand:SF 0 "register_operand" "=f")
12421 (div:SF (match_operand:SF 1 "immediate_operand" "i")
12422 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
12423 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
aba92f5f 12424 "TARGET_FPU_ANY && TARGET_FSRRA
312209c6
AO
12425 && operands[1] == CONST1_RTX (SFmode)"
12426 "fsrra %0"
12427 [(set_attr "type" "fsrra")
12428 (set_attr "fp_mode" "single")])
12429
aba92f5f
OE
12430;; When the sincos pattern is defined, the builtin functions sin and cos
12431;; will be expanded to the sincos pattern and one of the output values will
12432;; remain unused.
12433(define_expand "sincossf3"
dfa228f0
OE
12434 [(set (match_operand:SF 0 "nonimmediate_operand")
12435 (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
12436 (set (match_operand:SF 1 "nonimmediate_operand")
12437 (unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
aba92f5f 12438 "TARGET_FPU_ANY && TARGET_FSCA"
312209c6
AO
12439{
12440 rtx scaled = gen_reg_rtx (SFmode);
12441 rtx truncated = gen_reg_rtx (SImode);
12442 rtx fsca = gen_reg_rtx (V2SFmode);
12443 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
12444
aba92f5f 12445 emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
312209c6
AO
12446 emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
12447 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
12448 get_fpscr_rtx ()));
312209c6 12449
dfa228f0
OE
12450 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
12451 emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
312209c6 12452 DONE;
d9241861 12453})
312209c6 12454
db292b0e
OE
12455(define_insn_and_split "fsca"
12456 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12457 (vec_concat:V2SF
12458 (unspec:SF [(mult:SF
12459 (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
12460 (match_operand:SF 2 "fsca_scale_factor" "i"))
12461 ] UNSPEC_FSINA)
12462 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
12463 ] UNSPEC_FCOSA)))
12464 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12465 "TARGET_FPU_ANY && TARGET_FSCA"
12466 "fsca fpul,%d0"
12467 "&& !fpul_operand (operands[1], SImode)"
12468 [(const_int 0)]
12469{
12470 /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
12471 to a simple reg, otherwise reload will have trouble reloading the
12472 pseudo into fpul. */
12473 rtx x = XEXP (operands[1], 0);
12474 while (x != NULL_RTX && !fpul_operand (x, SImode))
12475 {
12476 gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
12477 x = XEXP (x, 0);
12478 }
12479
12480 gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
12481 emit_insn (gen_fsca (operands[0], x, operands[2], operands[3]));
12482 DONE;
12483}
12484 [(set_attr "type" "fsca")
12485 (set_attr "fp_mode" "single")])
12486
225e4f43 12487(define_expand "abssf2"
fa5322fa
AO
12488 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12489 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
3a8699c7 12490 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
fa5322fa 12491{
3a8699c7 12492 if (TARGET_SH2E)
fa5322fa
AO
12493 {
12494 expand_sf_unop (&gen_abssf2_i, operands);
12495 DONE;
12496 }
d9241861 12497})
fa5322fa
AO
12498
12499(define_insn "*abssf2_media"
12500 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12501 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12502 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12503 "fabs.s %1, %0"
12504 [(set_attr "type" "fmove_media")])
225e4f43
R
12505
12506(define_insn "abssf2_i"
4b9580a5
R
12507 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12508 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
225e4f43 12509 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
3a8699c7 12510 "TARGET_SH2E"
c1aef54d 12511 "fabs %0"
d64264ff
R
12512 [(set_attr "type" "fmove")
12513 (set_attr "fp_mode" "single")])
225e4f43
R
12514
12515(define_expand "adddf3"
fa5322fa
AO
12516 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12517 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12518 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
157371cf 12519 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
fa5322fa 12520{
157371cf 12521 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12522 {
12523 expand_df_binop (&gen_adddf3_i, operands);
12524 DONE;
12525 }
d9241861 12526})
fa5322fa
AO
12527
12528(define_insn "*adddf3_media"
12529 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12530 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12531 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12532 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12533 "fadd.d %1, %2, %0"
12534 [(set_attr "type" "dfparith_media")])
225e4f43
R
12535
12536(define_insn "adddf3_i"
4b9580a5
R
12537 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12538 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12539 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
225e4f43 12540 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
157371cf 12541 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43 12542 "fadd %2,%0"
d64264ff
R
12543 [(set_attr "type" "dfp_arith")
12544 (set_attr "fp_mode" "double")])
225e4f43
R
12545
12546(define_expand "subdf3"
fa5322fa
AO
12547 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12548 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12549 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
157371cf 12550 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
fa5322fa 12551{
157371cf 12552 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12553 {
12554 expand_df_binop (&gen_subdf3_i, operands);
12555 DONE;
12556 }
d9241861 12557})
fa5322fa
AO
12558
12559(define_insn "*subdf3_media"
12560 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12561 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12562 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12563 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12564 "fsub.d %1, %2, %0"
12565 [(set_attr "type" "dfparith_media")])
225e4f43
R
12566
12567(define_insn "subdf3_i"
4b9580a5
R
12568 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12569 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12570 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
225e4f43 12571 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
157371cf 12572 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43 12573 "fsub %2,%0"
d64264ff
R
12574 [(set_attr "type" "dfp_arith")
12575 (set_attr "fp_mode" "double")])
225e4f43
R
12576
12577(define_expand "muldf3"
fa5322fa
AO
12578 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12579 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12580 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
157371cf 12581 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
fa5322fa 12582{
157371cf 12583 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12584 {
12585 expand_df_binop (&gen_muldf3_i, operands);
12586 DONE;
12587 }
d9241861 12588})
fa5322fa
AO
12589
12590(define_insn "*muldf3_media"
12591 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12592 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12593 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12594 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12595 "fmul.d %1, %2, %0"
12596 [(set_attr "type" "dfmul_media")])
225e4f43
R
12597
12598(define_insn "muldf3_i"
4b9580a5
R
12599 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12600 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12601 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
225e4f43 12602 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
157371cf 12603 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43 12604 "fmul %2,%0"
78d310c2 12605 [(set_attr "type" "dfp_mul")
d64264ff 12606 (set_attr "fp_mode" "double")])
225e4f43
R
12607
12608(define_expand "divdf3"
fa5322fa
AO
12609 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12610 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12611 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
157371cf 12612 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
fa5322fa 12613{
157371cf 12614 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12615 {
12616 expand_df_binop (&gen_divdf3_i, operands);
12617 DONE;
12618 }
d9241861 12619})
fa5322fa
AO
12620
12621(define_insn "*divdf3_media"
12622 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12623 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12624 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12625 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12626 "fdiv.d %1, %2, %0"
12627 [(set_attr "type" "dfdiv_media")])
225e4f43
R
12628
12629(define_insn "divdf3_i"
4b9580a5
R
12630 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12631 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12632 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
225e4f43 12633 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
157371cf 12634 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43 12635 "fdiv %2,%0"
d64264ff
R
12636 [(set_attr "type" "dfdiv")
12637 (set_attr "fp_mode" "double")])
225e4f43 12638
fa5322fa
AO
12639(define_insn "floatdidf2"
12640 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12641 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12642 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12643 "float.qd %1, %0"
12644 [(set_attr "type" "dfpconv_media")])
fa5322fa 12645
225e4f43 12646(define_expand "floatsidf2"
fa5322fa
AO
12647 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12648 (float:DF (match_operand:SI 1 "fpul_operand" "")))]
157371cf 12649 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
225e4f43 12650{
157371cf 12651 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12652 {
12653 emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
12654 get_fpscr_rtx ()));
12655 DONE;
12656 }
d9241861 12657})
225e4f43 12658
fa5322fa
AO
12659(define_insn "*floatsidf2_media"
12660 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12661 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12662 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12663 "float.ld %1, %0"
12664 [(set_attr "type" "dfpconv_media")])
fa5322fa 12665
225e4f43 12666(define_insn "floatsidf2_i"
4b9580a5
R
12667 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12668 (float:DF (match_operand:SI 1 "fpul_operand" "y")))
0c4c9b16 12669 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12670 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
0c4c9b16 12671 "float %1,%0"
d64264ff
R
12672 [(set_attr "type" "dfp_conv")
12673 (set_attr "fp_mode" "double")])
225e4f43 12674
fa5322fa 12675(define_insn "fix_truncdfdi2"
73a4d10b 12676 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
fa5322fa
AO
12677 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12678 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12679 "ftrc.dq %1, %0"
12680 [(set_attr "type" "dfpconv_media")])
fa5322fa 12681
225e4f43 12682(define_expand "fix_truncdfsi2"
fa5322fa
AO
12683 [(set (match_operand:SI 0 "fpul_operand" "")
12684 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
157371cf 12685 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
225e4f43 12686{
157371cf 12687 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12688 {
12689 emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
12690 get_fpscr_rtx ()));
12691 DONE;
12692 }
d9241861 12693})
225e4f43 12694
fa5322fa
AO
12695(define_insn "*fix_truncdfsi2_media"
12696 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12697 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12698 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12699 "ftrc.dl %1, %0"
12700 [(set_attr "type" "dfpconv_media")])
fa5322fa 12701
225e4f43 12702(define_insn "fix_truncdfsi2_i"
4b9580a5
R
12703 [(set (match_operand:SI 0 "fpul_operand" "=y")
12704 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
0c4c9b16 12705 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12706 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
0c4c9b16
BS
12707 "ftrc %1,%0"
12708 [(set_attr "type" "dfp_conv")
c49439f1 12709 (set_attr "dfp_comp" "no")
d64264ff 12710 (set_attr "fp_mode" "double")])
225e4f43 12711
0c4c9b16
BS
12712;; ??? This pattern is used nowhere. fix_truncdfsi2 always expands to
12713;; fix_truncdfsi2_i.
12714;; (define_insn "fix_truncdfsi2_i4"
12715;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12716;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
12717;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
4773afa4 12718;; (clobber (reg:SI FPUL_REG))]
0c4c9b16
BS
12719;; "TARGET_SH4"
12720;; "#"
12721;; [(set_attr "length" "4")
12722;; (set_attr "fp_mode" "double")])
52702ae1 12723;;
0c4c9b16
BS
12724;; (define_split
12725;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12726;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
12727;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
4773afa4 12728;; (clobber (reg:SI FPUL_REG))]
0c4c9b16 12729;; "TARGET_SH4"
4773afa4 12730;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
0c4c9b16 12731;; (use (match_dup 2))])
4773afa4 12732;; (set (match_dup 0) (reg:SI FPUL_REG))])
225e4f43
R
12733
12734(define_insn "cmpgtdf_t"
4773afa4
AO
12735 [(set (reg:SI T_REG)
12736 (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
12737 (match_operand:DF 1 "arith_reg_operand" "f")))
225e4f43 12738 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12739 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43 12740 "fcmp/gt %1,%0"
d64264ff
R
12741 [(set_attr "type" "dfp_cmp")
12742 (set_attr "fp_mode" "double")])
225e4f43
R
12743
12744(define_insn "cmpeqdf_t"
4773afa4
AO
12745 [(set (reg:SI T_REG)
12746 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
12747 (match_operand:DF 1 "arith_reg_operand" "f")))
225e4f43 12748 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12749 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43 12750 "fcmp/eq %1,%0"
d64264ff
R
12751 [(set_attr "type" "dfp_cmp")
12752 (set_attr "fp_mode" "double")])
225e4f43
R
12753
12754(define_insn "*ieee_ccmpeqdf_t"
4773afa4
AO
12755 [(set (reg:SI T_REG)
12756 (ior:SI (reg:SI T_REG)
12757 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
12758 (match_operand:DF 1 "arith_reg_operand" "f"))))
225e4f43 12759 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12760 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
d9241861
OE
12761{
12762 return output_ieee_ccmpeq (insn, operands);
12763}
d64264ff
R
12764 [(set_attr "length" "4")
12765 (set_attr "fp_mode" "double")])
52702ae1 12766
fa5322fa 12767(define_insn "cmpeqdf_media"
73a4d10b
R
12768 [(set (match_operand:SI 0 "register_operand" "=r")
12769 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12770 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12771 "TARGET_SHMEDIA_FPU"
12772 "fcmpeq.d %1,%2,%0"
12773 [(set_attr "type" "fcmp_media")])
12774
fa5322fa 12775(define_insn "cmpgtdf_media"
537426e7
KK
12776 [(set (match_operand:SI 0 "register_operand" "=r")
12777 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
fa5322fa
AO
12778 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12779 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12780 "fcmpgt.d %1,%2,%0"
12781 [(set_attr "type" "fcmp_media")])
fa5322fa
AO
12782
12783(define_insn "cmpgedf_media"
537426e7
KK
12784 [(set (match_operand:SI 0 "register_operand" "=r")
12785 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
fa5322fa
AO
12786 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12787 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12788 "fcmpge.d %1,%2,%0"
12789 [(set_attr "type" "fcmp_media")])
fa5322fa
AO
12790
12791(define_insn "cmpundf_media"
537426e7
KK
12792 [(set (match_operand:SI 0 "register_operand" "=r")
12793 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
fa5322fa
AO
12794 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12795 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12796 "fcmpun.d %1,%2,%0"
12797 [(set_attr "type" "fcmp_media")])
fa5322fa 12798
f90b7a5a
PB
12799(define_expand "cbranchdf4"
12800 [(set (pc)
12801 (if_then_else (match_operator 0 "sh_float_comparison_operator"
12802 [(match_operand:DF 1 "arith_operand" "")
12803 (match_operand:DF 2 "arith_operand" "")])
12804 (match_operand 3 "" "")
12805 (pc)))]
157371cf 12806 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
225e4f43 12807{
f90b7a5a
PB
12808 if (TARGET_SHMEDIA)
12809 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12810 operands[3]));
12811 else
12812 sh_emit_compare_and_branch (operands, DFmode);
225e4f43 12813 DONE;
d9241861 12814})
225e4f43 12815
f90b7a5a 12816
225e4f43 12817(define_expand "negdf2"
fa5322fa
AO
12818 [(set (match_operand:DF 0 "arith_reg_operand" "")
12819 (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
157371cf 12820 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
fa5322fa 12821{
157371cf 12822 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12823 {
12824 expand_df_unop (&gen_negdf2_i, operands);
12825 DONE;
12826 }
d9241861 12827})
fa5322fa
AO
12828
12829(define_insn "*negdf2_media"
12830 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12831 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12832 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12833 "fneg.d %1, %0"
12834 [(set_attr "type" "fmove_media")])
225e4f43
R
12835
12836(define_insn "negdf2_i"
73a4d10b
R
12837 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12838 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
225e4f43 12839 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12840 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43 12841 "fneg %0"
d64264ff
R
12842 [(set_attr "type" "fmove")
12843 (set_attr "fp_mode" "double")])
225e4f43
R
12844
12845(define_expand "sqrtdf2"
fa5322fa
AO
12846 [(set (match_operand:DF 0 "arith_reg_operand" "")
12847 (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
157371cf 12848 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
fa5322fa 12849{
157371cf 12850 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12851 {
12852 expand_df_unop (&gen_sqrtdf2_i, operands);
12853 DONE;
12854 }
d9241861 12855})
fa5322fa
AO
12856
12857(define_insn "*sqrtdf2_media"
12858 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12859 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12860 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12861 "fsqrt.d %1, %0"
12862 [(set_attr "type" "dfdiv_media")])
225e4f43
R
12863
12864(define_insn "sqrtdf2_i"
73a4d10b
R
12865 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12866 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
225e4f43 12867 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12868 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43 12869 "fsqrt %0"
d64264ff
R
12870 [(set_attr "type" "dfdiv")
12871 (set_attr "fp_mode" "double")])
225e4f43
R
12872
12873(define_expand "absdf2"
fa5322fa
AO
12874 [(set (match_operand:DF 0 "arith_reg_operand" "")
12875 (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
157371cf 12876 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
fa5322fa 12877{
157371cf 12878 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12879 {
12880 expand_df_unop (&gen_absdf2_i, operands);
12881 DONE;
12882 }
d9241861 12883})
fa5322fa
AO
12884
12885(define_insn "*absdf2_media"
12886 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12887 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12888 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12889 "fabs.d %1, %0"
12890 [(set_attr "type" "fmove_media")])
225e4f43
R
12891
12892(define_insn "absdf2_i"
73a4d10b
R
12893 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12894 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
225e4f43 12895 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12896 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
225e4f43 12897 "fabs %0"
d64264ff
R
12898 [(set_attr "type" "fmove")
12899 (set_attr "fp_mode" "double")])
225e4f43
R
12900
12901(define_expand "extendsfdf2"
fa5322fa
AO
12902 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12903 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
157371cf 12904 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
225e4f43 12905{
157371cf 12906 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12907 {
12908 emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
12909 get_fpscr_rtx ()));
12910 DONE;
12911 }
d9241861 12912})
225e4f43 12913
fa5322fa
AO
12914(define_insn "*extendsfdf2_media"
12915 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12916 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12917 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12918 "fcnv.sd %1, %0"
12919 [(set_attr "type" "dfpconv_media")])
fa5322fa 12920
225e4f43 12921(define_insn "extendsfdf2_i4"
4b9580a5
R
12922 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12923 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
0c4c9b16 12924 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12925 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
0c4c9b16 12926 "fcnvsd %1,%0"
d64264ff
R
12927 [(set_attr "type" "fp")
12928 (set_attr "fp_mode" "double")])
225e4f43
R
12929
12930(define_expand "truncdfsf2"
fa5322fa
AO
12931 [(set (match_operand:SF 0 "fpul_operand" "")
12932 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
157371cf 12933 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
225e4f43 12934{
157371cf 12935 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
fa5322fa
AO
12936 {
12937 emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
12938 get_fpscr_rtx ()));
12939 DONE;
12940 }
d9241861 12941})
225e4f43 12942
fa5322fa
AO
12943(define_insn "*truncdfsf2_media"
12944 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12945 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12946 "TARGET_SHMEDIA_FPU"
2ad65b0e
SC
12947 "fcnv.ds %1, %0"
12948 [(set_attr "type" "dfpconv_media")])
fa5322fa 12949
225e4f43 12950(define_insn "truncdfsf2_i4"
4b9580a5
R
12951 [(set (match_operand:SF 0 "fpul_operand" "=y")
12952 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
0c4c9b16 12953 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
157371cf 12954 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
0c4c9b16 12955 "fcnvds %1,%0"
d64264ff
R
12956 [(set_attr "type" "fp")
12957 (set_attr "fp_mode" "double")])
45348d9e 12958\f
725de644
JW
12959;; Bit field extract patterns. These give better code for packed bitfields,
12960;; because they allow auto-increment addresses to be generated.
12961
12962(define_expand "insv"
12963 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
12964 (match_operand:SI 1 "immediate_operand" "")
12965 (match_operand:SI 2 "immediate_operand" ""))
12966 (match_operand:SI 3 "general_operand" ""))]
fa5322fa 12967 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
725de644 12968{
a7f52356 12969 rtx addr_target, orig_address, shift_reg, qi_val;
45dc67b7 12970 HOST_WIDE_INT bitsize, size, v = 0;
a7f52356 12971 rtx x = operands[3];
725de644 12972
9eb3a0dd
N
12973 if (TARGET_SH2A && TARGET_BITOPS
12974 && (satisfies_constraint_Sbw (operands[0])
12975 || satisfies_constraint_Sbv (operands[0]))
12976 && satisfies_constraint_M (operands[1])
12977 && satisfies_constraint_K03 (operands[2]))
12978 {
12979 if (satisfies_constraint_N (operands[3]))
12980 {
12981 emit_insn (gen_bclr_m2a (operands[0], operands[2]));
12982 DONE;
12983 }
12984 else if (satisfies_constraint_M (operands[3]))
12985 {
12986 emit_insn (gen_bset_m2a (operands[0], operands[2]));
12987 DONE;
12988 }
12989 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
12990 && satisfies_constraint_M (operands[1]))
12991 {
12992 emit_insn (gen_bst_m2a (operands[0], operands[2]));
12993 DONE;
12994 }
12995 else if (REG_P (operands[3])
12996 && satisfies_constraint_M (operands[1]))
12997 {
12998 emit_insn (gen_bld_reg (operands[3], const0_rtx));
12999 emit_insn (gen_bst_m2a (operands[0], operands[2]));
13000 DONE;
13001 }
13002 }
725de644
JW
13003 /* ??? expmed doesn't care for non-register predicates. */
13004 if (! memory_operand (operands[0], VOIDmode)
13005 || ! immediate_operand (operands[1], VOIDmode)
13006 || ! immediate_operand (operands[2], VOIDmode)
a7f52356 13007 || ! general_operand (x, VOIDmode))
725de644
JW
13008 FAIL;
13009 /* If this isn't a 16 / 24 / 32 bit field, or if
13010 it doesn't start on a byte boundary, then fail. */
a7f52356
R
13011 bitsize = INTVAL (operands[1]);
13012 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
725de644
JW
13013 || (INTVAL (operands[2]) % 8) != 0)
13014 FAIL;
13015
a7f52356 13016 size = bitsize / 8;
725de644 13017 orig_address = XEXP (operands[0], 0);
725de644 13018 shift_reg = gen_reg_rtx (SImode);
f3536097 13019 if (CONST_INT_P (x))
a7f52356
R
13020 {
13021 v = INTVAL (x);
13022 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
13023 }
13024 else
13025 {
13026 emit_insn (gen_movsi (shift_reg, operands[3]));
13027 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13028 }
0a81f074
RS
13029 addr_target = copy_addr_to_reg (plus_constant (Pmode,
13030 orig_address, size - 1));
725de644 13031
792760b9 13032 operands[0] = replace_equiv_address (operands[0], addr_target);
a7f52356 13033 emit_insn (gen_movqi (operands[0], qi_val));
725de644
JW
13034
13035 while (size -= 1)
13036 {
f3536097 13037 if (CONST_INT_P (x))
a7f52356
R
13038 qi_val
13039 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
13040 else
13041 {
13042 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
13043 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13044 }
a556fd39 13045 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
a7f52356 13046 emit_insn (gen_movqi (operands[0], qi_val));
725de644
JW
13047 }
13048
13049 DONE;
d9241861 13050})
312209c6
AO
13051
13052(define_insn "movua"
13053 [(set (match_operand:SI 0 "register_operand" "=z")
85144c5c
RS
13054 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
13055 UNSPEC_MOVUA))]
312209c6
AO
13056 "TARGET_SH4A_ARCH"
13057 "movua.l %1,%0"
13058 [(set_attr "type" "movua")])
13059
13060;; We shouldn't need this, but cse replaces increments with references
13061;; to other regs before flow has a chance to create post_inc
13062;; addressing modes, and only postreload's cse_move2add brings the
13063;; increments back to a usable form.
13064(define_peephole2
13065 [(set (match_operand:SI 0 "register_operand" "")
13066 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
13067 (const_int 32) (const_int 0)))
13068 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13069 "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
13070 [(set (match_operand:SI 0 "register_operand" "")
13071 (sign_extract:SI (mem:SI (post_inc:SI
13072 (match_operand:SI 1 "register_operand" "")))
13073 (const_int 32) (const_int 0)))]
13074 "")
13075
13076(define_expand "extv"
13077 [(set (match_operand:SI 0 "register_operand" "")
13078 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13079 (match_operand 2 "const_int_operand" "")
13080 (match_operand 3 "const_int_operand" "")))]
9eb3a0dd 13081 "TARGET_SH4A_ARCH || TARGET_SH2A"
312209c6 13082{
9eb3a0dd
N
13083 if (TARGET_SH2A && TARGET_BITOPS
13084 && (satisfies_constraint_Sbw (operands[1])
13085 || satisfies_constraint_Sbv (operands[1]))
13086 && satisfies_constraint_M (operands[2])
13087 && satisfies_constraint_K03 (operands[3]))
13088 {
13089 emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
13090 if (REGNO (operands[0]) != T_REG)
13091 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13092 DONE;
13093 }
312209c6
AO
13094 if (TARGET_SH4A_ARCH
13095 && INTVAL (operands[2]) == 32
2c62c8ec 13096 && INTVAL (operands[3]) == 0
f3536097 13097 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
312209c6 13098 {
85144c5c 13099 rtx src = adjust_address (operands[1], BLKmode, 0);
f5541398 13100 set_mem_size (src, 4);
85144c5c 13101 emit_insn (gen_movua (operands[0], src));
312209c6
AO
13102 DONE;
13103 }
13104
13105 FAIL;
13106})
13107
13108(define_expand "extzv"
13109 [(set (match_operand:SI 0 "register_operand" "")
13110 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
13111 (match_operand 2 "const_int_operand" "")
13112 (match_operand 3 "const_int_operand" "")))]
9eb3a0dd 13113 "TARGET_SH4A_ARCH || TARGET_SH2A"
312209c6 13114{
9eb3a0dd
N
13115 if (TARGET_SH2A && TARGET_BITOPS
13116 && (satisfies_constraint_Sbw (operands[1])
13117 || satisfies_constraint_Sbv (operands[1]))
13118 && satisfies_constraint_M (operands[2])
13119 && satisfies_constraint_K03 (operands[3]))
13120 {
13121 emit_insn (gen_bld_m2a (operands[1], operands[3]));
13122 if (REGNO (operands[0]) != T_REG)
13123 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
13124 DONE;
13125 }
312209c6
AO
13126 if (TARGET_SH4A_ARCH
13127 && INTVAL (operands[2]) == 32
2c62c8ec 13128 && INTVAL (operands[3]) == 0
f3536097 13129 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
312209c6 13130 {
85144c5c 13131 rtx src = adjust_address (operands[1], BLKmode, 0);
f5541398 13132 set_mem_size (src, 4);
85144c5c 13133 emit_insn (gen_movua (operands[0], src));
312209c6
AO
13134 DONE;
13135 }
13136
13137 FAIL;
13138})
13139
9eb3a0dd
N
13140;; SH2A instructions for bitwise operations.
13141
13142;; Clear a bit in a memory location.
13143(define_insn "bclr_m2a"
13144 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13145 (and:QI
13146 (not:QI (ashift:QI (const_int 1)
13147 (match_operand:QI 1 "const_int_operand" "K03,K03")))
13148 (match_dup 0)))]
13149 "TARGET_SH2A && TARGET_BITOPS"
13150 "@
35ed5a70
OE
13151 bclr.b %1,%0
13152 bclr.b %1,@(0,%t0)"
9eb3a0dd
N
13153[(set_attr "length" "4,4")])
13154
13155(define_insn "bclrmem_m2a"
13156 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13157 (and:QI (match_dup 0)
13158 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
13159 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
13160 "@
35ed5a70
OE
13161 bclr.b %W1,%0
13162 bclr.b %W1,@(0,%t0)"
9eb3a0dd
N
13163 [(set_attr "length" "4,4")])
13164
13165;; Set a bit in a memory location.
13166(define_insn "bset_m2a"
13167 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13168 (ior:QI
13169 (ashift:QI (const_int 1)
13170 (match_operand:QI 1 "const_int_operand" "K03,K03"))
13171 (match_dup 0)))]
13172 "TARGET_SH2A && TARGET_BITOPS"
13173 "@
35ed5a70
OE
13174 bset.b %1,%0
13175 bset.b %1,@(0,%t0)"
9eb3a0dd
N
13176 [(set_attr "length" "4,4")])
13177
13178(define_insn "bsetmem_m2a"
13179 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
13180 (ior:QI (match_dup 0)
13181 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
13182 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
13183 "@
35ed5a70
OE
13184 bset.b %V1,%0
13185 bset.b %V1,@(0,%t0)"
9eb3a0dd
N
13186 [(set_attr "length" "4,4")])
13187
13188;;; Transfer the contents of the T bit to a specified bit of memory.
13189(define_insn "bst_m2a"
13190 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
13191 (if_then_else (eq (reg:SI T_REG) (const_int 0))
13192 (and:QI
13193 (not:QI (ashift:QI (const_int 1)
13194 (match_operand:QI 1 "const_int_operand" "K03,K03")))
13195 (match_dup 0))
13196 (ior:QI
13197 (ashift:QI (const_int 1) (match_dup 1))
13198 (match_dup 0))))]
13199 "TARGET_SH2A && TARGET_BITOPS"
13200 "@
35ed5a70
OE
13201 bst.b %1,%0
13202 bst.b %1,@(0,%t0)"
9eb3a0dd
N
13203 [(set_attr "length" "4")])
13204
13205;; Store a specified bit of memory in the T bit.
13206(define_insn "bld_m2a"
13207 [(set (reg:SI T_REG)
13208 (zero_extract:SI
13209 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
13210 (const_int 1)
13211 (match_operand 1 "const_int_operand" "K03,K03")))]
13212 "TARGET_SH2A && TARGET_BITOPS"
13213 "@
35ed5a70
OE
13214 bld.b %1,%0
13215 bld.b %1,@(0,%t0)"
9eb3a0dd
N
13216 [(set_attr "length" "4,4")])
13217
13218;; Store a specified bit of memory in the T bit.
13219(define_insn "bldsign_m2a"
13220 [(set (reg:SI T_REG)
13221 (sign_extract:SI
13222 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13223 (const_int 1)
13224 (match_operand 1 "const_int_operand" "K03,K03")))]
13225 "TARGET_SH2A && TARGET_BITOPS"
13226 "@
35ed5a70
OE
13227 bld.b %1,%0
13228 bld.b %1,@(0,%t0)"
9eb3a0dd
N
13229 [(set_attr "length" "4,4")])
13230
13231;; Store a specified bit of the LSB 8 bits of a register in the T bit.
13232(define_insn "bld_reg"
13233 [(set (reg:SI T_REG)
13234 (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
13235 (const_int 1)
13236 (match_operand 1 "const_int_operand" "K03")))]
13237 "TARGET_SH2A"
35ed5a70 13238 "bld %1,%0")
9eb3a0dd
N
13239
13240(define_insn "*bld_regqi"
13241 [(set (reg:SI T_REG)
13242 (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
13243 (const_int 1)
13244 (match_operand 1 "const_int_operand" "K03")))]
13245 "TARGET_SH2A"
35ed5a70 13246 "bld %1,%0")
9eb3a0dd
N
13247
13248;; Take logical and of a specified bit of memory with the T bit and
13249;; store its result in the T bit.
13250(define_insn "band_m2a"
13251 [(set (reg:SI T_REG)
13252 (and:SI (reg:SI T_REG)
13253 (zero_extract:SI
13254 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13255 (const_int 1)
13256 (match_operand 1 "const_int_operand" "K03,K03"))))]
13257 "TARGET_SH2A && TARGET_BITOPS"
13258 "@
35ed5a70
OE
13259 band.b %1,%0
13260 band.b %1,@(0,%t0)"
9eb3a0dd
N
13261 [(set_attr "length" "4,4")])
13262
13263(define_insn "bandreg_m2a"
13264 [(set (match_operand:SI 0 "register_operand" "=r,r")
13265 (and:SI (zero_extract:SI
13266 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13267 (const_int 1)
13268 (match_operand 2 "const_int_operand" "K03,K03"))
13269 (match_operand:SI 3 "register_operand" "r,r")))]
13270 "TARGET_SH2A && TARGET_BITOPS"
35ed5a70
OE
13271{
13272 static const char* alt[] =
13273 {
13274 "band.b %2,%1" "\n"
13275 " movt %0",
13276
13277 "band.b %2,@(0,%t1)" "\n"
13278 " movt %0"
13279 };
13280 return alt[which_alternative];
13281}
9eb3a0dd
N
13282 [(set_attr "length" "6,6")])
13283
13284;; Take logical or of a specified bit of memory with the T bit and
13285;; store its result in the T bit.
13286(define_insn "bor_m2a"
13287 [(set (reg:SI T_REG)
13288 (ior:SI (reg:SI T_REG)
13289 (zero_extract:SI
13290 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13291 (const_int 1)
13292 (match_operand 1 "const_int_operand" "K03,K03"))))]
13293 "TARGET_SH2A && TARGET_BITOPS"
13294 "@
35ed5a70
OE
13295 bor.b %1,%0
13296 bor.b %1,@(0,%t0)"
9eb3a0dd
N
13297 [(set_attr "length" "4,4")])
13298
13299(define_insn "borreg_m2a"
13300 [(set (match_operand:SI 0 "register_operand" "=r,r")
13301 (ior:SI (zero_extract:SI
13302 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13303 (const_int 1)
13304 (match_operand 2 "const_int_operand" "K03,K03"))
13305 (match_operand:SI 3 "register_operand" "=r,r")))]
13306 "TARGET_SH2A && TARGET_BITOPS"
35ed5a70
OE
13307{
13308 static const char* alt[] =
13309 {
13310 "bor.b %2,%1" "\n"
13311 " movt %0",
13312
13313 "bor.b %2,@(0,%t1)" "\n"
13314 " movt %0"
13315 };
13316 return alt[which_alternative];
13317}
9eb3a0dd
N
13318 [(set_attr "length" "6,6")])
13319
13320;; Take exclusive or of a specified bit of memory with the T bit and
13321;; store its result in the T bit.
13322(define_insn "bxor_m2a"
13323 [(set (reg:SI T_REG)
13324 (xor:SI (reg:SI T_REG)
13325 (zero_extract:SI
13326 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13327 (const_int 1)
13328 (match_operand 1 "const_int_operand" "K03,K03"))))]
13329 "TARGET_SH2A && TARGET_BITOPS"
13330 "@
35ed5a70
OE
13331 bxor.b %1,%0
13332 bxor.b %1,@(0,%t0)"
9eb3a0dd
N
13333 [(set_attr "length" "4,4")])
13334
13335(define_insn "bxorreg_m2a"
13336 [(set (match_operand:SI 0 "register_operand" "=r,r")
13337 (xor:SI (zero_extract:SI
13338 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13339 (const_int 1)
13340 (match_operand 2 "const_int_operand" "K03,K03"))
13341 (match_operand:SI 3 "register_operand" "=r,r")))]
13342 "TARGET_SH2A && TARGET_BITOPS"
35ed5a70
OE
13343{
13344 static const char* alt[] =
13345 {
13346 "bxor.b %2,%1" "\n"
13347 " movt %0",
13348
13349 "bxor.b %2,@(0,%t1)" "\n"
13350 " movt %0"
13351 };
13352 return alt[which_alternative];
13353}
9eb3a0dd
N
13354 [(set_attr "length" "6,6")])
13355
725de644 13356\f
51bd623f
JW
13357;; -------------------------------------------------------------------------
13358;; Peepholes
13359;; -------------------------------------------------------------------------
9eb3a0dd
N
13360;; This matches cases where the bit in a memory location is set.
13361(define_peephole2
13362 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13363 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13364 (set (match_dup 0)
13365 (ior:SI (match_dup 0)
13366 (match_operand:SI 2 "const_int_operand" "Pso,Pso")))
13367 (set (match_dup 1)
13368 (match_operand 3 "arith_reg_operand" "r,r"))]
13369 "TARGET_SH2A && TARGET_BITOPS
13370 && satisfies_constraint_Pso (operands[2])
13371 && REGNO (operands[0]) == REGNO (operands[3])"
13372 [(set (match_dup 1)
13373 (ior:QI (match_dup 1)
13374 (match_dup 2)))]
13375 "")
13376
13377;; This matches cases where the bit in a memory location is cleared.
13378(define_peephole2
13379 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13380 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13381 (set (match_dup 0)
13382 (and:SI (match_dup 0)
13383 (match_operand:SI 2 "const_int_operand" "Psz,Psz")))
13384 (set (match_dup 1)
13385 (match_operand 3 "arith_reg_operand" "r,r"))]
13386 "TARGET_SH2A && TARGET_BITOPS
13387 && satisfies_constraint_Psz (operands[2])
13388 && REGNO (operands[0]) == REGNO (operands[3])"
13389 [(set (match_dup 1)
13390 (and:QI (match_dup 1)
13391 (match_dup 2)))]
13392 "")
961c4780 13393
51bd623f
JW
13394;; This matches cases where a stack pointer increment at the start of the
13395;; epilogue combines with a stack slot read loading the return value.
aa684c94 13396
07a45e5c 13397(define_peephole
51bd623f
JW
13398 [(set (match_operand:SI 0 "arith_reg_operand" "")
13399 (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
13400 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
fa5322fa 13401 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
51bd623f 13402 "mov.l @%1+,%0")
00f8ff66 13403
51bd623f 13404;; See the comment on the dt combiner pattern above.
00f8ff66 13405
07a45e5c
JW
13406(define_peephole
13407 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
00f8ff66
SC
13408 (plus:SI (match_dup 0)
13409 (const_int -1)))
4773afa4 13410 (set (reg:SI T_REG)
00f8ff66
SC
13411 (eq:SI (match_dup 0)
13412 (const_int 0)))]
13413 "TARGET_SH2"
13414 "dt %0")
e4931540 13415
344332e8
OE
13416;; The following peepholes fold load sequences for which reload was not
13417;; able to generate a displacement addressing move insn.
13418;; This can happen when reload has to transform a move insn
13419;; without displacement into one with displacement. Or when reload can't
13420;; fit a displacement into the insn's constraints. In the latter case, the
13421;; load destination reg remains at r0, which reload compensates by inserting
13422;; another mov insn.
13423
13424;; Fold sequence:
13425;; mov #54,r0
8c2a3f3b 13426;; mov.{b,w} @(r0,r15),r0
344332e8
OE
13427;; mov r0,r3
13428;; into:
8c2a3f3b 13429;; mov.{b,w} @(54,r15),r3
344332e8
OE
13430;;
13431(define_peephole2
13432 [(set (match_operand:SI 0 "arith_reg_dest" "")
13433 (match_operand:SI 1 "const_int_operand" ""))
13434 (set (match_operand:SI 2 "arith_reg_dest" "")
13435 (sign_extend:SI
13436 (mem:QI (plus:SI (match_dup 0)
13437 (match_operand:SI 3 "arith_reg_operand" "")))))
13438 (set (match_operand:QI 4 "arith_reg_dest" "")
13439 (match_operand:QI 5 "arith_reg_operand" ""))]
13440 "TARGET_SH2A
8c2a3f3b 13441 && sh_legitimate_index_p (QImode, operands[1], true, true)
344332e8
OE
13442 && REGNO (operands[2]) == REGNO (operands[5])
13443 && peep2_reg_dead_p (3, operands[5])"
13444 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
13445 "")
13446
8c2a3f3b
OE
13447(define_peephole2
13448 [(set (match_operand:SI 0 "arith_reg_dest" "")
13449 (match_operand:SI 1 "const_int_operand" ""))
13450 (set (match_operand:SI 2 "arith_reg_dest" "")
13451 (sign_extend:SI
13452 (mem:HI (plus:SI (match_dup 0)
13453 (match_operand:SI 3 "arith_reg_operand" "")))))
13454 (set (match_operand:HI 4 "arith_reg_dest" "")
13455 (match_operand:HI 5 "arith_reg_operand" ""))]
13456 "TARGET_SH2A
13457 && sh_legitimate_index_p (HImode, operands[1], true, true)
13458 && REGNO (operands[2]) == REGNO (operands[5])
13459 && peep2_reg_dead_p (3, operands[5])"
13460 [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
13461 "")
13462
344332e8
OE
13463;; Fold sequence:
13464;; mov #54,r0
8c2a3f3b 13465;; mov.{b,w} @(r0,r15),r1
344332e8 13466;; into:
8c2a3f3b 13467;; mov.{b,w} @(54,r15),r1
344332e8
OE
13468;;
13469(define_peephole2
13470 [(set (match_operand:SI 0 "arith_reg_dest" "")
13471 (match_operand:SI 1 "const_int_operand" ""))
13472 (set (match_operand:SI 2 "arith_reg_dest" "")
13473 (sign_extend:SI
13474 (mem:QI (plus:SI (match_dup 0)
13475 (match_operand:SI 3 "arith_reg_operand" "")))))]
13476 "TARGET_SH2A
8c2a3f3b 13477 && sh_legitimate_index_p (QImode, operands[1], true, true)
344332e8
OE
13478 && (peep2_reg_dead_p (2, operands[0])
13479 || REGNO (operands[0]) == REGNO (operands[2]))"
13480 [(set (match_dup 2)
13481 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
13482 "")
13483
8c2a3f3b
OE
13484(define_peephole2
13485 [(set (match_operand:SI 0 "arith_reg_dest" "")
13486 (match_operand:SI 1 "const_int_operand" ""))
13487 (set (match_operand:SI 2 "arith_reg_dest" "")
13488 (sign_extend:SI
13489 (mem:HI (plus:SI (match_dup 0)
13490 (match_operand:SI 3 "arith_reg_operand" "")))))]
13491 "TARGET_SH2A
13492 && sh_legitimate_index_p (HImode, operands[1], true, true)
13493 && (peep2_reg_dead_p (2, operands[0])
13494 || REGNO (operands[0]) == REGNO (operands[2]))"
13495 [(set (match_dup 2)
13496 (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
13497 "")
13498
344332e8 13499;; Fold sequence:
8c2a3f3b 13500;; mov.{b,w} @(r0,r15),r0
344332e8
OE
13501;; mov r0,r3
13502;; into:
8c2a3f3b 13503;; mov.{b,w} @(r0,r15),r3
344332e8 13504;;
8c2a3f3b
OE
13505;; This can happen when initially a displacement address is picked, where
13506;; the destination reg is fixed to r0, and then the address is transformed
13507;; into 'r0 + reg'.
344332e8
OE
13508(define_peephole2
13509 [(set (match_operand:SI 0 "arith_reg_dest" "")
13510 (sign_extend:SI
13511 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13512 (match_operand:SI 2 "arith_reg_operand" "")))))
13513 (set (match_operand:QI 3 "arith_reg_dest" "")
13514 (match_operand:QI 4 "arith_reg_operand" ""))]
13515 "TARGET_SH1
13516 && REGNO (operands[0]) == REGNO (operands[4])
13517 && peep2_reg_dead_p (2, operands[0])"
13518 [(set (match_dup 3)
13519 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
13520 "")
13521
8c2a3f3b
OE
13522(define_peephole2
13523 [(set (match_operand:SI 0 "arith_reg_dest" "")
13524 (sign_extend:SI
13525 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13526 (match_operand:SI 2 "arith_reg_operand" "")))))
13527 (set (match_operand:HI 3 "arith_reg_dest" "")
13528 (match_operand:HI 4 "arith_reg_operand" ""))]
13529 "TARGET_SH1
13530 && REGNO (operands[0]) == REGNO (operands[4])
13531 && peep2_reg_dead_p (2, operands[0])"
13532 [(set (match_dup 3)
13533 (mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
13534 "")
13535
e4931540
RK
13536(define_peephole
13537 [(set (match_operand:SI 0 "register_operand" "=r")
13538 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13539 (set (mem:SF (match_dup 0))
13540 (match_operand:SF 2 "general_movsrc_operand" ""))]
fa5322fa 13541 "TARGET_SH1 && REGNO (operands[0]) == 0
f3536097 13542 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
45348d9e
JW
13543 || (GET_CODE (operands[2]) == SUBREG
13544 && REGNO (SUBREG_REG (operands[2])) < 16))
13545 && reg_unused_after (operands[0], insn)"
e4931540
RK
13546 "mov.l %2,@(%0,%1)")
13547
13548(define_peephole
13549 [(set (match_operand:SI 0 "register_operand" "=r")
13550 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13551 (set (match_operand:SF 2 "general_movdst_operand" "")
13552
13553 (mem:SF (match_dup 0)))]
fa5322fa 13554 "TARGET_SH1 && REGNO (operands[0]) == 0
f3536097 13555 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
45348d9e
JW
13556 || (GET_CODE (operands[2]) == SUBREG
13557 && REGNO (SUBREG_REG (operands[2])) < 16))
13558 && reg_unused_after (operands[0], insn)"
e4931540 13559 "mov.l @(%0,%1),%2")
45348d9e
JW
13560
13561(define_peephole
13562 [(set (match_operand:SI 0 "register_operand" "=r")
13563 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13564 (set (mem:SF (match_dup 0))
13565 (match_operand:SF 2 "general_movsrc_operand" ""))]
3a8699c7 13566 "TARGET_SH2E && REGNO (operands[0]) == 0
f3536097 13567 && ((REG_P (operands[2])
104ee20b 13568 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
45348d9e 13569 || (GET_CODE (operands[2]) == SUBREG
104ee20b 13570 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
45348d9e 13571 && reg_unused_after (operands[0], insn)"
1245df60 13572 "fmov{.s|} %2,@(%0,%1)")
45348d9e
JW
13573
13574(define_peephole
13575 [(set (match_operand:SI 0 "register_operand" "=r")
13576 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13577 (set (match_operand:SF 2 "general_movdst_operand" "")
13578
13579 (mem:SF (match_dup 0)))]
3a8699c7 13580 "TARGET_SH2E && REGNO (operands[0]) == 0
f3536097 13581 && ((REG_P (operands[2])
104ee20b 13582 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
45348d9e 13583 || (GET_CODE (operands[2]) == SUBREG
104ee20b 13584 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
45348d9e 13585 && reg_unused_after (operands[0], insn)"
1245df60 13586 "fmov{.s|} @(%0,%1),%2")
4408efce 13587
35ed5a70 13588;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
4408efce 13589(define_insn "sp_switch_1"
a6ab9fc0 13590 [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
fa5322fa 13591 "TARGET_SH1"
4408efce 13592{
35ed5a70
OE
13593 return "mov.l r0,@-r15" "\n"
13594 " mov.l %0,r0" "\n"
13595 " mov.l @r0,r0" "\n"
13596 " mov.l r15,@-r0" "\n"
13597 " mov r0,r15";
d9241861 13598}
4408efce 13599 [(set_attr "length" "10")])
4408efce 13600
956d6950 13601;; Switch back to the original stack for interrupt functions with the
35ed5a70 13602;; sp_switch attribute.
4408efce
JL
13603(define_insn "sp_switch_2"
13604 [(const_int 2)]
fa5322fa 13605 "TARGET_SH1"
35ed5a70
OE
13606{
13607 return "mov.l @r15+,r15" "\n"
13608 " mov.l @r15+,r0";
13609}
4408efce 13610 [(set_attr "length" "4")])
fae15c93 13611
c1b92d09
R
13612;; Integer vector moves
13613
13614(define_expand "movv8qi"
13615 [(set (match_operand:V8QI 0 "general_movdst_operand" "")
13616 (match_operand:V8QI 1 "general_movsrc_operand" ""))]
13617 "TARGET_SHMEDIA"
d9241861 13618{
2ef6611e 13619 prepare_move_operands (operands, V8QImode);
d9241861 13620})
c1b92d09
R
13621
13622(define_insn "movv8qi_i"
13623 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
42201282 13624 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
c1b92d09
R
13625 "TARGET_SHMEDIA
13626 && (register_operand (operands[0], V8QImode)
d9da94a1 13627 || sh_register_operand (operands[1], V8QImode))"
c1b92d09
R
13628 "@
13629 add %1, r63, %0
13630 movi %1, %0
13631 #
13632 ld%M1.q %m1, %0
d9da94a1 13633 st%M0.q %m0, %N1"
c1b92d09
R
13634 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
13635 (set_attr "length" "4,4,16,4,4")])
13636
13637(define_split
13638 [(set (match_operand:V8QI 0 "arith_reg_dest" "")
13639 (subreg:V8QI (const_int 0) 0))]
13640 "TARGET_SHMEDIA"
13641 [(set (match_dup 0)
13642 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
13643 (const_int 0) (const_int 0) (const_int 0)
13644 (const_int 0) (const_int 0)]))])
13645
13646(define_split
13647 [(set (match_operand 0 "arith_reg_dest" "")
13648 (match_operand 1 "sh_rep_vec" ""))]
13649 "TARGET_SHMEDIA && reload_completed
13650 && GET_MODE (operands[0]) == GET_MODE (operands[1])
f676971a 13651 && sh_vector_mode_supported_p (GET_MODE (operands[0]))
c1b92d09
R
13652 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
13653 && (XVECEXP (operands[1], 0, 0) != const0_rtx
c034672a
R
13654 || XVECEXP (operands[1], 0, 1) != const0_rtx)
13655 && (XVECEXP (operands[1], 0, 0) != constm1_rtx
13656 || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
c1b92d09
R
13657 [(set (match_dup 0) (match_dup 1))
13658 (match_dup 2)]
c1b92d09
R
13659{
13660 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
13661 rtx elt1 = XVECEXP (operands[1], 0, 1);
13662
13663 if (unit_size > 2)
13664 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
13665 else
750afc12
R
13666 {
13667 if (unit_size < 2)
13668 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
13669 operands[2] = gen_mperm_w0 (operands[0], operands[0]);
13670 }
c1b92d09
R
13671 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
13672 operands[1] = XVECEXP (operands[1], 0, 0);
13673 if (unit_size < 2)
13674 {
f3536097 13675 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
40779a72
R
13676 operands[1]
13677 = GEN_INT (TARGET_LITTLE_ENDIAN
13678 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
13679 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
c1b92d09
R
13680 else
13681 {
13682 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
13683 operands[1]
13684 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
13685 }
13686 }
d9241861 13687})
c1b92d09
R
13688
13689(define_split
13690 [(set (match_operand 0 "arith_reg_dest" "")
13691 (match_operand 1 "sh_const_vec" ""))]
13692 "TARGET_SHMEDIA && reload_completed
13693 && GET_MODE (operands[0]) == GET_MODE (operands[1])
73a4d10b 13694 && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
c1b92d09 13695 [(set (match_dup 0) (match_dup 1))]
c1b92d09
R
13696{
13697 rtx v = operands[1];
13698 enum machine_mode new_mode
13699 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
13700
13701 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
13702 operands[1]
52702ae1 13703 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
d9241861 13704})
c1b92d09
R
13705
13706(define_expand "movv2hi"
13707 [(set (match_operand:V2HI 0 "general_movdst_operand" "")
13708 (match_operand:V2HI 1 "general_movsrc_operand" ""))]
13709 "TARGET_SHMEDIA"
d9241861 13710{
2ef6611e 13711 prepare_move_operands (operands, V2HImode);
d9241861 13712})
c1b92d09
R
13713
13714(define_insn "movv2hi_i"
13715 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
42201282 13716 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
c1b92d09
R
13717 "TARGET_SHMEDIA
13718 && (register_operand (operands[0], V2HImode)
d9da94a1 13719 || sh_register_operand (operands[1], V2HImode))"
c1b92d09 13720 "@
73a4d10b 13721 add.l %1, r63, %0
c1b92d09
R
13722 movi %1, %0
13723 #
13724 ld%M1.l %m1, %0
d9da94a1 13725 st%M0.l %m0, %N1"
c1b92d09 13726 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
73a4d10b
R
13727 (set_attr "length" "4,4,16,4,4")
13728 (set (attr "highpart")
68ed2b9c 13729 (cond [(match_test "sh_contains_memref_p (insn)")
73a4d10b
R
13730 (const_string "user")]
13731 (const_string "ignore")))])
c1b92d09
R
13732
13733(define_expand "movv4hi"
13734 [(set (match_operand:V4HI 0 "general_movdst_operand" "")
13735 (match_operand:V4HI 1 "general_movsrc_operand" ""))]
13736 "TARGET_SHMEDIA"
d9241861 13737{
2ef6611e 13738 prepare_move_operands (operands, V4HImode);
d9241861 13739})
c1b92d09
R
13740
13741(define_insn "movv4hi_i"
13742 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
42201282 13743 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
c1b92d09
R
13744 "TARGET_SHMEDIA
13745 && (register_operand (operands[0], V4HImode)
d9da94a1 13746 || sh_register_operand (operands[1], V4HImode))"
c1b92d09
R
13747 "@
13748 add %1, r63, %0
13749 movi %1, %0
13750 #
13751 ld%M1.q %m1, %0
d9da94a1 13752 st%M0.q %m0, %N1"
c1b92d09 13753 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
73a4d10b
R
13754 (set_attr "length" "4,4,16,4,4")
13755 (set_attr "highpart" "depend")])
c1b92d09
R
13756
13757(define_expand "movv2si"
13758 [(set (match_operand:V2SI 0 "general_movdst_operand" "")
13759 (match_operand:V2SI 1 "general_movsrc_operand" ""))]
13760 "TARGET_SHMEDIA"
d9241861 13761{
2ef6611e 13762 prepare_move_operands (operands, V2SImode);
d9241861 13763})
c1b92d09
R
13764
13765(define_insn "movv2si_i"
13766 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
42201282 13767 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
c1b92d09
R
13768 "TARGET_SHMEDIA
13769 && (register_operand (operands[0], V2SImode)
d9da94a1 13770 || sh_register_operand (operands[1], V2SImode))"
c1b92d09
R
13771 "@
13772 add %1, r63, %0
52702ae1 13773 #
c1b92d09
R
13774 #
13775 ld%M1.q %m1, %0
d9da94a1 13776 st%M0.q %m0, %N1"
c1b92d09 13777 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
73a4d10b
R
13778 (set_attr "length" "4,4,16,4,4")
13779 (set_attr "highpart" "depend")])
c1b92d09
R
13780
13781;; Multimedia Intrinsics
13782
13783(define_insn "absv2si2"
13784 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13785 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
13786 "TARGET_SHMEDIA"
13787 "mabs.l %1, %0"
73a4d10b
R
13788 [(set_attr "type" "mcmp_media")
13789 (set_attr "highpart" "depend")])
c1b92d09
R
13790
13791(define_insn "absv4hi2"
13792 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13793 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
13794 "TARGET_SHMEDIA"
13795 "mabs.w %1, %0"
73a4d10b
R
13796 [(set_attr "type" "mcmp_media")
13797 (set_attr "highpart" "depend")])
c1b92d09
R
13798
13799(define_insn "addv2si3"
13800 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13801 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
13802 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13803 "TARGET_SHMEDIA"
13804 "madd.l %1, %2, %0"
73a4d10b
R
13805 [(set_attr "type" "arith_media")
13806 (set_attr "highpart" "depend")])
c1b92d09
R
13807
13808(define_insn "addv4hi3"
13809 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13810 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
13811 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13812 "TARGET_SHMEDIA"
13813 "madd.w %1, %2, %0"
73a4d10b
R
13814 [(set_attr "type" "arith_media")
13815 (set_attr "highpart" "depend")])
13816
13817(define_insn_and_split "addv2hi3"
13818 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
13819 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
13820 (match_operand:V2HI 2 "extend_reg_operand" "r")))]
13821 "TARGET_SHMEDIA"
13822 "#"
13823 "TARGET_SHMEDIA"
13824 [(const_int 0)]
73a4d10b
R
13825{
13826 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
13827 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
13828 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
13829 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
13830 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
13831
13832 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
13833 emit_insn (gen_truncdisi2 (si_dst, di_dst));
13834 DONE;
d9241861 13835}
73a4d10b 13836 [(set_attr "highpart" "must_split")])
c1b92d09
R
13837
13838(define_insn "ssaddv2si3"
13839 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13840 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
13841 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13842 "TARGET_SHMEDIA"
13843 "madds.l %1, %2, %0"
73a4d10b
R
13844 [(set_attr "type" "mcmp_media")
13845 (set_attr "highpart" "depend")])
c1b92d09
R
13846
13847(define_insn "usaddv8qi3"
13848 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13849 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
13850 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
13851 "TARGET_SHMEDIA"
13852 "madds.ub %1, %2, %0"
73a4d10b
R
13853 [(set_attr "type" "mcmp_media")
13854 (set_attr "highpart" "depend")])
c1b92d09
R
13855
13856(define_insn "ssaddv4hi3"
13857 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13858 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
13859 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13860 "TARGET_SHMEDIA"
13861 "madds.w %1, %2, %0"
73a4d10b
R
13862 [(set_attr "type" "mcmp_media")
13863 (set_attr "highpart" "depend")])
c1b92d09
R
13864
13865(define_insn "negcmpeqv8qi"
13866 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
735cb76e
R
13867 (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
13868 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
13869 "TARGET_SHMEDIA"
13870 "mcmpeq.b %N1, %N2, %0"
73a4d10b
R
13871 [(set_attr "type" "mcmp_media")
13872 (set_attr "highpart" "depend")])
c1b92d09
R
13873
13874(define_insn "negcmpeqv2si"
13875 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
735cb76e
R
13876 (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
13877 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
13878 "TARGET_SHMEDIA"
13879 "mcmpeq.l %N1, %N2, %0"
73a4d10b
R
13880 [(set_attr "type" "mcmp_media")
13881 (set_attr "highpart" "depend")])
c1b92d09
R
13882
13883(define_insn "negcmpeqv4hi"
13884 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
735cb76e
R
13885 (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
13886 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
13887 "TARGET_SHMEDIA"
13888 "mcmpeq.w %N1, %N2, %0"
73a4d10b
R
13889 [(set_attr "type" "mcmp_media")
13890 (set_attr "highpart" "depend")])
c1b92d09
R
13891
13892(define_insn "negcmpgtuv8qi"
13893 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
735cb76e
R
13894 (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
13895 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
13896 "TARGET_SHMEDIA"
13897 "mcmpgt.ub %N1, %N2, %0"
73a4d10b
R
13898 [(set_attr "type" "mcmp_media")
13899 (set_attr "highpart" "depend")])
c1b92d09
R
13900
13901(define_insn "negcmpgtv2si"
13902 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
735cb76e
R
13903 (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
13904 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
13905 "TARGET_SHMEDIA"
13906 "mcmpgt.l %N1, %N2, %0"
73a4d10b
R
13907 [(set_attr "type" "mcmp_media")
13908 (set_attr "highpart" "depend")])
c1b92d09
R
13909
13910(define_insn "negcmpgtv4hi"
13911 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
735cb76e
R
13912 (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
13913 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
13914 "TARGET_SHMEDIA"
13915 "mcmpgt.w %N1, %N2, %0"
73a4d10b
R
13916 [(set_attr "type" "mcmp_media")
13917 (set_attr "highpart" "depend")])
c1b92d09
R
13918
13919(define_insn "mcmv"
13920 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
735cb76e 13921 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09
R
13922 (match_operand:DI 2 "arith_reg_operand" "r"))
13923 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
13924 (not:DI (match_dup 2)))))]
13925 "TARGET_SHMEDIA"
13926 "mcmv %N1, %2, %0"
73a4d10b
R
13927 [(set_attr "type" "arith_media")
13928 (set_attr "highpart" "depend")])
c1b92d09
R
13929
13930(define_insn "mcnvs_lw"
13931 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13932 (vec_concat:V4HI
735cb76e
R
13933 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
13934 (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
13935 "TARGET_SHMEDIA"
13936 "mcnvs.lw %N1, %N2, %0"
13937 [(set_attr "type" "mcmp_media")])
13938
13939(define_insn "mcnvs_wb"
13940 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13941 (vec_concat:V8QI
735cb76e
R
13942 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
13943 (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
13944 "TARGET_SHMEDIA"
13945 "mcnvs.wb %N1, %N2, %0"
13946 [(set_attr "type" "mcmp_media")])
13947
13948(define_insn "mcnvs_wub"
13949 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13950 (vec_concat:V8QI
735cb76e
R
13951 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
13952 (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
13953 "TARGET_SHMEDIA"
13954 "mcnvs.wub %N1, %N2, %0"
13955 [(set_attr "type" "mcmp_media")])
13956
13957(define_insn "mextr_rl"
13958 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
735cb76e 13959 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09 13960 (match_operand:HI 3 "mextr_bit_offset" "i"))
735cb76e 13961 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
c1b92d09
R
13962 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
13963 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
c1b92d09 13964{
9a487a45 13965 static char templ[21];
35ed5a70
OE
13966 sprintf (templ, "mextr%d %%N1, %%N2, %%0",
13967 (int) INTVAL (operands[3]) >> 3);
c1b92d09 13968 return templ;
d9241861 13969}
c1b92d09
R
13970 [(set_attr "type" "arith_media")])
13971
13972(define_insn "*mextr_lr"
13973 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
735cb76e 13974 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09 13975 (match_operand:HI 3 "mextr_bit_offset" "i"))
735cb76e 13976 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
c1b92d09
R
13977 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
13978 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
c1b92d09 13979{
9a487a45 13980 static char templ[21];
35ed5a70
OE
13981 sprintf (templ, "mextr%d %%N2, %%N1, %%0",
13982 (int) INTVAL (operands[4]) >> 3);
c1b92d09 13983 return templ;
d9241861 13984}
c1b92d09
R
13985 [(set_attr "type" "arith_media")])
13986
13987; mextrN can be modelled with vec_select / vec_concat, but the selection
13988; vector then varies depending on endianness.
13989(define_expand "mextr1"
0ac78517 13990 [(match_operand:DI 0 "arith_reg_dest" "")
735cb76e
R
13991 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13992 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 13993 "TARGET_SHMEDIA"
c1b92d09 13994{
0ac78517 13995 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
c1b92d09
R
13996 GEN_INT (1 * 8), GEN_INT (7 * 8)));
13997 DONE;
d9241861 13998})
c1b92d09
R
13999
14000(define_expand "mextr2"
0ac78517 14001 [(match_operand:DI 0 "arith_reg_dest" "")
735cb76e
R
14002 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14003 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14004 "TARGET_SHMEDIA"
c1b92d09 14005{
0ac78517 14006 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
c1b92d09
R
14007 GEN_INT (2 * 8), GEN_INT (6 * 8)));
14008 DONE;
d9241861 14009})
c1b92d09
R
14010
14011(define_expand "mextr3"
0ac78517 14012 [(match_operand:DI 0 "arith_reg_dest" "")
735cb76e
R
14013 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14014 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14015 "TARGET_SHMEDIA"
c1b92d09 14016{
0ac78517 14017 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
c1b92d09
R
14018 GEN_INT (3 * 8), GEN_INT (5 * 8)));
14019 DONE;
d9241861 14020})
c1b92d09
R
14021
14022(define_expand "mextr4"
0ac78517 14023 [(match_operand:DI 0 "arith_reg_dest" "")
735cb76e
R
14024 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14025 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14026 "TARGET_SHMEDIA"
c1b92d09 14027{
0ac78517 14028 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
c1b92d09
R
14029 GEN_INT (4 * 8), GEN_INT (4 * 8)));
14030 DONE;
d9241861 14031})
c1b92d09
R
14032
14033(define_expand "mextr5"
0ac78517 14034 [(match_operand:DI 0 "arith_reg_dest" "")
735cb76e
R
14035 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14036 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14037 "TARGET_SHMEDIA"
c1b92d09 14038{
0ac78517 14039 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
c1b92d09
R
14040 GEN_INT (5 * 8), GEN_INT (3 * 8)));
14041 DONE;
d9241861 14042})
c1b92d09
R
14043
14044(define_expand "mextr6"
0ac78517 14045 [(match_operand:DI 0 "arith_reg_dest" "")
735cb76e
R
14046 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14047 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14048 "TARGET_SHMEDIA"
c1b92d09 14049{
0ac78517 14050 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
c1b92d09
R
14051 GEN_INT (6 * 8), GEN_INT (2 * 8)));
14052 DONE;
d9241861 14053})
c1b92d09
R
14054
14055(define_expand "mextr7"
0ac78517 14056 [(match_operand:DI 0 "arith_reg_dest" "")
735cb76e
R
14057 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14058 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14059 "TARGET_SHMEDIA"
c1b92d09 14060{
0ac78517 14061 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
c1b92d09
R
14062 GEN_INT (7 * 8), GEN_INT (1 * 8)));
14063 DONE;
d9241861 14064})
c1b92d09
R
14065
14066(define_expand "mmacfx_wl"
14067 [(match_operand:V2SI 0 "arith_reg_dest" "")
14068 (match_operand:V2HI 1 "extend_reg_operand" "")
14069 (match_operand:V2HI 2 "extend_reg_operand" "")
14070 (match_operand:V2SI 3 "arith_reg_operand" "")]
14071 "TARGET_SHMEDIA"
c1b92d09
R
14072{
14073 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
14074 operands[1], operands[2]));
14075 DONE;
d9241861 14076})
c1b92d09 14077
73a4d10b
R
14078;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
14079;; is depend
c1b92d09
R
14080(define_insn "mmacfx_wl_i"
14081 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14082 (ss_plus:V2SI
14083 (match_operand:V2SI 1 "arith_reg_operand" "0")
14084 (ss_truncate:V2SI
14085 (ashift:V2DI
14086 (sign_extend:V2DI
14087 (mult:V2SI
14088 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14089 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14090 (const_int 1)))))]
14091 "TARGET_SHMEDIA"
14092 "mmacfx.wl %2, %3, %0"
73a4d10b
R
14093 [(set_attr "type" "mac_media")
14094 (set_attr "highpart" "depend")])
c1b92d09
R
14095
14096(define_expand "mmacnfx_wl"
14097 [(match_operand:V2SI 0 "arith_reg_dest" "")
14098 (match_operand:V2HI 1 "extend_reg_operand" "")
14099 (match_operand:V2HI 2 "extend_reg_operand" "")
14100 (match_operand:V2SI 3 "arith_reg_operand" "")]
14101 "TARGET_SHMEDIA"
c1b92d09
R
14102{
14103 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
14104 operands[1], operands[2]));
14105 DONE;
d9241861 14106})
c1b92d09
R
14107
14108(define_insn "mmacnfx_wl_i"
14109 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14110 (ss_minus:V2SI
14111 (match_operand:V2SI 1 "arith_reg_operand" "0")
14112 (ss_truncate:V2SI
14113 (ashift:V2DI
14114 (sign_extend:V2DI
14115 (mult:V2SI
14116 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
14117 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
14118 (const_int 1)))))]
14119 "TARGET_SHMEDIA"
14120 "mmacnfx.wl %2, %3, %0"
73a4d10b
R
14121 [(set_attr "type" "mac_media")
14122 (set_attr "highpart" "depend")])
c1b92d09
R
14123
14124(define_insn "mulv2si3"
14125 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14126 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14127 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14128 "TARGET_SHMEDIA"
14129 "mmul.l %1, %2, %0"
73a4d10b
R
14130 [(set_attr "type" "d2mpy_media")
14131 (set_attr "highpart" "depend")])
c1b92d09
R
14132
14133(define_insn "mulv4hi3"
14134 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14135 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14136 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14137 "TARGET_SHMEDIA"
14138 "mmul.w %1, %2, %0"
73a4d10b
R
14139 [(set_attr "type" "dmpy_media")
14140 (set_attr "highpart" "depend")])
c1b92d09
R
14141
14142(define_insn "mmulfx_l"
14143 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14144 (ss_truncate:V2SI
14145 (ashiftrt:V2DI
14146 (mult:V2DI
14147 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14148 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
14149 (const_int 31))))]
14150 "TARGET_SHMEDIA"
14151 "mmulfx.l %1, %2, %0"
73a4d10b
R
14152 [(set_attr "type" "d2mpy_media")
14153 (set_attr "highpart" "depend")])
c1b92d09
R
14154
14155(define_insn "mmulfx_w"
14156 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14157 (ss_truncate:V4HI
14158 (ashiftrt:V4SI
14159 (mult:V4SI
14160 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14161 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14162 (const_int 15))))]
14163 "TARGET_SHMEDIA"
14164 "mmulfx.w %1, %2, %0"
73a4d10b
R
14165 [(set_attr "type" "dmpy_media")
14166 (set_attr "highpart" "depend")])
c1b92d09
R
14167
14168(define_insn "mmulfxrp_w"
14169 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14170 (ss_truncate:V4HI
14171 (ashiftrt:V4SI
14172 (plus:V4SI
14173 (mult:V4SI
14174 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14175 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14176 (const_int 16384))
14177 (const_int 15))))]
14178 "TARGET_SHMEDIA"
14179 "mmulfxrp.w %1, %2, %0"
73a4d10b
R
14180 [(set_attr "type" "dmpy_media")
14181 (set_attr "highpart" "depend")])
14182
c1b92d09
R
14183
14184(define_expand "mmulhi_wl"
14185 [(match_operand:V2SI 0 "arith_reg_dest" "")
14186 (match_operand:V4HI 1 "arith_reg_operand" "")
14187 (match_operand:V4HI 2 "arith_reg_operand" "")]
14188 "TARGET_SHMEDIA"
c1b92d09
R
14189{
14190 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
14191 (operands[0], operands[1], operands[2]));
14192 DONE;
d9241861 14193})
c1b92d09
R
14194
14195(define_expand "mmullo_wl"
14196 [(match_operand:V2SI 0 "arith_reg_dest" "")
14197 (match_operand:V4HI 1 "arith_reg_operand" "")
14198 (match_operand:V4HI 2 "arith_reg_operand" "")]
14199 "TARGET_SHMEDIA"
c1b92d09
R
14200{
14201 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
14202 (operands[0], operands[1], operands[2]));
14203 DONE;
d9241861 14204})
c1b92d09
R
14205
14206(define_insn "mmul23_wl"
14207 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14208 (vec_select:V2SI
14209 (mult:V4SI
14210 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14211 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
0ac78517 14212 (parallel [(const_int 2) (const_int 3)])))]
c1b92d09 14213 "TARGET_SHMEDIA"
d9241861
OE
14214{
14215 return (TARGET_LITTLE_ENDIAN
14216 ? "mmulhi.wl %1, %2, %0"
14217 : "mmullo.wl %1, %2, %0");
14218}
73a4d10b
R
14219 [(set_attr "type" "dmpy_media")
14220 (set (attr "highpart")
14221 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14222 (const_string "user")))])
c1b92d09
R
14223
14224(define_insn "mmul01_wl"
14225 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14226 (vec_select:V2SI
14227 (mult:V4SI
14228 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14229 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
0ac78517 14230 (parallel [(const_int 0) (const_int 1)])))]
c1b92d09 14231 "TARGET_SHMEDIA"
d9241861
OE
14232{
14233 return (TARGET_LITTLE_ENDIAN
14234 ? "mmullo.wl %1, %2, %0"
14235 : "mmulhi.wl %1, %2, %0");
14236}
73a4d10b
R
14237 [(set_attr "type" "dmpy_media")
14238 (set (attr "highpart")
14239 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14240 (const_string "user")))])
14241
c1b92d09
R
14242
14243(define_expand "mmulsum_wq"
14244 [(match_operand:DI 0 "arith_reg_dest" "")
14245 (match_operand:V4HI 1 "arith_reg_operand" "")
14246 (match_operand:V4HI 2 "arith_reg_operand" "")
14247 (match_operand:DI 3 "arith_reg_operand" "")]
14248 "TARGET_SHMEDIA"
c1b92d09
R
14249{
14250 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
14251 operands[1], operands[2]));
14252 DONE;
d9241861 14253})
c1b92d09
R
14254
14255(define_insn "mmulsum_wq_i"
14256 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14257 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
14258 (plus:DI
14259 (plus:DI
14260 (vec_select:DI
14261 (mult:V4DI
14262 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
14263 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
0ac78517 14264 (parallel [(const_int 0)]))
c1b92d09
R
14265 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14266 (sign_extend:V4DI (match_dup 3)))
0ac78517 14267 (parallel [(const_int 1)])))
c1b92d09
R
14268 (plus:DI
14269 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14270 (sign_extend:V4DI (match_dup 3)))
0ac78517 14271 (parallel [(const_int 2)]))
c1b92d09
R
14272 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14273 (sign_extend:V4DI (match_dup 3)))
0ac78517 14274 (parallel [(const_int 3)]))))))]
c1b92d09
R
14275 "TARGET_SHMEDIA"
14276 "mmulsum.wq %2, %3, %0"
14277 [(set_attr "type" "mac_media")])
14278
14279(define_expand "mperm_w"
14280 [(match_operand:V4HI 0 "arith_reg_dest" "=r")
14281 (match_operand:V4HI 1 "arith_reg_operand" "r")
735cb76e 14282 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
c1b92d09 14283 "TARGET_SHMEDIA"
c1b92d09
R
14284{
14285 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
14286 (operands[0], operands[1], operands[2]));
c49439f1 14287 DONE;
d9241861 14288})
c1b92d09
R
14289
14290; This use of vec_select isn't exactly correct according to rtl.texi
14291; (because not constant), but it seems a straightforward extension.
14292(define_insn "mperm_w_little"
14293 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14294 (vec_select:V4HI
14295 (match_operand:V4HI 1 "arith_reg_operand" "r")
14296 (parallel
735cb76e 14297 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
502e6d5a
R
14298 (const_int 2) (const_int 0))
14299 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
14300 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
14301 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
c1b92d09
R
14302 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
14303 "mperm.w %1, %N2, %0"
14304 [(set_attr "type" "arith_media")])
14305
14306(define_insn "mperm_w_big"
14307 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14308 (vec_select:V4HI
14309 (match_operand:V4HI 1 "arith_reg_operand" "r")
14310 (parallel
502e6d5a 14311 [(zero_extract:QI (not:QI (match_operand:QI 2
735cb76e 14312 "extend_reg_or_0_operand" "rZ"))
502e6d5a
R
14313 (const_int 2) (const_int 0))
14314 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
14315 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
14316 (zero_extract:QI (not:QI (match_dup 2))
14317 (const_int 2) (const_int 6))])))]
c1b92d09
R
14318 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
14319 "mperm.w %1, %N2, %0"
14320 [(set_attr "type" "arith_media")])
14321
14322(define_insn "mperm_w0"
14323 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14324 (vec_duplicate:V4HI (truncate:HI (match_operand 1
e69d1422 14325 "trunc_hi_operand" "r"))))]
c1b92d09
R
14326 "TARGET_SHMEDIA"
14327 "mperm.w %1, r63, %0"
73a4d10b
R
14328 [(set_attr "type" "arith_media")
14329 (set_attr "highpart" "ignore")])
c1b92d09
R
14330
14331(define_expand "msad_ubq"
14332 [(match_operand:DI 0 "arith_reg_dest" "")
14333 (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
14334 (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
14335 (match_operand:DI 3 "arith_reg_operand" "")]
14336 "TARGET_SHMEDIA"
c1b92d09
R
14337{
14338 emit_insn (gen_msad_ubq_i (operands[0], operands[3],
14339 operands[1], operands[2]));
14340 DONE;
d9241861 14341})
c1b92d09
R
14342
14343(define_insn "msad_ubq_i"
14344 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14345 (plus:DI
14346 (plus:DI
14347 (plus:DI
14348 (plus:DI
14349 (match_operand:DI 1 "arith_reg_operand" "0")
14350 (abs:DI (vec_select:DI
14351 (minus:V8DI
14352 (zero_extend:V8DI
735cb76e 14353 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
c1b92d09 14354 (zero_extend:V8DI
735cb76e 14355 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
0ac78517 14356 (parallel [(const_int 0)]))))
c1b92d09
R
14357 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14358 (zero_extend:V8DI (match_dup 3)))
0ac78517 14359 (parallel [(const_int 1)]))))
c1b92d09
R
14360 (plus:DI
14361 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14362 (zero_extend:V8DI (match_dup 3)))
0ac78517 14363 (parallel [(const_int 2)])))
c1b92d09
R
14364 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14365 (zero_extend:V8DI (match_dup 3)))
0ac78517 14366 (parallel [(const_int 3)])))))
c1b92d09
R
14367 (plus:DI
14368 (plus:DI
14369 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14370 (zero_extend:V8DI (match_dup 3)))
0ac78517 14371 (parallel [(const_int 4)])))
c1b92d09
R
14372 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14373 (zero_extend:V8DI (match_dup 3)))
0ac78517 14374 (parallel [(const_int 5)]))))
c1b92d09
R
14375 (plus:DI
14376 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14377 (zero_extend:V8DI (match_dup 3)))
0ac78517 14378 (parallel [(const_int 6)])))
c1b92d09
R
14379 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14380 (zero_extend:V8DI (match_dup 3)))
0ac78517 14381 (parallel [(const_int 7)])))))))]
c1b92d09
R
14382 "TARGET_SHMEDIA"
14383 "msad.ubq %N2, %N3, %0"
14384 [(set_attr "type" "mac_media")])
14385
14386(define_insn "mshalds_l"
14387 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14388 (ss_truncate:V2SI
14389 (ashift:V2DI
14390 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14391 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14392 (const_int 31)))))]
14393 "TARGET_SHMEDIA"
14394 "mshalds.l %1, %2, %0"
73a4d10b
R
14395 [(set_attr "type" "mcmp_media")
14396 (set_attr "highpart" "depend")])
c1b92d09
R
14397
14398(define_insn "mshalds_w"
14399 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14400 (ss_truncate:V4HI
14401 (ashift:V4SI
14402 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14403 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14404 (const_int 15)))))]
14405 "TARGET_SHMEDIA"
14406 "mshalds.w %1, %2, %0"
73a4d10b
R
14407 [(set_attr "type" "mcmp_media")
14408 (set_attr "highpart" "depend")])
c1b92d09
R
14409
14410(define_insn "ashrv2si3"
14411 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14412 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14413 (match_operand:DI 2 "arith_reg_operand" "r")))]
14414 "TARGET_SHMEDIA"
14415 "mshard.l %1, %2, %0"
73a4d10b
R
14416 [(set_attr "type" "arith_media")
14417 (set_attr "highpart" "depend")])
c1b92d09
R
14418
14419(define_insn "ashrv4hi3"
14420 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14421 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14422 (match_operand:DI 2 "arith_reg_operand" "r")))]
14423 "TARGET_SHMEDIA"
14424 "mshard.w %1, %2, %0"
73a4d10b
R
14425 [(set_attr "type" "arith_media")
14426 (set_attr "highpart" "depend")])
c1b92d09
R
14427
14428(define_insn "mshards_q"
14429 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
14430 (ss_truncate:HI
14431 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
735cb76e 14432 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
c1b92d09
R
14433 "TARGET_SHMEDIA"
14434 "mshards.q %1, %N2, %0"
14435 [(set_attr "type" "mcmp_media")])
14436
14437(define_expand "mshfhi_b"
14438 [(match_operand:V8QI 0 "arith_reg_dest" "")
735cb76e
R
14439 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14440 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14441 "TARGET_SHMEDIA"
c1b92d09
R
14442{
14443 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
14444 (operands[0], operands[1], operands[2]));
8721e3df 14445 DONE;
d9241861 14446})
c1b92d09
R
14447
14448(define_expand "mshflo_b"
14449 [(match_operand:V8QI 0 "arith_reg_dest" "")
735cb76e
R
14450 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14451 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14452 "TARGET_SHMEDIA"
c1b92d09
R
14453{
14454 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
14455 (operands[0], operands[1], operands[2]));
8721e3df 14456 DONE;
d9241861 14457})
c1b92d09
R
14458
14459(define_insn "mshf4_b"
14460 [(set
14461 (match_operand:V8QI 0 "arith_reg_dest" "=r")
14462 (vec_select:V8QI
735cb76e
R
14463 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14464 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
0ac78517
R
14465 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
14466 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
c1b92d09 14467 "TARGET_SHMEDIA"
d9241861
OE
14468{
14469 return (TARGET_LITTLE_ENDIAN
14470 ? "mshfhi.b %N1, %N2, %0"
14471 : "mshflo.b %N1, %N2, %0");
14472}
73a4d10b
R
14473 [(set_attr "type" "arith_media")
14474 (set (attr "highpart")
14475 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14476 (const_string "user")))])
c1b92d09
R
14477
14478(define_insn "mshf0_b"
14479 [(set
14480 (match_operand:V8QI 0 "arith_reg_dest" "=r")
14481 (vec_select:V8QI
735cb76e
R
14482 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14483 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
0ac78517
R
14484 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
14485 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
c1b92d09 14486 "TARGET_SHMEDIA"
d9241861
OE
14487{
14488 return (TARGET_LITTLE_ENDIAN
14489 ? "mshflo.b %N1, %N2, %0"
14490 : "mshfhi.b %N1, %N2, %0");
14491}
73a4d10b
R
14492 [(set_attr "type" "arith_media")
14493 (set (attr "highpart")
14494 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14495 (const_string "user")))])
c1b92d09
R
14496
14497(define_expand "mshfhi_l"
14498 [(match_operand:V2SI 0 "arith_reg_dest" "")
735cb76e
R
14499 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14500 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14501 "TARGET_SHMEDIA"
c1b92d09
R
14502{
14503 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
14504 (operands[0], operands[1], operands[2]));
8721e3df 14505 DONE;
d9241861 14506})
c1b92d09
R
14507
14508(define_expand "mshflo_l"
14509 [(match_operand:V2SI 0 "arith_reg_dest" "")
735cb76e
R
14510 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14511 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14512 "TARGET_SHMEDIA"
c1b92d09
R
14513{
14514 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
14515 (operands[0], operands[1], operands[2]));
8721e3df 14516 DONE;
d9241861 14517})
c1b92d09
R
14518
14519(define_insn "mshf4_l"
14520 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14521 (vec_select:V2SI
735cb76e
R
14522 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14523 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
0ac78517 14524 (parallel [(const_int 1) (const_int 3)])))]
c1b92d09 14525 "TARGET_SHMEDIA"
d9241861
OE
14526{
14527 return (TARGET_LITTLE_ENDIAN
14528 ? "mshfhi.l %N1, %N2, %0"
14529 : "mshflo.l %N1, %N2, %0");
14530}
73a4d10b
R
14531 [(set_attr "type" "arith_media")
14532 (set (attr "highpart")
14533 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14534 (const_string "user")))])
c1b92d09
R
14535
14536(define_insn "mshf0_l"
14537 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14538 (vec_select:V2SI
735cb76e
R
14539 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14540 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
0ac78517 14541 (parallel [(const_int 0) (const_int 2)])))]
c1b92d09 14542 "TARGET_SHMEDIA"
d9241861
OE
14543{
14544 return (TARGET_LITTLE_ENDIAN
14545 ? "mshflo.l %N1, %N2, %0"
14546 : "mshfhi.l %N1, %N2, %0");
14547}
73a4d10b
R
14548 [(set_attr "type" "arith_media")
14549 (set (attr "highpart")
14550 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14551 (const_string "user")))])
c1b92d09
R
14552
14553(define_expand "mshfhi_w"
14554 [(match_operand:V4HI 0 "arith_reg_dest" "")
735cb76e
R
14555 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14556 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14557 "TARGET_SHMEDIA"
c1b92d09
R
14558{
14559 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
14560 (operands[0], operands[1], operands[2]));
8721e3df 14561 DONE;
d9241861 14562})
c1b92d09
R
14563
14564(define_expand "mshflo_w"
14565 [(match_operand:V4HI 0 "arith_reg_dest" "")
735cb76e
R
14566 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14567 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
c1b92d09 14568 "TARGET_SHMEDIA"
c1b92d09
R
14569{
14570 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
14571 (operands[0], operands[1], operands[2]));
8721e3df 14572 DONE;
d9241861 14573})
c1b92d09
R
14574
14575(define_insn "mshf4_w"
14576 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14577 (vec_select:V4HI
735cb76e
R
14578 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14579 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
0ac78517 14580 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
c1b92d09 14581 "TARGET_SHMEDIA"
d9241861
OE
14582{
14583 return (TARGET_LITTLE_ENDIAN
14584 ? "mshfhi.w %N1, %N2, %0"
14585 : "mshflo.w %N1, %N2, %0");
14586}
73a4d10b
R
14587 [(set_attr "type" "arith_media")
14588 (set (attr "highpart")
14589 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14590 (const_string "user")))])
c1b92d09
R
14591
14592(define_insn "mshf0_w"
14593 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14594 (vec_select:V4HI
735cb76e
R
14595 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14596 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
0ac78517 14597 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
c1b92d09 14598 "TARGET_SHMEDIA"
d9241861
OE
14599{
14600 return (TARGET_LITTLE_ENDIAN
14601 ? "mshflo.w %N1, %N2, %0"
14602 : "mshfhi.w %N1, %N2, %0");
14603}
73a4d10b
R
14604 [(set_attr "type" "arith_media")
14605 (set (attr "highpart")
14606 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14607 (const_string "user")))])
c1b92d09 14608
0ac78517
R
14609(define_insn "mshflo_w_x"
14610 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14611 (vec_select:V4HI
735cb76e
R
14612 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
14613 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
08c43ea7 14614 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
0ac78517
R
14615 "TARGET_SHMEDIA"
14616 "mshflo.w %N1, %N2, %0"
73a4d10b
R
14617 [(set_attr "type" "arith_media")
14618 (set_attr "highpart" "ignore")])
0ac78517 14619
2eff0b9d 14620;; These are useful to expand ANDs and as combiner patterns.
0ac78517
R
14621(define_insn_and_split "mshfhi_l_di"
14622 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
735cb76e 14623 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
c1b92d09 14624 (const_int 32))
735cb76e 14625 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
c1b92d09
R
14626 (const_int -4294967296))))]
14627 "TARGET_SHMEDIA"
0ac78517
R
14628 "@
14629 mshfhi.l %N1, %N2, %0
14630 #"
14631 "TARGET_SHMEDIA && reload_completed
14632 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14633 [(set (match_dup 3) (match_dup 4))
14634 (set (match_dup 5) (match_dup 6))]
0ac78517
R
14635{
14636 operands[3] = gen_lowpart (SImode, operands[0]);
14637 operands[4] = gen_highpart (SImode, operands[1]);
14638 operands[5] = gen_highpart (SImode, operands[0]);
14639 operands[6] = gen_highpart (SImode, operands[2]);
d9241861 14640}
c1b92d09
R
14641 [(set_attr "type" "arith_media")])
14642
14643(define_insn "*mshfhi_l_di_rev"
14644 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
735cb76e 14645 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09 14646 (const_int -4294967296))
735cb76e 14647 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
c1b92d09
R
14648 (const_int 32))))]
14649 "TARGET_SHMEDIA"
14650 "mshfhi.l %N2, %N1, %0"
14651 [(set_attr "type" "arith_media")])
14652
52702ae1
R
14653(define_split
14654 [(set (match_operand:DI 0 "arith_reg_dest" "")
14655 (ior:DI (zero_extend:DI (match_operand:SI 1
14656 "extend_reg_or_0_operand" ""))
14657 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
14658 (const_int -4294967296))))
14659 (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
14660 "TARGET_SHMEDIA"
14661 [(const_int 0)]
52702ae1
R
14662{
14663 emit_insn (gen_ashldi3_media (operands[3],
14664 simplify_gen_subreg (DImode, operands[1],
14665 SImode, 0),
14666 GEN_INT (32)));
14667 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
14668 DONE;
d9241861 14669})
52702ae1 14670
c1b92d09
R
14671(define_insn "mshflo_l_di"
14672 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
735cb76e 14673 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09 14674 (const_int 4294967295))
735cb76e 14675 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
c1b92d09 14676 (const_int 32))))]
73774972 14677
c1b92d09
R
14678 "TARGET_SHMEDIA"
14679 "mshflo.l %N1, %N2, %0"
73a4d10b
R
14680 [(set_attr "type" "arith_media")
14681 (set_attr "highpart" "ignore")])
c1b92d09
R
14682
14683(define_insn "*mshflo_l_di_rev"
14684 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
735cb76e 14685 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09 14686 (const_int 32))
735cb76e 14687 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
c1b92d09 14688 (const_int 4294967295))))]
73774972 14689
c1b92d09
R
14690 "TARGET_SHMEDIA"
14691 "mshflo.l %N2, %N1, %0"
73a4d10b
R
14692 [(set_attr "type" "arith_media")
14693 (set_attr "highpart" "ignore")])
c1b92d09 14694
ca903bba
R
14695;; Combiner pattern for trampoline initialization.
14696(define_insn_and_split "*double_shori"
14697 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14698 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
14699 (const_int 32))
14700 (match_operand:DI 2 "const_int_operand" "n")))]
14701 "TARGET_SHMEDIA
42201282 14702 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
ca903bba
R
14703 "#"
14704 "rtx_equal_p (operands[0], operands[1])"
14705 [(const_int 0)]
ca903bba
R
14706{
14707 HOST_WIDE_INT v = INTVAL (operands[2]);
14708
42201282
R
14709 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
14710 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
ca903bba 14711 DONE;
d9241861 14712}
73a4d10b 14713 [(set_attr "highpart" "ignore")])
ca903bba
R
14714
14715
c1b92d09
R
14716(define_insn "*mshflo_l_di_x"
14717 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
0ac78517 14718 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
735cb76e
R
14719 "rZ"))
14720 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
c1b92d09 14721 (const_int 32))))]
73774972 14722
c1b92d09
R
14723 "TARGET_SHMEDIA"
14724 "mshflo.l %N1, %N2, %0"
73a4d10b
R
14725 [(set_attr "type" "arith_media")
14726 (set_attr "highpart" "ignore")])
c1b92d09 14727
0ac78517
R
14728(define_insn_and_split "concat_v2sf"
14729 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
735cb76e
R
14730;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
14731 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
14732 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
73774972 14733
0ac78517
R
14734 "TARGET_SHMEDIA"
14735 "@
14736 mshflo.l %N1, %N2, %0
14737 #
14738 #"
14739 "TARGET_SHMEDIA && reload_completed
14740 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14741 [(set (match_dup 3) (match_dup 1))
14742 (set (match_dup 4) (match_dup 2))]
0ac78517
R
14743{
14744 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
14745 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
d9241861 14746}
73a4d10b
R
14747 [(set_attr "type" "arith_media")
14748 (set_attr "highpart" "ignore")])
0ac78517 14749
c1b92d09
R
14750(define_insn "*mshflo_l_di_x_rev"
14751 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
735cb76e 14752 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09 14753 (const_int 32))
735cb76e 14754 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
73774972 14755
c1b92d09
R
14756 "TARGET_SHMEDIA"
14757 "mshflo.l %N2, %N1, %0"
73a4d10b
R
14758 [(set_attr "type" "arith_media")
14759 (set_attr "highpart" "ignore")])
c1b92d09
R
14760
14761(define_insn "ashlv2si3"
14762 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14763 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
73a4d10b 14764 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
c1b92d09
R
14765 "TARGET_SHMEDIA"
14766 "mshlld.l %1, %2, %0"
73a4d10b
R
14767 [(set_attr "type" "arith_media")
14768 (set_attr "highpart" "depend")])
14769
14770(define_split
14771 [(set (match_operand 0 "any_register_operand" "")
14772 (match_operator 3 "shift_operator"
14773 [(match_operand 1 "any_register_operand" "")
14774 (match_operand 2 "shift_count_reg_operand" "")]))]
14775 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
14776 [(set (match_dup 0) (match_dup 3))]
73a4d10b
R
14777{
14778 rtx count = operands[2];
14779 enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
14780
14781 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
14782 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
14783 || GET_CODE (count) == TRUNCATE)
14784 count = XEXP (count, 0);
14785 inner_mode = GET_MODE (count);
14786 count = simplify_gen_subreg (outer_mode, count, inner_mode,
14787 subreg_lowpart_offset (outer_mode, inner_mode));
14788 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
14789 operands[1], count);
d9241861 14790})
c1b92d09
R
14791
14792(define_insn "ashlv4hi3"
14793 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14794 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
73a4d10b 14795 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
c1b92d09
R
14796 "TARGET_SHMEDIA"
14797 "mshlld.w %1, %2, %0"
73a4d10b
R
14798 [(set_attr "type" "arith_media")
14799 (set_attr "highpart" "depend")])
c1b92d09
R
14800
14801(define_insn "lshrv2si3"
14802 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14803 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
73a4d10b 14804 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
c1b92d09
R
14805 "TARGET_SHMEDIA"
14806 "mshlrd.l %1, %2, %0"
73a4d10b
R
14807 [(set_attr "type" "arith_media")
14808 (set_attr "highpart" "depend")])
c1b92d09
R
14809
14810(define_insn "lshrv4hi3"
14811 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14812 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
73a4d10b 14813 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
c1b92d09
R
14814 "TARGET_SHMEDIA"
14815 "mshlrd.w %1, %2, %0"
73a4d10b
R
14816 [(set_attr "type" "arith_media")
14817 (set_attr "highpart" "depend")])
c1b92d09
R
14818
14819(define_insn "subv2si3"
14820 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
735cb76e 14821 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09
R
14822 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14823 "TARGET_SHMEDIA"
14824 "msub.l %N1, %2, %0"
73a4d10b
R
14825 [(set_attr "type" "arith_media")
14826 (set_attr "highpart" "depend")])
c1b92d09
R
14827
14828(define_insn "subv4hi3"
14829 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
735cb76e 14830 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09
R
14831 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14832 "TARGET_SHMEDIA"
14833 "msub.w %N1, %2, %0"
73a4d10b
R
14834 [(set_attr "type" "arith_media")
14835 (set_attr "highpart" "depend")])
14836
14837(define_insn_and_split "subv2hi3"
14838 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
14839 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
14840 (match_operand:V2HI 2 "arith_reg_operand" "r")))]
14841 "TARGET_SHMEDIA"
14842 "#"
14843 "TARGET_SHMEDIA"
14844 [(const_int 0)]
73a4d10b
R
14845{
14846 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
14847 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
14848 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
14849 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
14850 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
14851
14852 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
14853 emit_insn (gen_truncdisi2 (si_dst, di_dst));
14854 DONE;
d9241861 14855}
73a4d10b 14856 [(set_attr "highpart" "must_split")])
c1b92d09
R
14857
14858(define_insn "sssubv2si3"
14859 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
735cb76e 14860 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09
R
14861 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14862 "TARGET_SHMEDIA"
14863 "msubs.l %N1, %2, %0"
73a4d10b
R
14864 [(set_attr "type" "mcmp_media")
14865 (set_attr "highpart" "depend")])
c1b92d09
R
14866
14867(define_insn "ussubv8qi3"
14868 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
73a4d10b 14869 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09
R
14870 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
14871 "TARGET_SHMEDIA"
73a4d10b
R
14872 "msubs.ub %N1, %2, %0"
14873 [(set_attr "type" "mcmp_media")
14874 (set_attr "highpart" "depend")])
c1b92d09
R
14875
14876(define_insn "sssubv4hi3"
14877 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
735cb76e 14878 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
c1b92d09
R
14879 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14880 "TARGET_SHMEDIA"
14881 "msubs.w %N1, %2, %0"
73a4d10b
R
14882 [(set_attr "type" "mcmp_media")
14883 (set_attr "highpart" "depend")])
c1b92d09
R
14884
14885;; Floating Point Intrinsics
14886
14887(define_insn "fcosa_s"
14888 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14889 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
14890 UNSPEC_FCOSA))]
14891 "TARGET_SHMEDIA"
14892 "fcosa.s %1, %0"
14893 [(set_attr "type" "atrans_media")])
14894
14895(define_insn "fsina_s"
14896 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14897 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
14898 UNSPEC_FSINA))]
14899 "TARGET_SHMEDIA"
14900 "fsina.s %1, %0"
14901 [(set_attr "type" "atrans_media")])
14902
14903(define_insn "fipr"
14904 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14905 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
14906 "fp_arith_reg_operand" "f")
14907 (match_operand:V4SF 2
14908 "fp_arith_reg_operand" "f"))
0ac78517 14909 (parallel [(const_int 0)]))
c1b92d09 14910 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
0ac78517 14911 (parallel [(const_int 1)])))
c1b92d09 14912 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
0ac78517 14913 (parallel [(const_int 2)]))
c1b92d09 14914 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
0ac78517 14915 (parallel [(const_int 3)])))))]
c1b92d09 14916 "TARGET_SHMEDIA"
40779a72 14917 "fipr.s %1, %2, %0"
c1b92d09
R
14918 [(set_attr "type" "fparith_media")])
14919
14920(define_insn "fsrra_s"
14921 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14922 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
14923 UNSPEC_FSRRA))]
14924 "TARGET_SHMEDIA"
14925 "fsrra.s %1, %0"
14926 [(set_attr "type" "atrans_media")])
14927
14928(define_insn "ftrv"
14929 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
14930 (plus:V4SF
14931 (plus:V4SF
14932 (mult:V4SF
14933 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
0ac78517
R
14934 (parallel [(const_int 0) (const_int 5)
14935 (const_int 10) (const_int 15)]))
c1b92d09
R
14936 (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
14937 (mult:V4SF
14938 (vec_select:V4SF (match_dup 1)
0ac78517
R
14939 (parallel [(const_int 4) (const_int 9)
14940 (const_int 14) (const_int 3)]))
c1b92d09 14941 (vec_select:V4SF (match_dup 2)
0ac78517 14942 (parallel [(const_int 1) (const_int 2)
40779a72 14943 (const_int 3) (const_int 0)]))))
c1b92d09
R
14944 (plus:V4SF
14945 (mult:V4SF
14946 (vec_select:V4SF (match_dup 1)
0ac78517
R
14947 (parallel [(const_int 8) (const_int 13)
14948 (const_int 2) (const_int 7)]))
c1b92d09 14949 (vec_select:V4SF (match_dup 2)
0ac78517
R
14950 (parallel [(const_int 2) (const_int 3)
14951 (const_int 0) (const_int 1)])))
c1b92d09
R
14952 (mult:V4SF
14953 (vec_select:V4SF (match_dup 1)
0ac78517
R
14954 (parallel [(const_int 12) (const_int 1)
14955 (const_int 6) (const_int 11)]))
c1b92d09 14956 (vec_select:V4SF (match_dup 2)
0ac78517
R
14957 (parallel [(const_int 3) (const_int 0)
14958 (const_int 1) (const_int 2)]))))))]
c1b92d09 14959 "TARGET_SHMEDIA"
40779a72 14960 "ftrv.s %1, %2, %0"
c1b92d09
R
14961 [(set_attr "type" "fparith_media")])
14962
73a4d10b
R
14963(define_insn "ldhi_l"
14964 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
14965 (zero_extract:SI
14966 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
14967 (const_int 3))
14968 (const_int -3)))
14969 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
14970 (const_int 0)))]
14971 "TARGET_SHMEDIA32"
14972 "ldhi.l %U1, %0"
14973 [(set_attr "type" "load_media")])
14974
14975(define_insn "ldhi_q"
14976 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14977 (zero_extract:DI
14978 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
14979 (const_int 7))
14980 (const_int -7)))
14981 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
14982 (const_int 0)))]
14983 "TARGET_SHMEDIA32"
14984 "ldhi.q %U1, %0"
14985 [(set_attr "type" "load_media")])
14986
14987(define_insn_and_split "*ldhi_q_comb0"
14988 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14989 (zero_extract:DI
14990 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
14991 "register_operand" "r")
14992 (match_operand:SI 2
14993 "ua_offset" "I06"))
14994 (const_int 7))
14995 (const_int -7)))
14996 (plus:SI (and:SI (match_dup 1) (const_int 7))
14997 (const_int 1))
14998 (const_int 0)))]
14999 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15000 "#"
15001 ""
15002 [(pc)]
d9241861
OE
15003{
15004 emit_insn (gen_ldhi_q (operands[0],
15005 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15006 DONE;
15007})
73a4d10b
R
15008
15009(define_insn_and_split "*ldhi_q_comb1"
15010 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15011 (zero_extract:DI
15012 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
15013 "register_operand" "r")
15014 (match_operand:SI 2
15015 "ua_offset" "I06"))
15016 (const_int 7))
15017 (const_int -7)))
15018 (plus:SI (and:SI (plus:SI (match_dup 1) (match_operand:SI 3
15019 "ua_offset" "I06"))
15020 (const_int 7))
15021 (const_int 1))
15022 (const_int 0)))]
15023 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15024 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15025 "#"
15026 ""
15027 [(pc)]
d9241861
OE
15028{
15029 emit_insn (gen_ldhi_q (operands[0],
15030 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15031 DONE;
15032})
73a4d10b
R
15033
15034(define_insn "ldlo_l"
15035 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15036 (zero_extract:SI
15037 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15038 (const_int -4)))
15039 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
15040 (and:SI (match_dup 1) (const_int 3))))]
15041 "TARGET_SHMEDIA32"
15042 "ldlo.l %U1, %0"
15043 [(set_attr "type" "load_media")])
15044
15045(define_insn "ldlo_q"
15046 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15047 (zero_extract:DI
15048 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
15049 (const_int -8)))
15050 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15051 (and:SI (match_dup 1) (const_int 7))))]
15052 "TARGET_SHMEDIA32"
15053 "ldlo.q %U1, %0"
15054 [(set_attr "type" "load_media")])
15055
15056(define_insn_and_split "*ldlo_q_comb0"
15057 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15058 (zero_extract:DI
15059 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15060 (match_operand:SI 2 "ua_offset" "I06"))
15061 (const_int -8)))
15062 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
15063 (and:SI (match_dup 1) (const_int 7))))]
15064 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
15065 "#"
15066 ""
15067 [(pc)]
d9241861
OE
15068{
15069 emit_insn (gen_ldlo_q (operands[0],
15070 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15071 DONE;
15072})
73a4d10b
R
15073
15074(define_insn_and_split "*ldlo_q_comb1"
15075 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15076 (zero_extract:DI
15077 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
15078 (match_operand:SI 2 "ua_offset" "I06"))
15079 (const_int -8)))
15080 (minus:SI (const_int 8)
15081 (and:SI (plus:SI (match_dup 1)
15082 (match_operand:SI 3 "ua_offset" "I06"))
15083 (const_int 7)))
15084 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
15085 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
15086 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
15087 "#"
15088 ""
15089 [(pc)]
d9241861
OE
15090{
15091 emit_insn (gen_ldlo_q (operands[0],
15092 gen_rtx_PLUS (SImode, operands[1], operands[2])));
15093 DONE;
15094})
73a4d10b
R
15095
15096(define_insn "sthi_l"
15097 [(set (zero_extract:SI
15098 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15099 (const_int 3))
15100 (const_int -3)))
15101 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
15102 (const_int 0))
15103 (match_operand:SI 1 "arith_reg_operand" "r"))]
15104 "TARGET_SHMEDIA32"
15105 "sthi.l %U0, %1"
15106 [(set_attr "type" "ustore_media")])
15107
15108;; All unaligned stores are considered to be 'narrow' because they typically
15109;; operate on less that a quadword, and when they operate on a full quadword,
15110;; the vanilla store high / store low sequence will cause a stall if not
15111;; scheduled apart.
15112(define_insn "sthi_q"
15113 [(set (zero_extract:DI
15114 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
15115 (const_int 7))
15116 (const_int -7)))
15117 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15118 (const_int 0))
15119 (match_operand:DI 1 "arith_reg_operand" "r"))]
15120 "TARGET_SHMEDIA32"
15121 "sthi.q %U0, %1"
15122 [(set_attr "type" "ustore_media")])
15123
15124(define_insn_and_split "*sthi_q_comb0"
15125 [(set (zero_extract:DI
15126 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
15127 "register_operand" "r")
15128 (match_operand:SI 1 "ua_offset"
15129 "I06"))
15130 (const_int 7))
15131 (const_int -7)))
15132 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
15133 (const_int 0))
15134 (match_operand:DI 2 "arith_reg_operand" "r"))]
15135 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15136 "#"
15137 ""
15138 [(pc)]
d9241861
OE
15139{
15140 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15141 operands[2]));
15142 DONE;
15143})
73a4d10b
R
15144
15145(define_insn_and_split "*sthi_q_comb1"
15146 [(set (zero_extract:DI
15147 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
15148 "register_operand" "r")
15149 (match_operand:SI 1 "ua_offset"
15150 "I06"))
15151 (const_int 7))
15152 (const_int -7)))
15153 (plus:SI (and:SI (plus:SI (match_dup 0)
15154 (match_operand:SI 2 "ua_offset" "I06"))
15155 (const_int 7))
15156 (const_int 1))
15157 (const_int 0))
15158 (match_operand:DI 3 "arith_reg_operand" "r"))]
15159 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
15160 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15161 "#"
15162 ""
15163 [(pc)]
d9241861
OE
15164{
15165 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15166 operands[3]));
15167 DONE;
15168})
73a4d10b
R
15169
15170;; This is highpart user because the address is used as full 64 bit.
15171(define_insn "stlo_l"
15172 [(set (zero_extract:SI
15173 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15174 (const_int -4)))
15175 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
15176 (and:SI (match_dup 0) (const_int 3)))
15177 (match_operand:SI 1 "arith_reg_operand" "r"))]
15178 "TARGET_SHMEDIA32"
15179 "stlo.l %U0, %1"
15180 [(set_attr "type" "ustore_media")])
15181
15182(define_insn "stlo_q"
15183 [(set (zero_extract:DI
15184 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
15185 (const_int -8)))
15186 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15187 (and:SI (match_dup 0) (const_int 7)))
15188 (match_operand:DI 1 "arith_reg_operand" "r"))]
15189 "TARGET_SHMEDIA32"
15190 "stlo.q %U0, %1"
15191 [(set_attr "type" "ustore_media")])
15192
15193(define_insn_and_split "*stlo_q_comb0"
15194 [(set (zero_extract:DI
15195 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15196 (match_operand:SI 1 "ua_offset" "I06"))
15197 (const_int -8)))
15198 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
15199 (and:SI (match_dup 0) (const_int 7)))
15200 (match_operand:DI 2 "arith_reg_operand" "r"))]
15201 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15202 "#"
15203 ""
15204 [(pc)]
d9241861
OE
15205{
15206 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15207 operands[2]));
15208 DONE;
15209})
73a4d10b
R
15210
15211(define_insn_and_split "*stlo_q_comb1"
15212 [(set (zero_extract:DI
15213 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15214 (match_operand:SI 1 "ua_offset" "I06"))
15215 (const_int -8)))
15216 (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
15217 (match_operand:SI 2
15218 "ua_offset" "I06"))
15219 (const_int 7)))
15220 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
15221 (match_operand:DI 3 "arith_reg_operand" "r"))]
15222 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15223 "#"
15224 ""
15225 [(pc)]
d9241861
OE
15226{
15227 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15228 operands[3]));
15229 DONE;
15230})
73a4d10b
R
15231
15232(define_insn "ldhi_l64"
15233 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15234 (zero_extract:SI
15235 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15236 (const_int 3))
15237 (const_int -3)))
15238 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
15239 (const_int 0)))]
15240 "TARGET_SHMEDIA64"
15241 "ldhi.l %U1, %0"
15242 [(set_attr "type" "load_media")])
15243
15244(define_insn "ldhi_q64"
15245 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15246 (zero_extract:DI
15247 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15248 (const_int 7))
15249 (const_int -7)))
15250 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
15251 (const_int 0)))]
15252 "TARGET_SHMEDIA64"
15253 "ldhi.q %U1, %0"
15254 [(set_attr "type" "load_media")])
15255
15256(define_insn "ldlo_l64"
15257 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15258 (zero_extract:SI
15259 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15260 (const_int -4)))
15261 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
15262 (and:DI (match_dup 1) (const_int 3))))]
15263 "TARGET_SHMEDIA64"
15264 "ldlo.l %U1, %0"
15265 [(set_attr "type" "load_media")])
15266
15267(define_insn "ldlo_q64"
15268 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15269 (zero_extract:DI
15270 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15271 (const_int -8)))
15272 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
15273 (and:DI (match_dup 1) (const_int 7))))]
15274 "TARGET_SHMEDIA64"
15275 "ldlo.q %U1, %0"
15276 [(set_attr "type" "load_media")])
15277
15278(define_insn "sthi_l64"
15279 [(set (zero_extract:SI
15280 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15281 (const_int 3))
15282 (const_int -3)))
15283 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
15284 (const_int 0))
15285 (match_operand:SI 1 "arith_reg_operand" "r"))]
15286 "TARGET_SHMEDIA64"
15287 "sthi.l %U0, %1"
15288 [(set_attr "type" "ustore_media")])
15289
15290(define_insn "sthi_q64"
15291 [(set (zero_extract:DI
15292 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15293 (const_int 7))
15294 (const_int -7)))
15295 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
15296 (const_int 0))
15297 (match_operand:DI 1 "arith_reg_operand" "r"))]
15298 "TARGET_SHMEDIA64"
15299 "sthi.q %U0, %1"
15300 [(set_attr "type" "ustore_media")])
15301
15302(define_insn "stlo_l64"
15303 [(set (zero_extract:SI
15304 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15305 (const_int -4)))
15306 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
15307 (and:DI (match_dup 0) (const_int 3)))
15308 (match_operand:SI 1 "arith_reg_operand" "r"))]
15309 "TARGET_SHMEDIA64"
15310 "stlo.l %U0, %1"
15311 [(set_attr "type" "ustore_media")])
15312
15313(define_insn "stlo_q64"
15314 [(set (zero_extract:DI
15315 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15316 (const_int -8)))
15317 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
15318 (and:DI (match_dup 0) (const_int 7)))
15319 (match_operand:DI 1 "arith_reg_operand" "r"))]
15320 "TARGET_SHMEDIA64"
15321 "stlo.q %U0, %1"
15322 [(set_attr "type" "ustore_media")])
15323
b6d33983
R
15324(define_insn "nsb"
15325 [(set (match_operand:QI 0 "arith_reg_dest" "=r")
15326 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15327 UNSPEC_NSB))]
15328 "TARGET_SHMEDIA"
15329 "nsb %1, %0"
15330 [(set_attr "type" "arith_media")])
15331
15332(define_insn "nsbsi"
15333 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15334 (zero_extend:SI
15335 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15336 UNSPEC_NSB)))]
15337 "TARGET_SHMEDIA"
15338 "nsb %1, %0"
15339 [(set_attr "type" "arith_media")])
15340
15341(define_insn "nsbdi"
15342 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15343 (zero_extend:DI
15344 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15345 UNSPEC_NSB)))]
15346 "TARGET_SHMEDIA"
15347 "nsb %1, %0"
15348 [(set_attr "type" "arith_media")])
15349
15350(define_expand "ffsdi2"
15351 [(set (match_operand:DI 0 "arith_reg_dest" "")
15352 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
15353 "TARGET_SHMEDIA"
b6d33983
R
15354{
15355 rtx scratch = gen_reg_rtx (DImode);
15356 rtx last;
15357
a556fd39 15358 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
b6d33983
R
15359 emit_insn (gen_xordi3 (scratch, operands[1], scratch));
15360 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
15361 emit_insn (gen_nsbdi (scratch, scratch));
15362 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
15363 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
15364 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
bd94cb6e
SB
15365 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
15366
b6d33983 15367 DONE;
d9241861 15368})
b6d33983
R
15369
15370(define_expand "ffssi2"
15371 [(set (match_operand:SI 0 "arith_reg_dest" "")
15372 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
15373 "TARGET_SHMEDIA"
b6d33983
R
15374{
15375 rtx scratch = gen_reg_rtx (SImode);
15376 rtx discratch = gen_reg_rtx (DImode);
15377 rtx last;
15378
e3c62520
R
15379 emit_insn (gen_adddi3 (discratch,
15380 simplify_gen_subreg (DImode, operands[1], SImode, 0),
a556fd39 15381 constm1_rtx));
e3c62520
R
15382 emit_insn (gen_andcdi3 (discratch,
15383 simplify_gen_subreg (DImode, operands[1], SImode, 0),
15384 discratch));
b6d33983
R
15385 emit_insn (gen_nsbsi (scratch, discratch));
15386 last = emit_insn (gen_subsi3 (operands[0],
e3c62520 15387 force_reg (SImode, GEN_INT (63)), scratch));
bd94cb6e
SB
15388 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
15389
b6d33983 15390 DONE;
d9241861 15391})
b6d33983
R
15392
15393(define_insn "byterev"
15394 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15395 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
15396 (parallel [(const_int 7) (const_int 6) (const_int 5)
15397 (const_int 4) (const_int 3) (const_int 2)
15398 (const_int 1) (const_int 0)])))]
15399 "TARGET_SHMEDIA"
15400 "byterev %1, %0"
15401 [(set_attr "type" "arith_media")])
15402
e0ff69ab
RS
15403;; In user mode, the "pref" instruction will raise a RADDERR exception
15404;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable
15405;; implementation of __builtin_prefetch for VxWorks RTPs.
07ea92d3 15406(define_expand "prefetch"
69853ea9
OE
15407 [(prefetch (match_operand 0 "address_operand" "")
15408 (match_operand:SI 1 "const_int_operand" "")
15409 (match_operand:SI 2 "const_int_operand" ""))]
15410 "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
15411 && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
73a4d10b 15412
6b45f126 15413(define_insn "*prefetch"
b4b0018b
N
15414 [(prefetch (match_operand:SI 0 "register_operand" "r")
15415 (match_operand:SI 1 "const_int_operand" "n")
15416 (match_operand:SI 2 "const_int_operand" "n"))]
69853ea9 15417 "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
6b45f126 15418 "pref @%0"
b4b0018b
N
15419 [(set_attr "type" "other")])
15420
69853ea9
OE
15421(define_insn "*prefetch_media"
15422 [(prefetch (match_operand:QI 0 "address_operand" "p")
15423 (match_operand:SI 1 "const_int_operand" "n")
15424 (match_operand:SI 2 "const_int_operand" "n"))]
15425 "TARGET_SHMEDIA"
15426{
15427 operands[0] = gen_rtx_MEM (QImode, operands[0]);
15428 output_asm_insn ("ld%M0.b %m0,r63", operands);
15429 return "";
15430}
15431 [(set_attr "type" "other")])
15432
73a4d10b
R
15433(define_insn "alloco_i"
15434 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
15435 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
15436 "TARGET_SHMEDIA32"
73a4d10b
R
15437{
15438 rtx xops[2];
15439
15440 if (GET_CODE (operands[0]) == PLUS)
15441 {
15442 xops[0] = XEXP (operands[0], 0);
15443 xops[1] = XEXP (operands[0], 1);
15444 }
15445 else
07ea92d3 15446 {
73a4d10b
R
15447 xops[0] = operands[0];
15448 xops[1] = const0_rtx;
07ea92d3 15449 }
d9241861
OE
15450 output_asm_insn ("alloco %0, %1", xops);
15451 return "";
15452}
73a4d10b 15453 [(set_attr "type" "other")])
07ea92d3 15454
73a4d10b
R
15455(define_split
15456 [(set (match_operand 0 "any_register_operand" "")
15457 (match_operand 1 "" ""))]
15458 "TARGET_SHMEDIA && reload_completed"
15459 [(set (match_dup 0) (match_dup 1))]
73a4d10b
R
15460{
15461 int n_changes = 0;
15462
15463 for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
15464 if (!n_changes)
15465 FAIL;
d9241861 15466})
50b69666
KK
15467
15468; Stack Protector Patterns
15469
15470(define_expand "stack_protect_set"
15471 [(set (match_operand 0 "memory_operand" "")
15472 (match_operand 1 "memory_operand" ""))]
15473 ""
15474{
15475 if (TARGET_SHMEDIA)
15476 {
15477 if (TARGET_SHMEDIA64)
15478 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
15479 else
15480 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
15481 }
15482 else
15483 emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
15484
15485 DONE;
15486})
15487
15488(define_insn "stack_protect_set_si"
15489 [(set (match_operand:SI 0 "memory_operand" "=m")
15490 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15491 (set (match_scratch:SI 2 "=&r") (const_int 0))]
15492 "!TARGET_SHMEDIA"
35ed5a70
OE
15493{
15494 return "mov.l %1,%2" "\n"
15495 " mov.l %2,%0" "\n"
15496 " mov #0,%2";
15497}
50b69666
KK
15498 [(set_attr "type" "other")
15499 (set_attr "length" "6")])
15500
15501(define_insn "stack_protect_set_si_media"
15502 [(set (match_operand:SI 0 "memory_operand" "=m")
15503 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15504 (set (match_scratch:SI 2 "=&r") (const_int 0))]
15505 "TARGET_SHMEDIA"
35ed5a70
OE
15506{
15507 return "ld%M1.l %m1,%2" "\n"
15508 " st%M0.l %m0,%2" "\n"
15509 " movi 0,%2";
15510}
50b69666
KK
15511 [(set_attr "type" "other")
15512 (set_attr "length" "12")])
15513
15514(define_insn "stack_protect_set_di_media"
15515 [(set (match_operand:DI 0 "memory_operand" "=m")
15516 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15517 (set (match_scratch:DI 2 "=&r") (const_int 0))]
15518 "TARGET_SHMEDIA64"
35ed5a70
OE
15519{
15520 return "ld%M1.q %m1,%2" "\n"
15521 " st%M0.q %m0,%2" "\n"
15522 " movi 0,%2";
15523}
50b69666
KK
15524 [(set_attr "type" "other")
15525 (set_attr "length" "12")])
15526
15527(define_expand "stack_protect_test"
15528 [(match_operand 0 "memory_operand" "")
15529 (match_operand 1 "memory_operand" "")
15530 (match_operand 2 "" "")]
15531 ""
15532{
15533 if (TARGET_SHMEDIA)
15534 {
15535 rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
f90b7a5a 15536 rtx test;
50b69666 15537
f90b7a5a 15538 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
50b69666 15539 if (TARGET_SHMEDIA64)
f90b7a5a
PB
15540 {
15541 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
15542 operands[1]));
15543 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
15544 }
50b69666 15545 else
f90b7a5a
PB
15546 {
15547 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
15548 operands[1]));
15549 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
15550 }
50b69666
KK
15551 }
15552 else
15553 {
15554 emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
b4eca9c8 15555 emit_jump_insn (gen_branch_true (operands[2]));
50b69666
KK
15556 }
15557
15558 DONE;
15559})
15560
15561(define_insn "stack_protect_test_si"
15562 [(set (reg:SI T_REG)
15563 (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
15564 (match_operand:SI 1 "memory_operand" "m")]
15565 UNSPEC_SP_TEST))
15566 (set (match_scratch:SI 2 "=&r") (const_int 0))
15567 (set (match_scratch:SI 3 "=&r") (const_int 0))]
15568 "!TARGET_SHMEDIA"
35ed5a70
OE
15569{
15570 return "mov.l %0,%2" "\n"
15571 " mov.l %1,%3" "\n"
15572 " cmp/eq %2,%3" "\n"
15573 " mov #0,%2" "\n"
15574 " mov #0,%3";
15575}
50b69666
KK
15576 [(set_attr "type" "other")
15577 (set_attr "length" "10")])
15578
15579(define_insn "stack_protect_test_si_media"
15580 [(set (match_operand:SI 0 "register_operand" "=&r")
15581 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
15582 (match_operand:SI 2 "memory_operand" "m")]
15583 UNSPEC_SP_TEST))
15584 (set (match_scratch:SI 3 "=&r") (const_int 0))]
15585 "TARGET_SHMEDIA"
35ed5a70
OE
15586{
15587 return "ld%M1.l %m1,%0" "\n"
15588 " ld%M2.l %m2,%3" "\n"
15589 " cmpeq %0,%3,%0" "\n"
15590 " movi 0,%3";
15591}
50b69666
KK
15592 [(set_attr "type" "other")
15593 (set_attr "length" "16")])
15594
15595(define_insn "stack_protect_test_di_media"
15596 [(set (match_operand:DI 0 "register_operand" "=&r")
15597 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
15598 (match_operand:DI 2 "memory_operand" "m")]
15599 UNSPEC_SP_TEST))
15600 (set (match_scratch:DI 3 "=&r") (const_int 0))]
15601 "TARGET_SHMEDIA64"
35ed5a70
OE
15602{
15603 return "ld%M1.q %m1,%0" "\n"
15604 " ld%M2.q %m2,%3" "\n"
15605 " cmpeq %0,%3,%0" "\n"
15606 " movi 0,%3";
15607}
50b69666
KK
15608 [(set_attr "type" "other")
15609 (set_attr "length" "16")])
7768ec4c
KK
15610
15611(include "sync.md")