]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/sh/sh.md
2ef4a1a4ee0b6158c549c53637e50293af4ea686
[thirdparty/gcc.git] / gcc / config / sh / sh.md
1 ;;- Machine description for Renesas / SuperH SH.
2 ;; Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3 ;; 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 ;; Free Software Foundation, Inc.
5 ;; Contributed by Steve Chamberlain (sac@cygnus.com).
6 ;; Improved by Jim Wilson (wilson@cygnus.com).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; any later version.
14
15 ;; GCC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING3. If not see
22 ;; <http://www.gnu.org/licenses/>.
23
24
25 ;; ??? Should prepend a * to all pattern names which are not used.
26 ;; This will make the compiler smaller, and rebuilds after changes faster.
27
28 ;; ??? Should be enhanced to include support for many more GNU superoptimizer
29 ;; sequences. Especially the sequences for arithmetic right shifts.
30
31 ;; ??? Should check all DImode patterns for consistency and usefulness.
32
33 ;; ??? The MAC.W and MAC.L instructions are not supported. There is no
34 ;; way to generate them.
35
36 ;; ??? The cmp/str instruction is not supported. Perhaps it can be used
37 ;; for a str* inline function.
38
39 ;; BSR is not generated by the compiler proper, but when relaxing, it
40 ;; generates .uses pseudo-ops that allow linker relaxation to create
41 ;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c
42
43 ;; Special constraints for SH machine description:
44 ;;
45 ;; t -- T
46 ;; x -- mac
47 ;; l -- pr
48 ;; z -- r0
49 ;;
50 ;; Special formats used for outputting SH instructions:
51 ;;
52 ;; %. -- print a .s if insn needs delay slot
53 ;; %@ -- print rte/rts if is/isn't an interrupt function
54 ;; %# -- output a nop if there is nothing to put in the delay slot
55 ;; %O -- print a constant without the #
56 ;; %R -- print the lsw reg of a double
57 ;; %S -- print the msw reg of a double
58 ;; %T -- print next word of a double REG or MEM
59 ;;
60 ;; Special predicates:
61 ;;
62 ;; arith_operand -- operand is valid source for arithmetic op
63 ;; arith_reg_operand -- operand is valid register for arithmetic op
64 ;; general_movdst_operand -- operand is valid move destination
65 ;; general_movsrc_operand -- operand is valid move source
66 ;; logical_operand -- operand is valid source for logical op
67
68 ;; -------------------------------------------------------------------------
69 ;; Constants
70 ;; -------------------------------------------------------------------------
71
72 (define_constants [
73 (AP_REG 145)
74 (PR_REG 146)
75 (T_REG 147)
76 (GBR_REG 144)
77 (MACH_REG 148)
78 (MACL_REG 149)
79 (FPUL_REG 150)
80 (RAP_REG 152)
81
82 (FPSCR_REG 151)
83
84 (PIC_REG 12)
85 (FP_REG 14)
86 (SP_REG 15)
87
88 (PR_MEDIA_REG 18)
89 (T_MEDIA_REG 19)
90
91 (R0_REG 0)
92 (R1_REG 1)
93 (R2_REG 2)
94 (R3_REG 3)
95 (R4_REG 4)
96 (R5_REG 5)
97 (R6_REG 6)
98 (R7_REG 7)
99 (R8_REG 8)
100 (R9_REG 9)
101 (R10_REG 10)
102 (R20_REG 20)
103 (R21_REG 21)
104 (R22_REG 22)
105 (R23_REG 23)
106
107 (DR0_REG 64)
108 (DR2_REG 66)
109 (DR4_REG 68)
110 (FR23_REG 87)
111
112 (TR0_REG 128)
113 (TR1_REG 129)
114 (TR2_REG 130)
115
116 (XD0_REG 136)
117
118 ;; These are used with unspec.
119 (UNSPEC_COMPACT_ARGS 0)
120 (UNSPEC_MOVA 1)
121 (UNSPEC_CASESI 2)
122 (UNSPEC_DATALABEL 3)
123 (UNSPEC_BBR 4)
124 (UNSPEC_SFUNC 5)
125 (UNSPEC_PIC 6)
126 (UNSPEC_GOT 7)
127 (UNSPEC_GOTOFF 8)
128 (UNSPEC_PLT 9)
129 (UNSPEC_CALLER 10)
130 (UNSPEC_GOTPLT 11)
131 (UNSPEC_ICACHE 12)
132 (UNSPEC_INIT_TRAMP 13)
133 (UNSPEC_FCOSA 14)
134 (UNSPEC_FSRRA 15)
135 (UNSPEC_FSINA 16)
136 (UNSPEC_NSB 17)
137 (UNSPEC_ALLOCO 18)
138 (UNSPEC_TLSGD 20)
139 (UNSPEC_TLSLDM 21)
140 (UNSPEC_TLSIE 22)
141 (UNSPEC_DTPOFF 23)
142 (UNSPEC_GOTTPOFF 24)
143 (UNSPEC_TPOFF 25)
144 (UNSPEC_RA 26)
145 (UNSPEC_DIV_INV_M0 30)
146 (UNSPEC_DIV_INV_M1 31)
147 (UNSPEC_DIV_INV_M2 32)
148 (UNSPEC_DIV_INV_M3 33)
149 (UNSPEC_DIV_INV20 34)
150 (UNSPEC_DIV_INV_TABLE 37)
151 (UNSPEC_ASHIFTRT 35)
152 (UNSPEC_THUNK 36)
153 (UNSPEC_CHKADD 38)
154 (UNSPEC_SP_SET 40)
155 (UNSPEC_SP_TEST 41)
156 (UNSPEC_MOVUA 42)
157
158 ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
159 ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
160 (UNSPEC_EXTRACT_S16 43)
161 (UNSPEC_EXTRACT_U16 44)
162
163 ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
164 (UNSPEC_SYMOFF 45)
165
166 ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
167 (UNSPEC_PCREL_SYMOFF 46)
168
169 ;; These are used with unspec_volatile.
170 (UNSPECV_BLOCKAGE 0)
171 (UNSPECV_ALIGN 1)
172 (UNSPECV_CONST2 2)
173 (UNSPECV_CONST4 4)
174 (UNSPECV_CONST8 6)
175 (UNSPECV_WINDOW_END 10)
176 (UNSPECV_CONST_END 11)
177 (UNSPECV_EH_RETURN 12)
178 (UNSPECV_GBR 13)
179 ])
180
181 ;; -------------------------------------------------------------------------
182 ;; Attributes
183 ;; -------------------------------------------------------------------------
184
185 ;; Target CPU.
186
187 (define_attr "cpu"
188 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
189 (const (symbol_ref "sh_cpu_attr")))
190
191 (define_attr "endian" "big,little"
192 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
193 (const_string "little") (const_string "big"))))
194
195 ;; Indicate if the default fpu mode is single precision.
196 (define_attr "fpu_single" "yes,no"
197 (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
198 (const_string "yes") (const_string "no"))))
199
200 (define_attr "fmovd" "yes,no"
201 (const (if_then_else (symbol_ref "TARGET_FMOVD")
202 (const_string "yes") (const_string "no"))))
203 ;; pipeline model
204 (define_attr "pipe_model" "sh1,sh4,sh5media"
205 (const
206 (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
207 (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
208 (const_string "sh1"))))
209
210 ;; cbranch conditional branch instructions
211 ;; jump unconditional jumps
212 ;; arith ordinary arithmetic
213 ;; arith3 a compound insn that behaves similarly to a sequence of
214 ;; three insns of type arith
215 ;; arith3b like above, but might end with a redirected branch
216 ;; load from memory
217 ;; load_si Likewise, SImode variant for general register.
218 ;; fload Likewise, but load to fp register.
219 ;; store to memory
220 ;; fstore floating point register to memory
221 ;; move general purpose register to register
222 ;; movi8 8-bit immediate to general purpose register
223 ;; mt_group other sh4 mt instructions
224 ;; fmove register to register, floating point
225 ;; smpy word precision integer multiply
226 ;; dmpy longword or doublelongword precision integer multiply
227 ;; return rts
228 ;; pload load of pr reg, which can't be put into delay slot of rts
229 ;; prset copy register to pr reg, ditto
230 ;; pstore store of pr reg, which can't be put into delay slot of jsr
231 ;; prget copy pr to register, ditto
232 ;; pcload pc relative load of constant value
233 ;; pcfload Likewise, but load to fp register.
234 ;; pcload_si Likewise, SImode variant for general register.
235 ;; rte return from exception
236 ;; sfunc special function call with known used registers
237 ;; call function call
238 ;; fp floating point
239 ;; fpscr_toggle toggle a bit in the fpscr
240 ;; fdiv floating point divide (or square root)
241 ;; gp_fpul move from general purpose register to fpul
242 ;; fpul_gp move from fpul to general purpose register
243 ;; mac_gp move from mac[lh] to general purpose register
244 ;; gp_mac move from general purpose register to mac[lh]
245 ;; mac_mem move from mac[lh] to memory
246 ;; mem_mac move from memory to mac[lh]
247 ;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
248 ;; ftrc_s fix_truncsfsi2_i4
249 ;; dfdiv double precision floating point divide (or square root)
250 ;; cwb ic_invalidate_line_i
251 ;; movua SH4a unaligned load
252 ;; fsrra square root reciprocal approximate
253 ;; fsca sine and cosine approximate
254 ;; tls_load load TLS related address
255 ;; arith_media SHmedia arithmetic, logical, and shift instructions
256 ;; cbranch_media SHmedia conditional branch instructions
257 ;; cmp_media SHmedia compare instructions
258 ;; dfdiv_media SHmedia double precision divide and square root
259 ;; dfmul_media SHmedia double precision multiply instruction
260 ;; dfparith_media SHmedia double precision floating point arithmetic
261 ;; dfpconv_media SHmedia double precision floating point conversions
262 ;; dmpy_media SHmedia longword multiply
263 ;; fcmp_media SHmedia floating point compare instructions
264 ;; fdiv_media SHmedia single precision divide and square root
265 ;; fload_media SHmedia floating point register load instructions
266 ;; fmove_media SHmedia floating point register moves (inc. fabs and fneg)
267 ;; fparith_media SHmedia single precision floating point arithmetic
268 ;; fpconv_media SHmedia single precision floating point conversions
269 ;; fstore_media SHmedia floating point register store instructions
270 ;; gettr_media SHmedia gettr instruction
271 ;; invalidate_line_media SHmedia invalidate_line sequence
272 ;; jump_media SHmedia unconditional branch instructions
273 ;; load_media SHmedia general register load instructions
274 ;; pt_media SHmedia pt instruction (expanded by assembler)
275 ;; ptabs_media SHmedia ptabs instruction
276 ;; store_media SHmedia general register store instructions
277 ;; mcmp_media SHmedia multimedia compare, absolute, saturating ops
278 ;; mac_media SHmedia mac-style fixed point operations
279 ;; d2mpy_media SHmedia: two 32-bit integer multiplies
280 ;; atrans_media SHmedia approximate transcendental functions
281 ;; ustore_media SHmedia unaligned stores
282 ;; nil no-op move, will be deleted.
283
284 (define_attr "type"
285 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,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"
286 (const_string "other"))
287
288 ;; We define a new attribute namely "insn_class".We use
289 ;; this for the DFA based pipeline description.
290 ;;
291 ;; mt_group SH4 "mt" group instructions.
292 ;;
293 ;; ex_group SH4 "ex" group instructions.
294 ;;
295 ;; ls_group SH4 "ls" group instructions.
296 ;;
297
298 (define_attr "insn_class"
299 "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
300 (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
301 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
302 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
303 (eq_attr "type" "cbranch,jump") (const_string "br_group")
304 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
305 (const_string "fe_group")
306 (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")]
307 (const_string "none")))
308 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
309 ;; so these do not belong in an insn group, although they are modeled
310 ;; with their own define_insn_reservations.
311
312 ;; Indicate what precision must be selected in fpscr for this insn, if any.
313
314 (define_attr "fp_mode" "single,double,none" (const_string "none"))
315
316 ;; Indicate if the fpu mode is set by this instruction
317 ;; "unknown" must have the value as "none" in fp_mode, and means
318 ;; that the instruction/abi has left the processor in an unknown
319 ;; state.
320 ;; "none" means that nothing has changed and no mode is set.
321 ;; This attribute is only used for the Renesas ABI.
322 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
323
324 ; If a conditional branch destination is within -252..258 bytes away
325 ; from the instruction it can be 2 bytes long. Something in the
326 ; range -4090..4100 bytes can be 6 bytes long. All other conditional
327 ; branches are initially assumed to be 16 bytes long.
328 ; In machine_dependent_reorg, we split all branches that are longer than
329 ; 2 bytes.
330
331 ;; The maximum range used for SImode constant pool entries is 1018. A final
332 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
333 ;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch
334 ;; instruction around the pool table, 2 bytes of alignment before the table,
335 ;; and 30 bytes of alignment after the table. That gives a maximum total
336 ;; pool size of 1058 bytes.
337 ;; Worst case code/pool content size ratio is 1:2 (using asms).
338 ;; Thus, in the worst case, there is one instruction in front of a maximum
339 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
340 ;; code. For the last n bytes of code, there are 2n + 36 bytes of pool.
341 ;; If we have a forward branch, the initial table will be put after the
342 ;; unconditional branch.
343 ;;
344 ;; ??? We could do much better by keeping track of the actual pcloads within
345 ;; the branch range and in the pcload range in front of the branch range.
346
347 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
348 ;; inside an le.
349 (define_attr "short_cbranch_p" "no,yes"
350 (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
351 (const_string "no")
352 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
353 (const_string "yes")
354 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
355 (const_string "no")
356 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
357 (const_string "yes")
358 ] (const_string "no")))
359
360 (define_attr "med_branch_p" "no,yes"
361 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
362 (const_int 1988))
363 (const_string "yes")
364 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
365 (const_string "no")
366 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
367 (const_int 8186))
368 (const_string "yes")
369 ] (const_string "no")))
370
371 (define_attr "med_cbranch_p" "no,yes"
372 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
373 (const_int 1986))
374 (const_string "yes")
375 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
376 (const_string "no")
377 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
378 (const_int 8184))
379 (const_string "yes")
380 ] (const_string "no")))
381
382 (define_attr "braf_branch_p" "no,yes"
383 (cond [(match_test "! TARGET_SH2")
384 (const_string "no")
385 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
386 (const_int 20660))
387 (const_string "yes")
388 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
389 (const_string "no")
390 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
391 (const_int 65530))
392 (const_string "yes")
393 ] (const_string "no")))
394
395 (define_attr "braf_cbranch_p" "no,yes"
396 (cond [(match_test "! TARGET_SH2")
397 (const_string "no")
398 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
399 (const_int 20658))
400 (const_string "yes")
401 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
402 (const_string "no")
403 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
404 (const_int 65528))
405 (const_string "yes")
406 ] (const_string "no")))
407
408 ; An unconditional jump in the range -4092..4098 can be 2 bytes long.
409 ; For wider ranges, we need a combination of a code and a data part.
410 ; If we can get a scratch register for a long range jump, the code
411 ; part can be 4 bytes long; otherwise, it must be 8 bytes long.
412 ; If the jump is in the range -32764..32770, the data part can be 2 bytes
413 ; long; otherwise, it must be 6 bytes long.
414
415 ; All other instructions are two bytes long by default.
416
417 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
418 ;; but getattrtab doesn't understand this.
419 (define_attr "length" ""
420 (cond [(eq_attr "type" "cbranch")
421 (cond [(eq_attr "short_cbranch_p" "yes")
422 (const_int 2)
423 (eq_attr "med_cbranch_p" "yes")
424 (const_int 6)
425 (eq_attr "braf_cbranch_p" "yes")
426 (const_int 12)
427 ;; ??? using pc is not computed transitively.
428 (ne (match_dup 0) (match_dup 0))
429 (const_int 14)
430 (match_test "flag_pic")
431 (const_int 24)
432 ] (const_int 16))
433 (eq_attr "type" "jump")
434 (cond [(eq_attr "med_branch_p" "yes")
435 (const_int 2)
436 (and (match_test "prev_nonnote_insn (insn)")
437 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))") (symbol_ref "INSN"))
438 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))") (symbol_ref "code_for_indirect_jump_scratch"))))
439 (cond [(eq_attr "braf_branch_p" "yes")
440 (const_int 6)
441 (not (match_test "flag_pic"))
442 (const_int 10)
443 (match_test "TARGET_SH2")
444 (const_int 10)] (const_int 18))
445 (eq_attr "braf_branch_p" "yes")
446 (const_int 10)
447 ;; ??? using pc is not computed transitively.
448 (ne (match_dup 0) (match_dup 0))
449 (const_int 12)
450 (match_test "flag_pic")
451 (const_int 22)
452 ] (const_int 14))
453 (eq_attr "type" "pt_media")
454 (if_then_else (match_test "TARGET_SHMEDIA64")
455 (const_int 20) (const_int 12))
456 (and (eq_attr "type" "jump_media")
457 (match_test "TARGET_SH5_CUT2_WORKAROUND"))
458 (const_int 8)
459 ] (if_then_else (match_test "TARGET_SHMEDIA")
460 (const_int 4)
461 (const_int 2))))
462
463 ;; DFA descriptions for the pipelines
464
465 (include "sh1.md")
466 (include "shmedia.md")
467 (include "sh4.md")
468
469 (include "iterators.md")
470 (include "predicates.md")
471 (include "constraints.md")
472
473 ;; Definitions for filling delay slots
474
475 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
476
477 (define_attr "banked" "yes,no"
478 (cond [(match_test "sh_loads_bankedreg_p (insn)")
479 (const_string "yes")]
480 (const_string "no")))
481
482 ;; ??? This should be (nil) instead of (const_int 0)
483 (define_attr "hit_stack" "yes,no"
484 (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
485 (const_string "no")]
486 (const_string "yes")))
487
488 (define_attr "interrupt_function" "no,yes"
489 (const (symbol_ref "current_function_interrupt")))
490
491 (define_attr "in_delay_slot" "yes,no"
492 (cond [(eq_attr "type" "cbranch") (const_string "no")
493 (eq_attr "type" "pcload,pcload_si") (const_string "no")
494 (eq_attr "needs_delay_slot" "yes") (const_string "no")
495 (eq_attr "length" "2") (const_string "yes")
496 ] (const_string "no")))
497
498 (define_attr "cond_delay_slot" "yes,no"
499 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
500 ] (const_string "no")))
501
502 (define_attr "is_sfunc" ""
503 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
504
505 (define_attr "is_mac_media" ""
506 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
507
508 (define_attr "branch_zero" "yes,no"
509 (cond [(eq_attr "type" "!cbranch") (const_string "no")
510 (ne (symbol_ref "(next_active_insn (insn)\
511 == (prev_active_insn\
512 (XEXP (SET_SRC (PATTERN (insn)), 1))))\
513 && get_attr_length (next_active_insn (insn)) == 2")
514 (const_int 0))
515 (const_string "yes")]
516 (const_string "no")))
517
518 ;; SH4 Double-precision computation with double-precision result -
519 ;; the two halves are ready at different times.
520 (define_attr "dfp_comp" "yes,no"
521 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
522 (const_string "no")))
523
524 ;; Insns for which the latency of a preceding fp insn is decreased by one.
525 (define_attr "late_fp_use" "yes,no" (const_string "no"))
526 ;; And feeding insns for which this relevant.
527 (define_attr "any_fp_comp" "yes,no"
528 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
529 (const_string "yes")]
530 (const_string "no")))
531
532 (define_attr "any_int_load" "yes,no"
533 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
534 (const_string "yes")]
535 (const_string "no")))
536
537 (define_attr "highpart" "user, ignore, extend, depend, must_split"
538 (const_string "user"))
539
540 (define_delay
541 (eq_attr "needs_delay_slot" "yes")
542 [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
543
544 ;; Since a normal return (rts) implicitly uses the PR register,
545 ;; we can't allow PR register loads in an rts delay slot.
546 ;; On the SH1* and SH2*, the rte instruction reads the return pc from the
547 ;; stack, and thus we can't put a pop instruction in its delay slot.
548 ;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
549 ;; pop instruction can go in the delay slot, unless it references a banked
550 ;; register (the register bank is switched by rte).
551 (define_delay
552 (eq_attr "type" "return")
553 [(and (eq_attr "in_delay_slot" "yes")
554 (ior (and (eq_attr "interrupt_function" "no")
555 (eq_attr "type" "!pload,prset"))
556 (and (eq_attr "interrupt_function" "yes")
557 (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
558 (eq_attr "banked" "no"))))
559 (nil) (nil)])
560
561 ;; Since a call implicitly uses the PR register, we can't allow
562 ;; a PR register store in a jsr delay slot.
563
564 (define_delay
565 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
566 [(and (eq_attr "in_delay_slot" "yes")
567 (eq_attr "type" "!pstore,prget")) (nil) (nil)])
568
569 ;; Say that we have annulled true branches, since this gives smaller and
570 ;; faster code when branches are predicted as not taken.
571
572 ;; ??? The non-annulled condition should really be "in_delay_slot",
573 ;; but insns that can be filled in non-annulled get priority over insns
574 ;; that can only be filled in anulled.
575
576 (define_delay
577 (and (eq_attr "type" "cbranch")
578 (match_test "TARGET_SH2"))
579 ;; SH2e has a hardware bug that pretty much prohibits the use of
580 ;; annulled delay slots.
581 [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
582 (not (eq_attr "cpu" "sh2e"))) (nil)])
583 \f
584 ;; -------------------------------------------------------------------------
585 ;; SImode signed integer comparisons
586 ;; -------------------------------------------------------------------------
587
588 ;; Various patterns to generate the TST #imm, R0 instruction.
589 ;; Although this adds some pressure on the R0 register, it can potentially
590 ;; result in faster code, even if the operand has to be moved to R0 first.
591 ;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group
592 ;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0
593 ;; is an EX group instruction but still can be executed in parallel with the
594 ;; MT group MOV Rm, Rn instruction.
595
596 ;; Usual TST #imm, R0 patterns for SI, HI and QI
597 ;; This is usually used for bit patterns other than contiguous bits
598 ;; and single bits.
599
600 (define_insn "tstsi_t"
601 [(set (reg:SI T_REG)
602 (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
603 (match_operand:SI 1 "logical_operand" "K08,r"))
604 (const_int 0)))]
605 "TARGET_SH1"
606 "tst %1,%0"
607 [(set_attr "type" "mt_group")])
608
609 (define_insn "tsthi_t"
610 [(set (reg:SI T_REG)
611 (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
612 (match_operand 1 "const_int_operand")) 0)
613 (const_int 0)))]
614 "TARGET_SH1
615 && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
616 "tst %1,%0"
617 [(set_attr "type" "mt_group")])
618
619 (define_insn "tstqi_t"
620 [(set (reg:SI T_REG)
621 (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
622 (match_operand 1 "const_int_operand")) 0)
623 (const_int 0)))]
624 "TARGET_SH1
625 && (CONST_OK_FOR_K08 (INTVAL (operands[1]))
626 || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
627 {
628 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
629 return "tst %1,%0";
630 }
631 [(set_attr "type" "mt_group")])
632
633 ;; Test low QI subreg against zero.
634 ;; This avoids unnecessary zero extension before the test.
635
636 (define_insn "tstqi_t_zero"
637 [(set (reg:SI T_REG)
638 (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
639 "TARGET_SH1"
640 "tst #255,%0"
641 [(set_attr "type" "mt_group")])
642
643 ;; Extract LSB, negate and store in T bit.
644
645 (define_insn "tstsi_t_and_not"
646 [(set (reg:SI T_REG)
647 (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
648 (const_int 1)))]
649 "TARGET_SH1"
650 "tst #1,%0"
651 [(set_attr "type" "mt_group")])
652
653 ;; Extract contiguous bits and compare them against zero.
654
655 (define_insn "tstsi_t_zero_extract_eq"
656 [(set (reg:SI T_REG)
657 (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z")
658 (match_operand:SI 1 "const_int_operand")
659 (match_operand:SI 2 "const_int_operand"))
660 (const_int 0)))]
661 "TARGET_SH1
662 && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
663 {
664 operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
665 return "tst %1,%0";
666 }
667 [(set_attr "type" "mt_group")])
668
669 ;; This split is required when testing bits in a QI subreg.
670
671 (define_split
672 [(set (reg:SI T_REG)
673 (eq:SI (if_then_else:SI (zero_extract:SI
674 (match_operand 0 "logical_operand" "")
675 (match_operand 1 "const_int_operand")
676 (match_operand 2 "const_int_operand"))
677 (match_operand 3 "const_int_operand")
678 (const_int 0))
679 (const_int 0)))]
680 "TARGET_SH1
681 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
682 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
683 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
684 (const_int 0)))]
685 {
686 if (GET_MODE (operands[0]) == QImode)
687 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
688 })
689
690 ;; Extract single bit, negate and store it in the T bit.
691 ;; Not used for SH4A.
692
693 (define_insn "tstsi_t_zero_extract_xor"
694 [(set (reg:SI T_REG)
695 (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
696 (match_operand:SI 3 "const_int_operand"))
697 (match_operand:SI 1 "const_int_operand")
698 (match_operand:SI 2 "const_int_operand")))]
699 "TARGET_SH1
700 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
701 && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
702 "tst %3,%0"
703 [(set_attr "type" "mt_group")])
704
705 ;; Extract single bit, negate and store it in the T bit.
706 ;; Used for SH4A little endian.
707
708 (define_insn "tstsi_t_zero_extract_subreg_xor_little"
709 [(set (reg:SI T_REG)
710 (zero_extract:SI
711 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
712 (match_operand:SI 3 "const_int_operand")) 0)
713 (match_operand:SI 1 "const_int_operand")
714 (match_operand:SI 2 "const_int_operand")))]
715 "TARGET_SH1 && TARGET_LITTLE_ENDIAN
716 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
717 == (INTVAL (operands[3]) & 255)
718 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
719 {
720 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
721 return "tst %3,%0";
722 }
723 [(set_attr "type" "mt_group")])
724
725 ;; Extract single bit, negate and store it in the T bit.
726 ;; Used for SH4A big endian.
727
728 (define_insn "tstsi_t_zero_extract_subreg_xor_big"
729 [(set (reg:SI T_REG)
730 (zero_extract:SI
731 (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
732 (match_operand:SI 3 "const_int_operand")) 3)
733 (match_operand:SI 1 "const_int_operand")
734 (match_operand:SI 2 "const_int_operand")))]
735 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
736 && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
737 == (INTVAL (operands[3]) & 255)
738 && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
739 {
740 operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
741 return "tst %3,%0";
742 }
743 [(set_attr "type" "mt_group")])
744
745 (define_insn "cmpeqsi_t"
746 [(set (reg:SI T_REG)
747 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
748 (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
749 "TARGET_SH1"
750 "@
751 tst %0,%0
752 cmp/eq %1,%0
753 cmp/eq %1,%0"
754 [(set_attr "type" "mt_group")])
755
756 ;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
757 ;; pattern by itself. What this actually does is:
758 ;; x == 0: (1 >> 0-0) & 1 = 1
759 ;; x != 0: (1 >> 0-x) & 1 = 0
760 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
761 (define_insn_and_split "*cmpeqsi_t"
762 [(set (reg:SI T_REG)
763 (and:SI (lshiftrt:SI
764 (const_int 1)
765 (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
766 (const_int 1)))]
767 "TARGET_SH1"
768 "#"
769 "&& 1"
770 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
771
772 (define_insn "cmpgtsi_t"
773 [(set (reg:SI T_REG)
774 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
775 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
776 "TARGET_SH1"
777 "@
778 cmp/pl %0
779 cmp/gt %1,%0"
780 [(set_attr "type" "mt_group")])
781
782 (define_insn "cmpgesi_t"
783 [(set (reg:SI T_REG)
784 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
785 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
786 "TARGET_SH1"
787 "@
788 cmp/pz %0
789 cmp/ge %1,%0"
790 [(set_attr "type" "mt_group")])
791
792 ;; FIXME: This is actually wrong. There is no way to literally move a
793 ;; general reg to t reg. Luckily, it seems that this pattern will be only
794 ;; used when the general reg is known be either '0' or '1' during combine.
795 ;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
796 ;; Due to interactions with other patterns, combine fails to pick the latter
797 ;; and invert the dependent logic.
798 (define_insn "*negtstsi"
799 [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
800 "TARGET_SH1"
801 "cmp/pl %0"
802 [(set_attr "type" "mt_group")])
803
804 ;; Some integer sign comparison patterns can be realized with the div0s insn.
805 ;; div0s Rm,Rn T = (Rm >> 31) ^ (Rn >> 31)
806 (define_insn "cmp_div0s_0"
807 [(set (reg:SI T_REG)
808 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
809 (match_operand:SI 1 "arith_reg_operand" "r"))
810 (const_int 31)))]
811 "TARGET_SH1"
812 "div0s %0,%1"
813 [(set_attr "type" "arith")])
814
815 (define_insn "cmp_div0s_1"
816 [(set (reg:SI T_REG)
817 (lt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
818 (match_operand:SI 1 "arith_reg_operand" "r"))
819 (const_int 0)))]
820 "TARGET_SH1"
821 "div0s %0,%1"
822 [(set_attr "type" "arith")])
823
824 (define_insn_and_split "*cmp_div0s_0"
825 [(set (match_operand:SI 0 "arith_reg_dest" "")
826 (lshiftrt:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
827 (match_operand:SI 2 "arith_reg_operand" ""))
828 (const_int 31)))
829 (clobber (reg:SI T_REG))]
830 "TARGET_SH1"
831 "#"
832 "&& 1"
833 [(set (reg:SI T_REG)
834 (lshiftrt:SI (xor:SI (match_dup 1) (match_dup 2)) (const_int 31)))
835 (set (match_dup 0) (reg:SI T_REG))])
836
837 (define_insn_and_split "*cmp_div0s_1"
838 [(set (match_operand:SI 0 "arith_reg_dest" "")
839 (ge:SI (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
840 (match_operand:SI 2 "arith_reg_operand" ""))
841 (const_int 0)))
842 (clobber (reg:SI T_REG))]
843 "TARGET_SH1"
844 "#"
845 "&& can_create_pseudo_p ()"
846 [(const_int 0)]
847 ;; We have to go through the movnegt expander here which will handle the
848 ;; SH2A vs non-SH2A cases.
849 {
850 emit_insn (gen_cmp_div0s_1 (operands[1], operands[2]));
851 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
852 DONE;
853 })
854
855 (define_insn_and_split "*cmp_div0s_1"
856 [(set (reg:SI T_REG)
857 (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
858 (match_operand:SI 1 "arith_reg_operand" ""))
859 (const_int 0)))]
860 "TARGET_SH1"
861 "#"
862 "&& can_create_pseudo_p ()"
863 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 0) (match_dup 1))
864 (const_int 0)))
865 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
866
867
868 ;; -------------------------------------------------------------------------
869 ;; SImode compare and branch
870 ;; -------------------------------------------------------------------------
871
872 (define_expand "cbranchsi4"
873 [(set (pc)
874 (if_then_else (match_operator 0 "comparison_operator"
875 [(match_operand:SI 1 "arith_operand" "")
876 (match_operand:SI 2 "arith_operand" "")])
877 (label_ref (match_operand 3 "" ""))
878 (pc)))
879 (clobber (reg:SI T_REG))]
880 ""
881 {
882 if (TARGET_SHMEDIA)
883 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
884 operands[2], operands[3]));
885 else
886 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
887
888 DONE;
889 })
890
891 ;; Combine patterns to invert compare and branch operations for which we
892 ;; don't have actual comparison insns. These patterns are used in cases
893 ;; which appear after the initial cbranchsi expansion, which also does
894 ;; some condition inversion.
895
896 (define_split
897 [(set (pc)
898 (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
899 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
900 (label_ref (match_operand 2))
901 (pc)))
902 (clobber (reg:SI T_REG))]
903 "TARGET_SH1"
904 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
905 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
906 (label_ref (match_dup 2))
907 (pc)))])
908
909 ;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
910 ;; and SH2A combine fails to simplify this pattern by itself.
911 ;; What this actually does is:
912 ;; x == 0: (1 >> 0-0) & 1 = 1
913 ;; x != 0: (1 >> 0-x) & 1 = 0
914 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
915 (define_split
916 [(set (pc)
917 (if_then_else
918 (eq (and:SI (lshiftrt:SI
919 (const_int 1)
920 (neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
921 (const_int 1))
922 (const_int 0))
923 (label_ref (match_operand 2))
924 (pc)))
925 (clobber (reg:SI T_REG))]
926 "TARGET_SH1"
927 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
928 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
929 (label_ref (match_dup 2))
930 (pc)))])
931
932 ;; FIXME: These could probably use code iterators for the compare op.
933 (define_split
934 [(set (pc)
935 (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
936 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
937 (label_ref (match_operand 2))
938 (pc)))
939 (clobber (reg:SI T_REG))]
940 "TARGET_SH1"
941 [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
942 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
943 (label_ref (match_dup 2))
944 (pc)))])
945
946 (define_split
947 [(set (pc)
948 (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
949 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
950 (label_ref (match_operand 2))
951 (pc)))
952 (clobber (reg:SI T_REG))]
953 "TARGET_SH1"
954 [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
955 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
956 (label_ref (match_dup 2))
957 (pc)))])
958
959 (define_split
960 [(set (pc)
961 (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
962 (match_operand:SI 1 "arith_reg_operand" ""))
963 (label_ref (match_operand 2))
964 (pc)))
965 (clobber (reg:SI T_REG))]
966 "TARGET_SH1"
967 [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
968 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
969 (label_ref (match_dup 2))
970 (pc)))])
971
972 (define_split
973 [(set (pc)
974 (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
975 (match_operand:SI 1 "arith_reg_operand" ""))
976 (label_ref (match_operand 2))
977 (pc)))
978 (clobber (reg:SI T_REG))]
979 "TARGET_SH1"
980 [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
981 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
982 (label_ref (match_dup 2))
983 (pc)))])
984
985 ;; Compare and branch combine patterns for div0s comparisons.
986 (define_insn_and_split "*cbranch_div0s"
987 [(set (pc)
988 (if_then_else (lt (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
989 (match_operand:SI 1 "arith_reg_operand" ""))
990 (const_int 0))
991 (label_ref (match_operand 2))
992 (pc)))
993 (clobber (reg:SI T_REG))]
994 "TARGET_SH1"
995 "#"
996 "&& 1"
997 [(set (reg:SI T_REG)
998 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
999 (set (pc)
1000 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1001 (label_ref (match_dup 2))
1002 (pc)))])
1003
1004 (define_insn_and_split "*cbranch_div0s"
1005 [(set (pc)
1006 (if_then_else (ge (xor:SI (match_operand:SI 0 "arith_reg_operand" "")
1007 (match_operand:SI 1 "arith_reg_operand" ""))
1008 (const_int 0))
1009 (label_ref (match_operand 2))
1010 (pc)))
1011 (clobber (reg:SI T_REG))]
1012 "TARGET_SH1"
1013 "#"
1014 "&& 1"
1015 [(set (reg:SI T_REG)
1016 (lt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 0)))
1017 (set (pc)
1018 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1019 (label_ref (match_dup 2))
1020 (pc)))])
1021
1022 ;; Conditional move combine pattern for div0s comparisons.
1023 ;; This is used when TARGET_PRETEND_CMOVE is in effect.
1024 (define_insn_and_split "*movsicc_div0s"
1025 [(set (match_operand:SI 0 "arith_reg_dest" "")
1026 (if_then_else:SI (ge (xor:SI (match_operand:SI 1 "arith_reg_operand" "")
1027 (match_operand:SI 2 "arith_reg_operand" ""))
1028 (const_int 0))
1029 (match_operand:SI 3 "arith_reg_operand" "")
1030 (match_operand:SI 4 "general_movsrc_operand" "")))
1031 (clobber (reg:SI T_REG))]
1032 "TARGET_PRETEND_CMOVE"
1033 "#"
1034 "&& 1"
1035 [(set (reg:SI T_REG) (lt:SI (xor:SI (match_dup 1) (match_dup 2))
1036 (const_int 0)))
1037 (set (match_dup 0)
1038 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1039 (match_dup 4)
1040 (match_dup 3)))])
1041
1042 ;; -------------------------------------------------------------------------
1043 ;; SImode unsigned integer comparisons
1044 ;; -------------------------------------------------------------------------
1045
1046 ;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1047 ;; However, especially when optimizations are off (e.g. -O0) such comparisons
1048 ;; might remain and we have to handle them. If the '>= 0' case wasn't
1049 ;; handled here, something else would just load a '0' into the second operand
1050 ;; and do the comparison. We can do slightly better by just setting the
1051 ;; T bit to '1'.
1052 (define_insn_and_split "cmpgeusi_t"
1053 [(set (reg:SI T_REG)
1054 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1055 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1056 "TARGET_SH1"
1057 "cmp/hs %1,%0"
1058 "&& satisfies_constraint_Z (operands[1])"
1059 [(set (reg:SI T_REG) (const_int 1))]
1060 ""
1061 [(set_attr "type" "mt_group")])
1062
1063 (define_insn "cmpgtusi_t"
1064 [(set (reg:SI T_REG)
1065 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1066 (match_operand:SI 1 "arith_reg_operand" "r")))]
1067 "TARGET_SH1"
1068 "cmp/hi %1,%0"
1069 [(set_attr "type" "mt_group")])
1070
1071 \f
1072 ;; -------------------------------------------------------------------------
1073 ;; DImode compare and branch
1074 ;; -------------------------------------------------------------------------
1075
1076
1077 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1078 ;; Therefore, we aim to have a set of three branches that go straight to the
1079 ;; destination, i.e. only one of them is taken at any one time.
1080 ;; This mechanism should also be slightly better for the sh4-200.
1081
1082 (define_expand "cbranchdi4"
1083 [(set (pc)
1084 (if_then_else (match_operator 0 "comparison_operator"
1085 [(match_operand:DI 1 "arith_operand" "")
1086 (match_operand:DI 2 "arith_operand" "")])
1087 (label_ref (match_operand 3 "" ""))
1088 (pc)))
1089 (clobber (match_dup 4))
1090 (clobber (reg:SI T_REG))]
1091 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1092 {
1093 enum rtx_code comparison;
1094
1095 if (TARGET_SHMEDIA)
1096 {
1097 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1098 operands[2], operands[3]));
1099 DONE;
1100 }
1101
1102 else if (!TARGET_CBRANCHDI4)
1103 {
1104 sh_emit_compare_and_branch (operands, DImode);
1105 DONE;
1106 }
1107
1108 else
1109 {
1110 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1111 DONE;
1112
1113 comparison = prepare_cbranch_operands (operands, DImode,
1114 LAST_AND_UNUSED_RTX_CODE);
1115 if (comparison != GET_CODE (operands[0]))
1116 operands[0]
1117 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1118 operands[4] = gen_rtx_SCRATCH (SImode);
1119 }
1120 })
1121
1122 (define_insn_and_split "cbranchdi4_i"
1123 [(set (pc)
1124 (if_then_else (match_operator 0 "comparison_operator"
1125 [(match_operand:DI 1 "arith_operand" "r,r")
1126 (match_operand:DI 2 "arith_operand" "rN,I08")])
1127 (label_ref (match_operand 3 "" ""))
1128 (pc)))
1129 (clobber (match_scratch:SI 4 "=X,&r"))
1130 (clobber (reg:SI T_REG))]
1131 "TARGET_CBRANCHDI4"
1132 "#"
1133 "&& reload_completed"
1134 [(pc)]
1135 {
1136 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1137 FAIL;
1138 DONE;
1139 })
1140
1141 ;; -------------------------------------------------------------------------
1142 ;; DImode signed integer comparisons
1143 ;; -------------------------------------------------------------------------
1144
1145 (define_insn ""
1146 [(set (reg:SI T_REG)
1147 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1148 (match_operand:DI 1 "arith_operand" "r"))
1149 (const_int 0)))]
1150 "TARGET_SH1"
1151 {
1152 return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1153 insn, operands);
1154 }
1155 [(set_attr "length" "6")
1156 (set_attr "type" "arith3b")])
1157
1158 (define_insn "cmpeqdi_t"
1159 [(set (reg:SI T_REG)
1160 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1161 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1162 "TARGET_SH1"
1163 {
1164 static const char* alt[] =
1165 {
1166 "tst %S0,%S0" "\n"
1167 " bf 0f" "\n"
1168 " tst %R0,%R0" "\n"
1169 "0:",
1170
1171 "cmp/eq %S1,%S0" "\n"
1172 " bf 0f" "\n"
1173 " cmp/eq %R1,%R0" "\n"
1174 "0:"
1175 };
1176 return alt[which_alternative];
1177 }
1178 [(set_attr "length" "6")
1179 (set_attr "type" "arith3b")])
1180
1181 (define_split
1182 [(set (reg:SI T_REG)
1183 (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1184 (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1185 ;; If we applied this split when not optimizing, it would only be
1186 ;; applied during the machine-dependent reorg, when no new basic blocks
1187 ;; may be created.
1188 "TARGET_SH1 && reload_completed && optimize"
1189 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1190 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1191 (label_ref (match_dup 6))
1192 (pc)))
1193 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1194 (match_dup 6)]
1195 {
1196 operands[2] = gen_highpart (SImode, operands[0]);
1197 operands[3] = operands[1] == const0_rtx
1198 ? const0_rtx
1199 : gen_highpart (SImode, operands[1]);
1200 operands[4] = gen_lowpart (SImode, operands[0]);
1201 operands[5] = gen_lowpart (SImode, operands[1]);
1202 operands[6] = gen_label_rtx ();
1203 })
1204
1205 (define_insn "cmpgtdi_t"
1206 [(set (reg:SI T_REG)
1207 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1208 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1209 "TARGET_SH2"
1210 {
1211 static const char* alt[] =
1212 {
1213 "cmp/eq %S1,%S0" "\n"
1214 " bf{.|/}s 0f" "\n"
1215 " cmp/gt %S1,%S0" "\n"
1216 " cmp/hi %R1,%R0" "\n"
1217 "0:",
1218
1219 "tst %S0,%S0" "\n"
1220 " bf{.|/}s 0f" "\n"
1221 " cmp/pl %S0" "\n"
1222 " cmp/hi %S0,%R0" "\n"
1223 "0:"
1224 };
1225 return alt[which_alternative];
1226 }
1227 [(set_attr "length" "8")
1228 (set_attr "type" "arith3")])
1229
1230 (define_insn "cmpgedi_t"
1231 [(set (reg:SI T_REG)
1232 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1233 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1234 "TARGET_SH2"
1235 {
1236 static const char* alt[] =
1237 {
1238 "cmp/eq %S1,%S0" "\n"
1239 " bf{.|/}s 0f" "\n"
1240 " cmp/ge %S1,%S0" "\n"
1241 " cmp/hs %R1,%R0" "\n"
1242 "0:",
1243
1244 "cmp/pz %S0"
1245 };
1246 return alt[which_alternative];
1247 }
1248 [(set_attr "length" "8,2")
1249 (set_attr "type" "arith3,mt_group")])
1250 \f
1251 ;; -------------------------------------------------------------------------
1252 ;; DImode unsigned integer comparisons
1253 ;; -------------------------------------------------------------------------
1254
1255 (define_insn "cmpgeudi_t"
1256 [(set (reg:SI T_REG)
1257 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1258 (match_operand:DI 1 "arith_reg_operand" "r")))]
1259 "TARGET_SH2"
1260 {
1261 return "cmp/eq %S1,%S0" "\n"
1262 " bf{.|/}s 0f" "\n"
1263 " cmp/hs %S1,%S0" "\n"
1264 " cmp/hs %R1,%R0" "\n"
1265 "0:";
1266 }
1267 [(set_attr "length" "8")
1268 (set_attr "type" "arith3")])
1269
1270 (define_insn "cmpgtudi_t"
1271 [(set (reg:SI T_REG)
1272 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1273 (match_operand:DI 1 "arith_reg_operand" "r")))]
1274 "TARGET_SH2"
1275 {
1276 return "cmp/eq %S1,%S0" "\n"
1277 " bf{.|/}s 0f" "\n"
1278 " cmp/hi %S1,%S0" "\n"
1279 " cmp/hi %R1,%R0" "\n"
1280 "0:";
1281 }
1282 [(set_attr "length" "8")
1283 (set_attr "type" "arith3")])
1284
1285 (define_insn "cmpeqsi_media"
1286 [(set (match_operand:SI 0 "register_operand" "=r")
1287 (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1288 (match_operand:SI 2 "cmp_operand" "Nr")))]
1289 "TARGET_SHMEDIA"
1290 "cmpeq %1, %N2, %0"
1291 [(set_attr "type" "cmp_media")])
1292
1293 (define_insn "cmpeqdi_media"
1294 [(set (match_operand:SI 0 "register_operand" "=r")
1295 (eq:SI (match_operand:DI 1 "register_operand" "%r")
1296 (match_operand:DI 2 "cmp_operand" "Nr")))]
1297 "TARGET_SHMEDIA"
1298 "cmpeq %1, %N2, %0"
1299 [(set_attr "type" "cmp_media")])
1300
1301 (define_insn "cmpgtsi_media"
1302 [(set (match_operand:SI 0 "register_operand" "=r")
1303 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1304 (match_operand:SI 2 "cmp_operand" "rN")))]
1305 "TARGET_SHMEDIA"
1306 "cmpgt %N1, %N2, %0"
1307 [(set_attr "type" "cmp_media")])
1308
1309 (define_insn "cmpgtdi_media"
1310 [(set (match_operand:SI 0 "register_operand" "=r")
1311 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1312 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1313 "TARGET_SHMEDIA"
1314 "cmpgt %N1, %N2, %0"
1315 [(set_attr "type" "cmp_media")])
1316
1317 (define_insn "cmpgtusi_media"
1318 [(set (match_operand:SI 0 "register_operand" "=r")
1319 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1320 (match_operand:SI 2 "cmp_operand" "rN")))]
1321 "TARGET_SHMEDIA"
1322 "cmpgtu %N1, %N2, %0"
1323 [(set_attr "type" "cmp_media")])
1324
1325 (define_insn "cmpgtudi_media"
1326 [(set (match_operand:SI 0 "register_operand" "=r")
1327 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1328 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1329 "TARGET_SHMEDIA"
1330 "cmpgtu %N1, %N2, %0"
1331 [(set_attr "type" "cmp_media")])
1332
1333 ; This pattern is for combine.
1334 (define_insn "*cmpne0sisi_media"
1335 [(set (match_operand:SI 0 "register_operand" "=r")
1336 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1337 "TARGET_SHMEDIA"
1338 "cmpgtu %1,r63,%0"
1339 [(set_attr "type" "cmp_media")])
1340
1341 ;; -------------------------------------------------------------------------
1342 ;; Conditional move instructions
1343 ;; -------------------------------------------------------------------------
1344
1345 ;; The insn names may seem reversed, but note that cmveq performs the move
1346 ;; if op1 == 0, and cmvne does it if op1 != 0.
1347
1348 (define_insn "movdicc_false"
1349 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1350 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1351 (const_int 0))
1352 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1353 (match_operand:DI 3 "arith_reg_operand" "0")))]
1354 "TARGET_SHMEDIA"
1355 "cmveq %1, %N2, %0"
1356 [(set_attr "type" "arith_media")])
1357
1358 (define_insn "movdicc_true"
1359 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1360 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1361 (const_int 0))
1362 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1363 (match_operand:DI 3 "arith_reg_operand" "0")))]
1364 "TARGET_SHMEDIA"
1365 "cmvne %1, %N2, %0"
1366 [(set_attr "type" "arith_media")])
1367
1368 (define_peephole2
1369 [(set (match_operand:DI 0 "arith_reg_dest" "")
1370 (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1371 [(match_operand:DI 1 "arith_reg_operand" "")
1372 (const_int 0)])
1373 (match_operand:DI 2 "arith_reg_dest" "")
1374 (match_dup 0)))
1375 (set (match_dup 2) (match_dup 0))]
1376 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1377 [(set (match_dup 2)
1378 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1379 {
1380 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1381 VOIDmode, operands[1], CONST0_RTX (DImode));
1382 })
1383
1384 (define_peephole2
1385 [(set (match_operand:DI 0 "general_movdst_operand" "")
1386 (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1387 (set (match_operand:DI 2 "arith_reg_dest" "")
1388 (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1389 [(match_operand:DI 3 "arith_reg_operand" "")
1390 (const_int 0)])
1391 (match_dup 0)
1392 (match_dup 2)))]
1393 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1394 [(set (match_dup 2)
1395 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1396 "")
1397
1398 (define_expand "movdicc"
1399 [(set (match_operand:DI 0 "register_operand" "")
1400 (if_then_else:DI (match_operand 1 "comparison_operator" "")
1401 (match_operand:DI 2 "register_operand" "")
1402 (match_operand:DI 3 "register_operand" "")))]
1403 "TARGET_SHMEDIA"
1404 {
1405 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1406 && GET_MODE (XEXP (operands[1], 0)) == DImode
1407 && XEXP (operands[1], 1) == const0_rtx)
1408 ;
1409 else
1410 {
1411 if (!can_create_pseudo_p ())
1412 FAIL;
1413
1414 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1415 GET_CODE (operands[1]),
1416 XEXP (operands[1], 0),
1417 XEXP (operands[1], 1));
1418 if (!operands[1])
1419 FAIL;
1420 }
1421 })
1422
1423 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1424 ;; SImode to DImode.
1425 (define_insn "movsicc_false"
1426 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1427 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1428 (const_int 0))
1429 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1430 (match_operand:SI 3 "arith_reg_operand" "0")))]
1431 "TARGET_SHMEDIA"
1432 "cmveq %1, %N2, %0"
1433 [(set_attr "type" "arith_media")])
1434
1435 (define_insn "movsicc_true"
1436 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1437 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1438 (const_int 0))
1439 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1440 (match_operand:SI 3 "arith_reg_operand" "0")))]
1441 "TARGET_SHMEDIA"
1442 "cmvne %1, %N2, %0"
1443 [(set_attr "type" "arith_media")])
1444
1445 (define_peephole2
1446 [(set (match_operand:SI 0 "arith_reg_dest" "")
1447 (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1448 [(match_operand:SI 1 "arith_reg_operand" "")
1449 (const_int 0)])
1450 (match_operand:SI 2 "arith_reg_dest" "")
1451 (match_dup 0)))
1452 (set (match_dup 2) (match_dup 0))]
1453 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1454 [(set (match_dup 2)
1455 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1456 {
1457 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1458 VOIDmode, operands[1], CONST0_RTX (SImode));
1459 })
1460
1461 (define_peephole2
1462 [(set (match_operand:SI 0 "general_movdst_operand" "")
1463 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1464 (set (match_operand:SI 2 "arith_reg_dest" "")
1465 (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1466 [(match_operand:SI 3 "arith_reg_operand" "")
1467 (const_int 0)])
1468 (match_dup 0)
1469 (match_dup 2)))]
1470 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1471 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1472 [(set (match_dup 2)
1473 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1474 {
1475 replace_rtx (operands[4], operands[0], operands[1]);
1476 })
1477
1478 (define_peephole2
1479 [(set (match_operand 0 "any_register_operand" "")
1480 (match_operand 1 "any_register_operand" ""))
1481 (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" ""))
1482 (set (match_operand 4 "" "") (match_operand 5 "" ""))]
1483 "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2]))
1484 <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0])))
1485 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])
1486 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[0])
1487 && ! FIND_REG_INC_NOTE (peep2_next_insn (2), operands[2])
1488 && ! reg_overlap_mentioned_p (operands[0], operands[3])
1489 && ! reg_overlap_mentioned_p (operands[2], operands[0])
1490 && ! reg_overlap_mentioned_p (operands[0], operands[1])
1491 && (REGNO_REG_CLASS (REGNO (operands[0]))
1492 == REGNO_REG_CLASS (REGNO (operands[2])))
1493 && (REGNO_REG_CLASS (REGNO (operands[1]))
1494 == REGNO_REG_CLASS (REGNO (operands[0])))"
1495 [(set (match_dup 0) (match_dup 3))
1496 (set (match_dup 4) (match_dup 5))]
1497 {
1498 rtx set1, set2, insn2;
1499 rtx replacements[4];
1500
1501 /* We want to replace occurrences of operands[0] with operands[1] and
1502 operands[2] with operands[0] in operands[4]/operands[5].
1503 Doing just two replace_rtx calls naively would result in the second
1504 replacement undoing all that the first did if operands[1] and operands[2]
1505 are identical, so we must do this simultaneously. */
1506 replacements[0] = operands[0];
1507 replacements[1] = operands[1];
1508 replacements[2] = operands[2];
1509 replacements[3] = operands[0];
1510 if (!replace_n_hard_rtx (operands[5], replacements, 2, 0)
1511 || !replace_n_hard_rtx (operands[4], replacements, 2, 0)
1512 || !replace_n_hard_rtx (operands[2], replacements, 2, 0))
1513 FAIL;
1514
1515 operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1);
1516 replace_n_hard_rtx (operands[4], replacements, 2, 1);
1517 operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1);
1518 /* The operands array is aliased to recog_data.operand, which gets
1519 clobbered by extract_insn, so finish with it now. */
1520 set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]);
1521 set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]);
1522 /* ??? The last insn might be a jump insn, but the generic peephole2 code
1523 always uses emit_insn. */
1524 /* Check that we don't violate matching constraints or earlyclobbers. */
1525 extract_insn (emit_insn (set1));
1526 if (! constrain_operands (1))
1527 goto failure;
1528 insn2 = emit (set2);
1529 if (GET_CODE (insn2) == BARRIER)
1530 goto failure;
1531 extract_insn (insn2);
1532 if (! constrain_operands (1))
1533 {
1534 rtx tmp;
1535 failure:
1536 tmp = replacements[0];
1537 replacements[0] = replacements[1];
1538 replacements[1] = tmp;
1539 tmp = replacements[2];
1540 replacements[2] = replacements[3];
1541 replacements[3] = tmp;
1542 replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1);
1543 replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1);
1544 replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1);
1545 FAIL;
1546 }
1547 DONE;
1548 })
1549
1550 ;; The register allocator is rather clumsy in handling multi-way conditional
1551 ;; moves, so allow the combiner to make them, and we split them up after
1552 ;; reload. */
1553 (define_insn_and_split "*movsicc_umin"
1554 [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1555 (umin:SI (if_then_else:SI
1556 (eq (match_operand:SI 1 "arith_reg_operand" "r")
1557 (const_int 0))
1558 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1559 (match_operand:SI 3 "register_operand" "0"))
1560 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1561 (clobber (match_scratch:SI 5 "=&r"))]
1562 "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1563 "#"
1564 "TARGET_SHMEDIA && reload_completed"
1565 [(pc)]
1566 {
1567 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1568 operands[3]));
1569 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1570 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1571 operands[0]));
1572 DONE;
1573 })
1574
1575 (define_insn "*movsicc_t_false"
1576 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1577 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1578 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1579 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1580 "TARGET_PRETEND_CMOVE
1581 && (arith_reg_operand (operands[1], SImode)
1582 || (immediate_operand (operands[1], SImode)
1583 && satisfies_constraint_I08 (operands[1])))"
1584 {
1585 return "bt 0f" "\n"
1586 " mov %1,%0" "\n"
1587 "0:";
1588 }
1589 [(set_attr "type" "mt_group,arith") ;; poor approximation
1590 (set_attr "length" "4")])
1591
1592 (define_insn "*movsicc_t_true"
1593 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1594 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1595 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1596 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1597 "TARGET_PRETEND_CMOVE
1598 && (arith_reg_operand (operands[1], SImode)
1599 || (immediate_operand (operands[1], SImode)
1600 && satisfies_constraint_I08 (operands[1])))"
1601 {
1602 return "bf 0f" "\n"
1603 " mov %1,%0" "\n"
1604 "0:";
1605 }
1606 [(set_attr "type" "mt_group,arith") ;; poor approximation
1607 (set_attr "length" "4")])
1608
1609 (define_expand "movsicc"
1610 [(set (match_operand:SI 0 "arith_reg_dest" "")
1611 (if_then_else:SI (match_operand 1 "comparison_operator" "")
1612 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1613 (match_operand:SI 3 "arith_reg_operand" "")))]
1614 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1615 {
1616 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1617 && GET_MODE (XEXP (operands[1], 0)) == SImode
1618 && (TARGET_SHMEDIA
1619 || (REG_P (XEXP (operands[1], 0))
1620 && REGNO (XEXP (operands[1], 0)) == T_REG))
1621 && XEXP (operands[1], 1) == const0_rtx)
1622 ;
1623
1624 else if (TARGET_PRETEND_CMOVE)
1625 {
1626 enum rtx_code code = GET_CODE (operands[1]);
1627 enum rtx_code new_code = code;
1628 rtx op0 = XEXP (operands[1], 0);
1629 rtx op1 = XEXP (operands[1], 1);
1630
1631 if (! currently_expanding_to_rtl)
1632 FAIL;
1633 switch (code)
1634 {
1635 case LT: case LE: case LEU: case LTU:
1636 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1637 break;
1638 case NE:
1639 new_code = reverse_condition (code);
1640 break;
1641 case EQ: case GT: case GE: case GEU: case GTU:
1642 break;
1643 default:
1644 FAIL;
1645 }
1646 sh_emit_scc_to_t (new_code, op0, op1);
1647 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1648 gen_rtx_REG (SImode, T_REG), const0_rtx);
1649 }
1650 else
1651 {
1652 if (!can_create_pseudo_p ())
1653 FAIL;
1654
1655 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1656 GET_CODE (operands[1]),
1657 XEXP (operands[1], 0),
1658 XEXP (operands[1], 1));
1659 if (!operands[1])
1660 FAIL;
1661 }
1662 })
1663
1664 (define_expand "movqicc"
1665 [(set (match_operand:QI 0 "register_operand" "")
1666 (if_then_else:QI (match_operand 1 "comparison_operator" "")
1667 (match_operand:QI 2 "register_operand" "")
1668 (match_operand:QI 3 "register_operand" "")))]
1669 "TARGET_SHMEDIA"
1670 {
1671 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1672 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1673 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1674 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1675 DONE;
1676 })
1677 \f
1678 ;; -------------------------------------------------------------------------
1679 ;; Addition instructions
1680 ;; -------------------------------------------------------------------------
1681
1682 (define_expand "adddi3"
1683 [(set (match_operand:DI 0 "arith_reg_operand" "")
1684 (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
1685 (match_operand:DI 2 "arith_operand" "")))]
1686 ""
1687 {
1688 if (TARGET_SH1)
1689 {
1690 if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
1691 FAIL;
1692 operands[2] = force_reg (DImode, operands[2]);
1693 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1694 DONE;
1695 }
1696 })
1697
1698 (define_insn "*adddi3_media"
1699 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1700 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1701 (match_operand:DI 2 "arith_operand" "r,I10")))]
1702 "TARGET_SHMEDIA"
1703 "@
1704 add %1, %2, %0
1705 addi %1, %2, %0"
1706 [(set_attr "type" "arith_media")])
1707
1708 (define_insn "*adddisi3_media"
1709 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1710 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1711 (match_operand:DI 2 "arith_operand" "r,I10")))]
1712 "TARGET_SHMEDIA"
1713 "@
1714 add.l %1, %2, %0
1715 addi.l %1, %2, %0"
1716 [(set_attr "type" "arith_media")
1717 (set_attr "highpart" "ignore")])
1718
1719 (define_insn "adddi3z_media"
1720 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1721 (zero_extend:DI
1722 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1723 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1724 "TARGET_SHMEDIA"
1725 "addz.l %1, %N2, %0"
1726 [(set_attr "type" "arith_media")
1727 (set_attr "highpart" "ignore")])
1728
1729 (define_insn_and_split "adddi3_compact"
1730 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1731 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
1732 (match_operand:DI 2 "arith_reg_operand" "r")))
1733 (clobber (reg:SI T_REG))]
1734 "TARGET_SH1"
1735 "#"
1736 "&& reload_completed"
1737 [(const_int 0)]
1738 {
1739 rtx high0 = gen_highpart (SImode, operands[0]);
1740 rtx high2 = gen_highpart (SImode, operands[2]);
1741 rtx low0 = gen_lowpart (SImode, operands[0]);
1742
1743 emit_insn (gen_clrt ());
1744 emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
1745 emit_insn (gen_addc (high0, high0, high2));
1746 DONE;
1747 })
1748
1749 (define_insn "addc"
1750 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1751 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1752 (match_operand:SI 2 "arith_reg_operand" "r"))
1753 (reg:SI T_REG)))
1754 (set (reg:SI T_REG)
1755 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1756 "TARGET_SH1"
1757 "addc %2,%0"
1758 [(set_attr "type" "arith")])
1759
1760 ;; A simplified version of the addc insn, where the exact value of the
1761 ;; T bit doesn't matter. This is easier for combine to pick up.
1762 ;; We allow a reg or 0 for one of the operands in order to be able to
1763 ;; do 'reg + T' sequences. Reload will load the constant 0 into the reg
1764 ;; as needed.
1765 (define_insn "*addc"
1766 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1767 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1768 (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1769 (match_operand:SI 3 "t_reg_operand" "")))
1770 (clobber (reg:SI T_REG))]
1771 "TARGET_SH1"
1772 "addc %2,%0"
1773 [(set_attr "type" "arith")])
1774
1775 ;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
1776 ;; better, if the sett insn can be done early.
1777 (define_insn_and_split "*addc"
1778 [(set (match_operand:SI 0 "arith_reg_dest" "")
1779 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
1780 (match_operand:SI 2 "arith_reg_operand" ""))
1781 (const_int 1)))
1782 (clobber (reg:SI T_REG))]
1783 "TARGET_SH1"
1784 "#"
1785 "&& 1"
1786 [(set (reg:SI T_REG) (const_int 1))
1787 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
1788 (reg:SI T_REG)))
1789 (clobber (reg:SI T_REG))])])
1790
1791 ;; Left shifts by one are usually done with an add insn to avoid T_REG
1792 ;; clobbers. Thus addc can also be used to do something like '(x << 1) + 1'.
1793 (define_insn_and_split "*addc"
1794 [(set (match_operand:SI 0 "arith_reg_dest")
1795 (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
1796 (const_int 2))
1797 (const_int 1)))
1798 (clobber (reg:SI T_REG))]
1799 "TARGET_SH1"
1800 "#"
1801 "&& 1"
1802 [(set (reg:SI T_REG) (const_int 1))
1803 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
1804 (reg:SI T_REG)))
1805 (clobber (reg:SI T_REG))])])
1806
1807 ;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1808 ;; matched. Split this up into a simple sub add sequence, as this will save
1809 ;; us one sett insn.
1810 (define_insn_and_split "*minus_plus_one"
1811 [(set (match_operand:SI 0 "arith_reg_dest" "")
1812 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1813 (match_operand:SI 2 "arith_reg_operand" ""))
1814 (const_int 1)))]
1815 "TARGET_SH1"
1816 "#"
1817 "&& 1"
1818 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1819 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
1820
1821 ;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
1822 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
1823 ;; operation, as opposed to sequences such as
1824 ;; movt r2
1825 ;; add r2,r3
1826 ;;
1827 ;; Even if the constant is not CSE-ed, a sequence such as
1828 ;; mov #0,r2
1829 ;; addc r2,r3
1830 ;; can be scheduled much better since the load of the constant can be
1831 ;; done earlier, before any comparison insns that store the result in
1832 ;; the T bit.
1833 (define_insn_and_split "*addc"
1834 [(set (match_operand:SI 0 "arith_reg_dest" "")
1835 (plus:SI (match_operand:SI 1 "t_reg_operand" "")
1836 (match_operand:SI 2 "arith_reg_operand" "")))
1837 (clobber (reg:SI T_REG))]
1838 "TARGET_SH1"
1839 "#"
1840 "&& 1"
1841 [(parallel [(set (match_dup 0)
1842 (plus:SI (plus:SI (match_dup 2) (const_int 0))
1843 (match_dup 1)))
1844 (clobber (reg:SI T_REG))])])
1845
1846 (define_expand "addsi3"
1847 [(set (match_operand:SI 0 "arith_reg_operand" "")
1848 (plus:SI (match_operand:SI 1 "arith_operand" "")
1849 (match_operand:SI 2 "arith_operand" "")))]
1850 ""
1851 {
1852 if (TARGET_SHMEDIA)
1853 operands[1] = force_reg (SImode, operands[1]);
1854 })
1855
1856 (define_insn "addsi3_media"
1857 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1858 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
1859 (match_operand:SI 2 "arith_operand" "r,I10")))]
1860 "TARGET_SHMEDIA"
1861 "@
1862 add.l %1, %2, %0
1863 addi.l %1, %2, %0"
1864 [(set_attr "type" "arith_media")
1865 (set_attr "highpart" "ignore")])
1866
1867 (define_insn "addsidi3_media"
1868 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1869 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
1870 "%r,r")
1871 (match_operand:SI 2 "arith_operand"
1872 "r,I10"))))]
1873 "TARGET_SHMEDIA"
1874 "@
1875 add.l %1, %2, %0
1876 addi.l %1, %2, %0"
1877 [(set_attr "type" "arith_media")
1878 (set_attr "highpart" "ignore")])
1879
1880 (define_insn "*addsi3_compact"
1881 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1882 (plus:SI (match_operand:SI 1 "arith_operand" "%0")
1883 (match_operand:SI 2 "arith_operand" "rI08")))]
1884 "TARGET_SH1"
1885 "add %2,%0"
1886 [(set_attr "type" "arith")])
1887
1888 ;; -------------------------------------------------------------------------
1889 ;; Subtraction instructions
1890 ;; -------------------------------------------------------------------------
1891
1892 (define_expand "subdi3"
1893 [(set (match_operand:DI 0 "arith_reg_operand" "")
1894 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
1895 (match_operand:DI 2 "arith_reg_operand" "")))]
1896 ""
1897 {
1898 if (TARGET_SH1)
1899 {
1900 operands[1] = force_reg (DImode, operands[1]);
1901 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
1902 DONE;
1903 }
1904 })
1905
1906 (define_insn "*subdi3_media"
1907 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1908 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1909 (match_operand:DI 2 "arith_reg_operand" "r")))]
1910 "TARGET_SHMEDIA"
1911 "sub %N1, %2, %0"
1912 [(set_attr "type" "arith_media")])
1913
1914 (define_insn "subdisi3_media"
1915 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
1916 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
1917 (match_operand:DI 2 "arith_reg_operand" "r")))]
1918 "TARGET_SHMEDIA"
1919 "sub.l %N1, %2, %0"
1920 [(set_attr "type" "arith_media")
1921 (set_attr "highpart" "ignore")])
1922
1923 (define_insn_and_split "subdi3_compact"
1924 [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
1925 (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
1926 (match_operand:DI 2 "arith_reg_operand" "r")))
1927 (clobber (reg:SI T_REG))]
1928 "TARGET_SH1"
1929 "#"
1930 "&& reload_completed"
1931 [(const_int 0)]
1932 {
1933 rtx high0 = gen_highpart (SImode, operands[0]);
1934 rtx high2 = gen_highpart (SImode, operands[2]);
1935 rtx low0 = gen_lowpart (SImode, operands[0]);
1936
1937 emit_insn (gen_clrt ());
1938 emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
1939 emit_insn (gen_subc (high0, high0, high2));
1940 DONE;
1941 })
1942
1943 (define_insn "subc"
1944 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1945 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1946 (match_operand:SI 2 "arith_reg_operand" "r"))
1947 (reg:SI T_REG)))
1948 (set (reg:SI T_REG)
1949 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1950 (reg:SI T_REG))
1951 (match_dup 1)))]
1952 "TARGET_SH1"
1953 "subc %2,%0"
1954 [(set_attr "type" "arith")])
1955
1956 ;; A simplified version of the subc insn, where the exact value of the
1957 ;; T bit doesn't matter. This is easier for combine to pick up.
1958 ;; We allow a reg or 0 for one of the operands in order to be able to
1959 ;; do 'reg - T' sequences. Reload will load the constant 0 into the reg
1960 ;; as needed.
1961 (define_insn "*subc"
1962 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1963 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
1964 (match_operand:SI 2 "arith_reg_or_0_operand" "r"))
1965 (match_operand:SI 3 "t_reg_operand" "")))
1966 (clobber (reg:SI T_REG))]
1967 "TARGET_SH1"
1968 "subc %2,%0"
1969 [(set_attr "type" "arith")])
1970
1971 ;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
1972 ;; better, if the sett insn can be done early.
1973 ;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
1974 (define_insn_and_split "*subc"
1975 [(set (match_operand:SI 0 "arith_reg_dest" "")
1976 (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
1977 (match_operand:SI 2 "arith_reg_operand" "")))
1978 (clobber (reg:SI T_REG))]
1979 "TARGET_SH1"
1980 "#"
1981 "&& 1"
1982 [(set (reg:SI T_REG) (const_int 1))
1983 (parallel [(set (match_dup 0)
1984 (minus:SI (minus:SI (match_dup 2) (match_dup 1))
1985 (reg:SI T_REG)))
1986 (clobber (reg:SI T_REG))])])
1987
1988 ;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
1989 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
1990 ;; operation, as opposed to sequences such as
1991 ;; movt r2
1992 ;; sub r2,r3
1993 ;;
1994 ;; Even if the constant is not CSE-ed, a sequence such as
1995 ;; mov #0,r2
1996 ;; subc r2,r3
1997 ;; can be scheduled much better since the load of the constant can be
1998 ;; done earlier, before any comparison insns that store the result in
1999 ;; the T bit.
2000 (define_insn_and_split "*subc"
2001 [(set (match_operand:SI 0 "arith_reg_dest" "")
2002 (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2003 (match_operand:SI 2 "t_reg_operand" "")))
2004 (clobber (reg:SI T_REG))]
2005 "TARGET_SH1"
2006 "#"
2007 "&& 1"
2008 [(parallel [(set (match_dup 0)
2009 (minus:SI (minus:SI (match_dup 1) (const_int 0))
2010 (match_dup 2)))
2011 (clobber (reg:SI T_REG))])])
2012
2013 (define_insn "*subsi3_internal"
2014 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2015 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2016 (match_operand:SI 2 "arith_reg_operand" "r")))]
2017 "TARGET_SH1"
2018 "sub %2,%0"
2019 [(set_attr "type" "arith")])
2020
2021 (define_insn_and_split "*subsi3_media"
2022 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2023 (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2024 (match_operand:SI 2 "extend_reg_operand" "r")))]
2025 "TARGET_SHMEDIA
2026 && (operands[1] != constm1_rtx
2027 || (GET_CODE (operands[2]) != TRUNCATE
2028 && GET_CODE (operands[2]) != SUBREG))"
2029 "sub.l %N1, %2, %0"
2030 "operands[1] == constm1_rtx"
2031 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2032 ""
2033 [(set_attr "type" "arith_media")
2034 (set_attr "highpart" "ignore")])
2035
2036 (define_split
2037 [(set (match_operand:SI 0 "arith_reg_dest" "")
2038 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2039 "general_extend_operand"
2040 "") 0)) 0)))]
2041 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2042 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2043 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2044 "")
2045
2046 (define_split
2047 [(set (match_operand:SI 0 "arith_reg_dest" "")
2048 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2049 "general_extend_operand"
2050 "") 0)) 3)))]
2051 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
2052 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2053 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2054 "")
2055 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
2056 ;; will sometimes save one instruction. Otherwise we might get
2057 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
2058 ;; are the same.
2059
2060 (define_expand "subsi3"
2061 [(set (match_operand:SI 0 "arith_reg_operand" "")
2062 (minus:SI (match_operand:SI 1 "arith_operand" "")
2063 (match_operand:SI 2 "arith_reg_operand" "")))]
2064 ""
2065 {
2066 if (TARGET_SH1 && CONST_INT_P (operands[1]))
2067 {
2068 emit_insn (gen_negsi2 (operands[0], operands[2]));
2069 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2070 DONE;
2071 }
2072 if (TARGET_SHMEDIA)
2073 {
2074 if (!can_create_pseudo_p ()
2075 && ! arith_reg_or_0_operand (operands[1], SImode))
2076 FAIL;
2077 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2078 operands[1] = force_reg (SImode, operands[1]);
2079 }
2080 })
2081 \f
2082 ;; -------------------------------------------------------------------------
2083 ;; Division instructions
2084 ;; -------------------------------------------------------------------------
2085
2086 ;; We take advantage of the library routines which don't clobber as many
2087 ;; registers as a normal function call would.
2088
2089 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2090 ;; also has an effect on the register that holds the address of the sfunc.
2091 ;; To make this work, we have an extra dummy insn that shows the use
2092 ;; of this register for reorg.
2093
2094 (define_insn "use_sfunc_addr"
2095 [(set (reg:SI PR_REG)
2096 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2097 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2098 ""
2099 [(set_attr "length" "0")])
2100
2101 (define_insn "udivsi3_sh2a"
2102 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2103 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2104 (match_operand:SI 2 "arith_reg_operand" "z")))]
2105 "TARGET_SH2A"
2106 "divu %2,%1"
2107 [(set_attr "type" "arith")
2108 (set_attr "in_delay_slot" "no")])
2109
2110 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2111 ;; hard register 0. If we used hard register 0, then the next instruction
2112 ;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg
2113 ;; gets allocated to a stack slot that needs its address reloaded, then
2114 ;; there is nothing to prevent reload from using r0 to reload the address.
2115 ;; This reload would clobber the value in r0 we are trying to store.
2116 ;; If we let reload allocate r0, then this problem can never happen.
2117
2118 (define_insn "udivsi3_i1"
2119 [(set (match_operand:SI 0 "register_operand" "=z")
2120 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2121 (clobber (reg:SI T_REG))
2122 (clobber (reg:SI PR_REG))
2123 (clobber (reg:SI R4_REG))
2124 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2125 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
2126 "jsr @%1%#"
2127 [(set_attr "type" "sfunc")
2128 (set_attr "needs_delay_slot" "yes")])
2129
2130 ; Since shmedia-nofpu code could be linked against shcompact code, and
2131 ; the udivsi3 libcall has the same name, we must consider all registers
2132 ; clobbered that are in the union of the registers clobbered by the
2133 ; shmedia and the shcompact implementation. Note, if the shcompact
2134 ; implementation actually used shcompact code, we'd need to clobber
2135 ; also r23 and fr23.
2136 (define_insn "udivsi3_i1_media"
2137 [(set (match_operand:SI 0 "register_operand" "=z")
2138 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2139 (clobber (reg:SI T_MEDIA_REG))
2140 (clobber (reg:SI PR_MEDIA_REG))
2141 (clobber (reg:SI R20_REG))
2142 (clobber (reg:SI R21_REG))
2143 (clobber (reg:SI R22_REG))
2144 (clobber (reg:DI TR0_REG))
2145 (clobber (reg:DI TR1_REG))
2146 (clobber (reg:DI TR2_REG))
2147 (use (match_operand 1 "target_reg_operand" "b"))]
2148 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2149 "blink %1, r18"
2150 [(set_attr "type" "sfunc")
2151 (set_attr "needs_delay_slot" "yes")])
2152
2153 (define_expand "udivsi3_i4_media"
2154 [(set (match_dup 3)
2155 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2156 (set (match_dup 4)
2157 (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2158 (set (match_dup 5) (float:DF (match_dup 3)))
2159 (set (match_dup 6) (float:DF (match_dup 4)))
2160 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2161 (set (match_dup 8) (fix:DI (match_dup 7)))
2162 (set (match_operand:SI 0 "register_operand" "")
2163 (truncate:SI (match_dup 8)))]
2164 "TARGET_SHMEDIA_FPU"
2165 {
2166 operands[3] = gen_reg_rtx (DImode);
2167 operands[4] = gen_reg_rtx (DImode);
2168 operands[5] = gen_reg_rtx (DFmode);
2169 operands[6] = gen_reg_rtx (DFmode);
2170 operands[7] = gen_reg_rtx (DFmode);
2171 operands[8] = gen_reg_rtx (DImode);
2172 })
2173
2174 (define_insn "udivsi3_i4"
2175 [(set (match_operand:SI 0 "register_operand" "=y")
2176 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2177 (clobber (reg:SI T_REG))
2178 (clobber (reg:SI PR_REG))
2179 (clobber (reg:DF DR0_REG))
2180 (clobber (reg:DF DR2_REG))
2181 (clobber (reg:DF DR4_REG))
2182 (clobber (reg:SI R0_REG))
2183 (clobber (reg:SI R1_REG))
2184 (clobber (reg:SI R4_REG))
2185 (clobber (reg:SI R5_REG))
2186 (use (reg:PSI FPSCR_REG))
2187 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2188 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2189 "jsr @%1%#"
2190 [(set_attr "type" "sfunc")
2191 (set_attr "fp_mode" "double")
2192 (set_attr "needs_delay_slot" "yes")])
2193
2194 (define_insn "udivsi3_i4_single"
2195 [(set (match_operand:SI 0 "register_operand" "=y")
2196 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2197 (clobber (reg:SI T_REG))
2198 (clobber (reg:SI PR_REG))
2199 (clobber (reg:DF DR0_REG))
2200 (clobber (reg:DF DR2_REG))
2201 (clobber (reg:DF DR4_REG))
2202 (clobber (reg:SI R0_REG))
2203 (clobber (reg:SI R1_REG))
2204 (clobber (reg:SI R4_REG))
2205 (clobber (reg:SI R5_REG))
2206 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2207 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2208 "jsr @%1%#"
2209 [(set_attr "type" "sfunc")
2210 (set_attr "needs_delay_slot" "yes")])
2211
2212 (define_insn "udivsi3_i4_int"
2213 [(set (match_operand:SI 0 "register_operand" "=z")
2214 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2215 (clobber (reg:SI T_REG))
2216 (clobber (reg:SI R1_REG))
2217 (clobber (reg:SI PR_REG))
2218 (clobber (reg:SI MACH_REG))
2219 (clobber (reg:SI MACL_REG))
2220 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2221 "TARGET_SH1"
2222 "jsr @%1%#"
2223 [(set_attr "type" "sfunc")
2224 (set_attr "needs_delay_slot" "yes")])
2225
2226
2227 (define_expand "udivsi3"
2228 [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2229 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2230 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2231 (parallel [(set (match_operand:SI 0 "register_operand" "")
2232 (udiv:SI (reg:SI R4_REG)
2233 (reg:SI R5_REG)))
2234 (clobber (reg:SI T_REG))
2235 (clobber (reg:SI PR_REG))
2236 (clobber (reg:SI R4_REG))
2237 (use (match_dup 3))])]
2238 ""
2239 {
2240 rtx last;
2241
2242 operands[3] = gen_reg_rtx (Pmode);
2243 /* Emit the move of the address to a pseudo outside of the libcall. */
2244 if (TARGET_DIVIDE_CALL_TABLE)
2245 {
2246 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2247 that causes problems when the divide code is supposed to come from a
2248 separate library. Division by zero is undefined, so dividing 1 can be
2249 implemented by comparing with the divisor. */
2250 if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2251 {
2252 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2253 emit_insn (gen_cstoresi4 (operands[0], test,
2254 operands[1], operands[2]));
2255 DONE;
2256 }
2257 else if (operands[2] == const0_rtx)
2258 {
2259 emit_move_insn (operands[0], operands[2]);
2260 DONE;
2261 }
2262 function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2263 last = gen_udivsi3_i4_int (operands[0], operands[3]);
2264 }
2265 else if (TARGET_DIVIDE_CALL_FP)
2266 {
2267 function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
2268 if (TARGET_FPU_SINGLE)
2269 last = gen_udivsi3_i4_single (operands[0], operands[3]);
2270 else
2271 last = gen_udivsi3_i4 (operands[0], operands[3]);
2272 }
2273 else if (TARGET_SHMEDIA_FPU)
2274 {
2275 operands[1] = force_reg (SImode, operands[1]);
2276 operands[2] = force_reg (SImode, operands[2]);
2277 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2278 DONE;
2279 }
2280 else if (TARGET_SH2A)
2281 {
2282 operands[1] = force_reg (SImode, operands[1]);
2283 operands[2] = force_reg (SImode, operands[2]);
2284 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2285 DONE;
2286 }
2287 else if (TARGET_SH5)
2288 {
2289 function_symbol (operands[3],
2290 TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2291 SFUNC_STATIC);
2292
2293 if (TARGET_SHMEDIA)
2294 last = gen_udivsi3_i1_media (operands[0], operands[3]);
2295 else if (TARGET_FPU_ANY)
2296 last = gen_udivsi3_i4_single (operands[0], operands[3]);
2297 else
2298 last = gen_udivsi3_i1 (operands[0], operands[3]);
2299 }
2300 else
2301 {
2302 function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
2303 last = gen_udivsi3_i1 (operands[0], operands[3]);
2304 }
2305 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2306 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2307 emit_insn (last);
2308 DONE;
2309 })
2310
2311 (define_insn "divsi3_sh2a"
2312 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2313 (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2314 (match_operand:SI 2 "arith_reg_operand" "z")))]
2315 "TARGET_SH2A"
2316 "divs %2,%1"
2317 [(set_attr "type" "arith")
2318 (set_attr "in_delay_slot" "no")])
2319
2320 (define_insn "divsi3_i1"
2321 [(set (match_operand:SI 0 "register_operand" "=z")
2322 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2323 (clobber (reg:SI T_REG))
2324 (clobber (reg:SI PR_REG))
2325 (clobber (reg:SI R1_REG))
2326 (clobber (reg:SI R2_REG))
2327 (clobber (reg:SI R3_REG))
2328 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2329 "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
2330 "jsr @%1%#"
2331 [(set_attr "type" "sfunc")
2332 (set_attr "needs_delay_slot" "yes")])
2333
2334 (define_insn "divsi3_i1_media"
2335 [(set (match_operand:SI 0 "register_operand" "=z")
2336 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2337 (clobber (reg:SI T_MEDIA_REG))
2338 (clobber (reg:SI PR_MEDIA_REG))
2339 (clobber (reg:SI R1_REG))
2340 (clobber (reg:SI R20_REG))
2341 (clobber (reg:SI R21_REG))
2342 (clobber (reg:SI TR0_REG))
2343 (use (match_operand 1 "target_reg_operand" "b"))]
2344 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2345 "blink %1, r18"
2346 [(set_attr "type" "sfunc")])
2347
2348 (define_insn "divsi3_media_2"
2349 [(set (match_operand:SI 0 "register_operand" "=z")
2350 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2351 (clobber (reg:SI T_MEDIA_REG))
2352 (clobber (reg:SI PR_MEDIA_REG))
2353 (clobber (reg:SI R1_REG))
2354 (clobber (reg:SI R21_REG))
2355 (clobber (reg:SI TR0_REG))
2356 (use (reg:SI R20_REG))
2357 (use (match_operand 1 "target_reg_operand" "b"))]
2358 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2359 "blink %1, r18"
2360 [(set_attr "type" "sfunc")])
2361
2362 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2363 ;; hard reg clobbers and data dependencies that we need when we want
2364 ;; to rematerialize the division into a call.
2365 (define_insn_and_split "divsi_inv_call"
2366 [(set (match_operand:SI 0 "register_operand" "=r")
2367 (div:SI (match_operand:SI 1 "register_operand" "r")
2368 (match_operand:SI 2 "register_operand" "r")))
2369 (clobber (reg:SI R4_REG))
2370 (clobber (reg:SI R5_REG))
2371 (clobber (reg:SI T_MEDIA_REG))
2372 (clobber (reg:SI PR_MEDIA_REG))
2373 (clobber (reg:SI R1_REG))
2374 (clobber (reg:SI R21_REG))
2375 (clobber (reg:SI TR0_REG))
2376 (clobber (reg:SI R20_REG))
2377 (use (match_operand:SI 3 "register_operand" "r"))]
2378 "TARGET_SHMEDIA"
2379 "#"
2380 "&& (reload_in_progress || reload_completed)"
2381 [(set (match_dup 0) (match_dup 3))]
2382 ""
2383 [(set_attr "highpart" "must_split")])
2384
2385 ;; This is the combiner pattern for -mdiv=inv:call .
2386 (define_insn_and_split "*divsi_inv_call_combine"
2387 [(set (match_operand:SI 0 "register_operand" "=z")
2388 (div:SI (match_operand:SI 1 "register_operand" "r")
2389 (match_operand:SI 2 "register_operand" "r")))
2390 (clobber (reg:SI R4_REG))
2391 (clobber (reg:SI R5_REG))
2392 (clobber (reg:SI T_MEDIA_REG))
2393 (clobber (reg:SI PR_MEDIA_REG))
2394 (clobber (reg:SI R1_REG))
2395 (clobber (reg:SI R21_REG))
2396 (clobber (reg:SI TR0_REG))
2397 (clobber (reg:SI R20_REG))
2398 (use (unspec:SI [(match_dup 1)
2399 (match_operand:SI 3 "" "")
2400 (unspec:SI [(match_operand:SI 4 "" "")
2401 (match_dup 3)
2402 (match_operand:DI 5 "" "")]
2403 UNSPEC_DIV_INV_M2)
2404 (match_operand:DI 6 "" "")
2405 (const_int 0)
2406 (const_int 0)]
2407 UNSPEC_DIV_INV_M3))]
2408 "TARGET_SHMEDIA"
2409 "#"
2410 "&& (reload_in_progress || reload_completed)"
2411 [(pc)]
2412 {
2413 const char *name = sh_divsi3_libfunc;
2414 enum sh_function_kind kind = SFUNC_GOT;
2415 rtx sym;
2416
2417 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2418 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2419 while (TARGET_DIVIDE_INV_CALL2)
2420 {
2421 rtx x = operands[3];
2422
2423 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2424 break;
2425 x = XVECEXP (x, 0, 0);
2426 name = "__sdivsi3_2";
2427 kind = SFUNC_STATIC;
2428 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2429 break;
2430 }
2431 sym = function_symbol (NULL, name, kind);
2432 emit_insn (gen_divsi3_media_2 (operands[0], sym));
2433 DONE;
2434 }
2435 [(set_attr "highpart" "must_split")])
2436
2437 (define_expand "divsi3_i4_media"
2438 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2439 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2440 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2441 (set (match_operand:SI 0 "register_operand" "=r")
2442 (fix:SI (match_dup 5)))]
2443 "TARGET_SHMEDIA_FPU"
2444 {
2445 operands[3] = gen_reg_rtx (DFmode);
2446 operands[4] = gen_reg_rtx (DFmode);
2447 operands[5] = gen_reg_rtx (DFmode);
2448 })
2449
2450 (define_insn "divsi3_i4"
2451 [(set (match_operand:SI 0 "register_operand" "=y")
2452 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2453 (clobber (reg:SI PR_REG))
2454 (clobber (reg:DF DR0_REG))
2455 (clobber (reg:DF DR2_REG))
2456 (use (reg:PSI FPSCR_REG))
2457 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2458 "TARGET_SH4 && ! TARGET_FPU_SINGLE"
2459 "jsr @%1%#"
2460 [(set_attr "type" "sfunc")
2461 (set_attr "fp_mode" "double")
2462 (set_attr "needs_delay_slot" "yes")])
2463
2464 (define_insn "divsi3_i4_single"
2465 [(set (match_operand:SI 0 "register_operand" "=y")
2466 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2467 (clobber (reg:SI PR_REG))
2468 (clobber (reg:DF DR0_REG))
2469 (clobber (reg:DF DR2_REG))
2470 (clobber (reg:SI R2_REG))
2471 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2472 "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
2473 "jsr @%1%#"
2474 [(set_attr "type" "sfunc")
2475 (set_attr "needs_delay_slot" "yes")])
2476
2477 (define_insn "divsi3_i4_int"
2478 [(set (match_operand:SI 0 "register_operand" "=z")
2479 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2480 (clobber (reg:SI T_REG))
2481 (clobber (reg:SI PR_REG))
2482 (clobber (reg:SI R1_REG))
2483 (clobber (reg:SI MACH_REG))
2484 (clobber (reg:SI MACL_REG))
2485 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2486 "TARGET_SH1"
2487 "jsr @%1%#"
2488 [(set_attr "type" "sfunc")
2489 (set_attr "needs_delay_slot" "yes")])
2490
2491 (define_expand "divsi3"
2492 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2493 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2494 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2495 (parallel [(set (match_operand:SI 0 "register_operand" "")
2496 (div:SI (reg:SI R4_REG)
2497 (reg:SI R5_REG)))
2498 (clobber (reg:SI T_REG))
2499 (clobber (reg:SI PR_REG))
2500 (clobber (reg:SI R1_REG))
2501 (clobber (reg:SI R2_REG))
2502 (clobber (reg:SI R3_REG))
2503 (use (match_dup 3))])]
2504 ""
2505 {
2506 rtx last;
2507
2508 operands[3] = gen_reg_rtx (Pmode);
2509 /* Emit the move of the address to a pseudo outside of the libcall. */
2510 if (TARGET_DIVIDE_CALL_TABLE)
2511 {
2512 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2513 last = gen_divsi3_i4_int (operands[0], operands[3]);
2514 }
2515 else if (TARGET_DIVIDE_CALL_FP)
2516 {
2517 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2518 if (TARGET_FPU_SINGLE)
2519 last = gen_divsi3_i4_single (operands[0], operands[3]);
2520 else
2521 last = gen_divsi3_i4 (operands[0], operands[3]);
2522 }
2523 else if (TARGET_SH2A)
2524 {
2525 operands[1] = force_reg (SImode, operands[1]);
2526 operands[2] = force_reg (SImode, operands[2]);
2527 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
2528 DONE;
2529 }
2530 else if (TARGET_DIVIDE_INV)
2531 {
2532 rtx dividend = operands[1];
2533 rtx divisor = operands[2];
2534 rtx tab_base;
2535 rtx nsb_res = gen_reg_rtx (DImode);
2536 rtx norm64 = gen_reg_rtx (DImode);
2537 rtx tab_ix = gen_reg_rtx (DImode);
2538 rtx norm32 = gen_reg_rtx (SImode);
2539 rtx i92 = force_reg (DImode, GEN_INT (92));
2540 rtx scratch0a = gen_reg_rtx (DImode);
2541 rtx scratch0b = gen_reg_rtx (DImode);
2542 rtx inv0 = gen_reg_rtx (SImode);
2543 rtx scratch1a = gen_reg_rtx (DImode);
2544 rtx scratch1b = gen_reg_rtx (DImode);
2545 rtx shift = gen_reg_rtx (DImode);
2546 rtx i2p27, i43;
2547 rtx inv1 = gen_reg_rtx (SImode);
2548 rtx scratch2a = gen_reg_rtx (DImode);
2549 rtx scratch2b = gen_reg_rtx (SImode);
2550 rtx inv2 = gen_reg_rtx (SImode);
2551 rtx scratch3a = gen_reg_rtx (DImode);
2552 rtx scratch3b = gen_reg_rtx (DImode);
2553 rtx scratch3c = gen_reg_rtx (DImode);
2554 rtx scratch3d = gen_reg_rtx (SImode);
2555 rtx scratch3e = gen_reg_rtx (DImode);
2556 rtx result = gen_reg_rtx (SImode);
2557
2558 if (! arith_reg_or_0_operand (dividend, SImode))
2559 dividend = force_reg (SImode, dividend);
2560 if (! arith_reg_operand (divisor, SImode))
2561 divisor = force_reg (SImode, divisor);
2562 if (flag_pic && Pmode != DImode)
2563 {
2564 tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2565 tab_base = gen_datalabel_ref (tab_base);
2566 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
2567 }
2568 else
2569 {
2570 tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
2571 tab_base = gen_datalabel_ref (tab_base);
2572 tab_base = force_reg (DImode, tab_base);
2573 }
2574 if (TARGET_DIVIDE_INV20U)
2575 i2p27 = force_reg (DImode, GEN_INT (-2 << 27));
2576 else
2577 i2p27 = GEN_INT (0);
2578 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
2579 i43 = force_reg (DImode, GEN_INT (43));
2580 else
2581 i43 = GEN_INT (0);
2582 emit_insn (gen_nsbdi (nsb_res,
2583 simplify_gen_subreg (DImode, divisor, SImode, 0)));
2584 emit_insn (gen_ashldi3_media (norm64,
2585 gen_rtx_SUBREG (DImode, divisor, 0),
2586 nsb_res));
2587 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
2588 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
2589 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
2590 inv0, scratch0a, scratch0b,
2591 scratch1a, scratch1b));
2592 emit_insn (gen_subdi3 (shift, i92, nsb_res));
2593 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
2594 scratch2a));
2595 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
2596 i2p27, i43,
2597 scratch3a, scratch3b, scratch3c,
2598 scratch2a, scratch2b, scratch3d, scratch3e));
2599 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
2600 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
2601 else if (TARGET_DIVIDE_INV_FP)
2602 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
2603 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
2604 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
2605 gen_reg_rtx (DFmode)));
2606 else
2607 emit_move_insn (operands[0], result);
2608 DONE;
2609 }
2610 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
2611 {
2612 operands[1] = force_reg (SImode, operands[1]);
2613 operands[2] = force_reg (SImode, operands[2]);
2614 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
2615 DONE;
2616 }
2617 else if (TARGET_SH5)
2618 {
2619 if (TARGET_DIVIDE_CALL2)
2620 {
2621 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
2622 tab_base = gen_datalabel_ref (tab_base);
2623 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
2624 }
2625 if (TARGET_FPU_ANY && TARGET_SH1)
2626 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2627 else if (TARGET_DIVIDE_CALL2)
2628 function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
2629 else
2630 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2631
2632 if (TARGET_SHMEDIA)
2633 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
2634 (operands[0], operands[3]));
2635 else if (TARGET_FPU_ANY)
2636 last = gen_divsi3_i4_single (operands[0], operands[3]);
2637 else
2638 last = gen_divsi3_i1 (operands[0], operands[3]);
2639 }
2640 else
2641 {
2642 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2643 last = gen_divsi3_i1 (operands[0], operands[3]);
2644 }
2645 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2646 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2647 emit_insn (last);
2648 DONE;
2649 })
2650
2651 ;; operands: scratch, tab_base, tab_ix
2652 ;; These are unspecs because we could generate an indexed addressing mode
2653 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
2654 ;; confuse reload. See PR27117.
2655
2656 (define_insn "divsi_inv_qitable"
2657 [(set (match_operand:DI 0 "register_operand" "=r")
2658 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
2659 (match_operand:DI 2 "register_operand" "r")]
2660 UNSPEC_DIV_INV_TABLE)))]
2661 "TARGET_SHMEDIA"
2662 "ldx.ub %1, %2, %0"
2663 [(set_attr "type" "load_media")
2664 (set_attr "highpart" "user")])
2665
2666 ;; operands: scratch, tab_base, tab_ix
2667 (define_insn "divsi_inv_hitable"
2668 [(set (match_operand:DI 0 "register_operand" "=r")
2669 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
2670 (match_operand:DI 2 "register_operand" "r")]
2671 UNSPEC_DIV_INV_TABLE)))]
2672 "TARGET_SHMEDIA"
2673 "ldx.w %1, %2, %0"
2674 [(set_attr "type" "load_media")
2675 (set_attr "highpart" "user")])
2676
2677 ;; operands: inv0, tab_base, tab_ix, norm32
2678 ;; scratch equiv in sdivsi3_2: r19, r21
2679 (define_expand "divsi_inv_m0"
2680 [(set (match_operand:SI 0 "register_operand" "=r")
2681 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2682 (match_operand:DI 2 "register_operand" "r")
2683 (match_operand:SI 3 "register_operand" "r")]
2684 UNSPEC_DIV_INV_M0))
2685 (clobber (match_operand:DI 4 "register_operand" "=r"))
2686 (clobber (match_operand:DI 5 "register_operand" "=r"))]
2687 "TARGET_SHMEDIA"
2688 {
2689 /*
2690 tab_base: r20
2691 tab_ix: r21
2692 norm32: r25
2693 ldx.ub r20, r21, r19 // u0.8
2694 shlli r21, 1, r21
2695 muls.l r25, r19, r19 // s2.38
2696 ldx.w r20, r21, r21 // s2.14
2697 shari r19, 24, r19 // truncate to s2.14
2698 sub r21, r19, r19 // some 11 bit inverse in s1.14
2699 */
2700
2701 rtx inv0 = operands[0];
2702 rtx tab_base = operands[1];
2703 rtx tab_ix = operands[2];
2704 rtx norm32 = operands[3];
2705 rtx scratch0 = operands[4];
2706 rtx scratch0_si = gen_lowpart (SImode, scratch0);
2707 rtx scratch1 = operands[5];
2708
2709 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
2710 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
2711 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
2712 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
2713 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
2714 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
2715 DONE;
2716 })
2717
2718 ;; operands: inv1, tab_base, tab_ix, norm32
2719 (define_insn_and_split "divsi_inv_m1"
2720 [(set (match_operand:SI 0 "register_operand" "=r")
2721 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
2722 (match_operand:DI 2 "register_operand" "r")
2723 (match_operand:SI 3 "register_operand" "r")]
2724 UNSPEC_DIV_INV_M1))
2725 (clobber (match_operand:SI 4 "register_operand" "=r"))
2726 (clobber (match_operand:DI 5 "register_operand" "=r"))
2727 (clobber (match_operand:DI 6 "register_operand" "=r"))
2728 (clobber (match_operand:DI 7 "register_operand" "=r"))
2729 (clobber (match_operand:DI 8 "register_operand" "=r"))]
2730 "TARGET_SHMEDIA"
2731 "#"
2732 "&& !can_create_pseudo_p ()"
2733 [(pc)]
2734 {
2735 /* inv0: r19
2736 muls.l r19, r19, r18 // u0.28
2737 muls.l r25, r18, r18 // s2.58
2738 shlli r19, 45, r0 // multiply by two and convert to s2.58
2739 sub r0, r18, r18
2740 shari r18, 28, r18 // some 18 bit inverse in s1.30
2741 */
2742
2743 rtx inv1 = operands[0];
2744 rtx tab_base = operands[1];
2745 rtx tab_ix = operands[2];
2746 rtx norm32 = operands[3];
2747 rtx inv0 = operands[4];
2748 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
2749 rtx scratch0a = operands[5];
2750 rtx scratch0b = operands[6];
2751 rtx scratch0 = operands[7];
2752 rtx scratch1 = operands[8];
2753 rtx scratch1_si = gen_lowpart (SImode, scratch1);
2754
2755 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
2756 scratch0a, scratch0b));
2757 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
2758 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2759 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
2760 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
2761 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
2762 DONE;
2763 })
2764
2765 ;; operands: inv2, norm32, inv1, i92
2766 (define_insn_and_split "divsi_inv_m2"
2767 [(set (match_operand:SI 0 "register_operand" "=r")
2768 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
2769 (match_operand:SI 2 "register_operand" "r")
2770 (match_operand:DI 3 "register_operand" "r")]
2771 UNSPEC_DIV_INV_M2))
2772 (clobber (match_operand:DI 4 "register_operand" "=r"))]
2773 "TARGET_SHMEDIA"
2774 "#"
2775 "&& !can_create_pseudo_p ()"
2776 [(pc)]
2777 {
2778 /*
2779 muls.l r18, r25, r0 // s2.60
2780 shari r0, 16, r0 // s-16.44
2781 sub
2782 muls.l r0, r18, r19 // s-16.74
2783 shari r19, 30, r19 // s-16.44
2784 */
2785 rtx inv2 = operands[0];
2786 rtx norm32 = operands[1];
2787 rtx inv1 = operands[2];
2788 rtx i92 = operands[3];
2789 rtx scratch0 = operands[4];
2790 rtx scratch0_si = gen_lowpart (SImode, scratch0);
2791
2792 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
2793 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
2794 emit_insn (gen_subdi3 (scratch0, i92, scratch0));
2795 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
2796 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
2797 DONE;
2798 })
2799
2800 (define_insn_and_split "divsi_inv_m3"
2801 [(set (match_operand:SI 0 "register_operand" "=r")
2802 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2803 (match_operand:SI 2 "register_operand" "r")
2804 (match_operand:SI 3 "register_operand" "r")
2805 (match_operand:DI 4 "register_operand" "r")
2806 (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
2807 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
2808 UNSPEC_DIV_INV_M3))
2809 (clobber (match_operand:DI 7 "register_operand" "=r"))
2810 (clobber (match_operand:DI 8 "register_operand" "=r"))
2811 (clobber (match_operand:DI 9 "register_operand" "=r"))
2812 (clobber (match_operand:DI 10 "register_operand" "=r"))
2813 (clobber (match_operand:SI 11 "register_operand" "=r"))
2814 (clobber (match_operand:SI 12 "register_operand" "=r"))
2815 (clobber (match_operand:DI 13 "register_operand" "=r"))]
2816 "TARGET_SHMEDIA"
2817 "#"
2818 "&& !can_create_pseudo_p ()"
2819 [(pc)]
2820 {
2821 /*
2822 r0: result r1: shift r4: dividend r18: inv1 r19: inv2
2823 r0: scratch0 r19: scratch1 r21: scratch2
2824
2825 muls.l r18, r4, r25 // s32.30
2826 muls.l r19, r4, r19 // s15.30
2827 shari r25, 63, r21
2828 shari r19, 14, r19 // s18.-14
2829 sub r25, r19, r0
2830 shard r0, r1, r0
2831 sub r0, r21, r0
2832 */
2833
2834 rtx result = operands[0];
2835 rtx dividend = operands[1];
2836 rtx inv1 = operands[2];
2837 rtx inv2 = operands[3];
2838 rtx shift = operands[4];
2839 rtx scratch0 = operands[7];
2840 rtx scratch1 = operands[8];
2841 rtx scratch2 = operands[9];
2842
2843 if (satisfies_constraint_N (dividend))
2844 {
2845 emit_move_insn (result, dividend);
2846 DONE;
2847 }
2848
2849 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
2850 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
2851 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
2852 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
2853 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
2854 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
2855 emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
2856 DONE;
2857 })
2858
2859 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
2860 ;; inv1: tab_base, tab_ix, norm32
2861 ;; inv2: norm32, inv1, i92
2862 (define_insn_and_split "divsi_inv_m1_3"
2863 [(set (match_operand:SI 0 "register_operand" "=r")
2864 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
2865 (unspec:SI [(match_operand:DI 2 "register_operand" "r")
2866 (match_operand:DI 3 "register_operand" "r")
2867 (match_operand:SI 4 "register_operand" "r")]
2868 UNSPEC_DIV_INV_M1)
2869 (unspec:SI [(match_dup 4)
2870 (unspec:SI [(match_dup 2)
2871 (match_dup 3)
2872 (match_dup 4)] UNSPEC_DIV_INV_M1)
2873 (match_operand:SI 5 "" "")]
2874 UNSPEC_DIV_INV_M2)
2875 (match_operand:DI 6 "register_operand" "r")
2876 (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
2877 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
2878 UNSPEC_DIV_INV_M3))
2879 (clobber (match_operand:DI 9 "register_operand" "=r"))
2880 (clobber (match_operand:DI 10 "register_operand" "=r"))
2881 (clobber (match_operand:DI 11 "register_operand" "=r"))
2882 (clobber (match_operand:DI 12 "register_operand" "=r"))
2883 (clobber (match_operand:SI 13 "register_operand" "=r"))
2884 (clobber (match_operand:SI 14 "register_operand" "=r"))
2885 (clobber (match_operand:DI 15 "register_operand" "=r"))]
2886 "TARGET_SHMEDIA
2887 && (TARGET_DIVIDE_INV_MINLAT
2888 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2889 "#"
2890 "&& !can_create_pseudo_p ()"
2891 [(pc)]
2892 {
2893 rtx result = operands[0];
2894 rtx dividend = operands[1];
2895 rtx tab_base = operands[2];
2896 rtx tab_ix = operands[3];
2897 rtx norm32 = operands[4];
2898 /* rtx i92 = operands[5]; */
2899 rtx shift = operands[6];
2900 rtx i2p27 = operands[7];
2901 rtx i43 = operands[8];
2902 rtx scratch0 = operands[9];
2903 rtx scratch0_si = gen_lowpart (SImode, scratch0);
2904 rtx scratch1 = operands[10];
2905 rtx scratch1_si = gen_lowpart (SImode, scratch1);
2906 rtx scratch2 = operands[11];
2907 rtx scratch3 = operands[12];
2908 rtx scratch4 = operands[13];
2909 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
2910 rtx scratch5 = operands[14];
2911 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
2912 rtx scratch6 = operands[15];
2913
2914 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
2915 scratch0, scratch1));
2916 /* inv0 == scratch4 */
2917 if (! TARGET_DIVIDE_INV20U)
2918 {
2919 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
2920 i2p27 = scratch0;
2921 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
2922 }
2923 else
2924 {
2925 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
2926 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
2927 }
2928 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
2929 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
2930 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
2931 /* inv1 == scratch4 */
2932
2933 if (TARGET_DIVIDE_INV_MINLAT)
2934 {
2935 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
2936 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
2937 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
2938 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
2939 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
2940 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
2941 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
2942 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
2943 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
2944 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
2945 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
2946 }
2947 else
2948 {
2949 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
2950 /* Use separate scratch regs for nsb and sign to allow scheduling. */
2951 emit_insn (gen_nsbdi (scratch6,
2952 simplify_gen_subreg (DImode, dividend, SImode, 0)));
2953 emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
2954 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
2955 emit_insn (gen_divsi_inv20 (scratch2,
2956 norm32, scratch4, dividend,
2957 scratch6, scratch3, i43,
2958 /* scratch0 may be shared with i2p27. */
2959 scratch0, scratch1, scratch5,
2960 label, label, i2p27));
2961 }
2962 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
2963 emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
2964 DONE;
2965 })
2966
2967 (define_insn "divsi_inv20"
2968 [(set (match_operand:DI 0 "register_operand" "=&r")
2969 (unspec:DI [(match_operand:SI 1 "register_operand" "r")
2970 (match_operand:SI 2 "register_operand" "r")
2971 (match_operand:SI 3 "register_operand" "r")
2972 (match_operand:DI 4 "register_operand" "r")
2973 (match_operand:DI 5 "register_operand" "r")
2974 (match_operand:DI 6 "register_operand" "r")
2975 (match_operand:DI 12 "register_operand" "r")
2976 (match_operand 10 "target_operand" "b")
2977 (match_operand 11 "immediate_operand" "i")]
2978 UNSPEC_DIV_INV20))
2979 (clobber (match_operand:DI 7 "register_operand" "=&r"))
2980 (clobber (match_operand:DI 8 "register_operand" "=&r"))
2981 (clobber (match_operand:SI 9 "register_operand" "=r"))]
2982 "TARGET_SHMEDIA
2983 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
2984 {
2985 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
2986 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
2987 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
2988 %10 label (tr), %11 label (imm)
2989
2990 muls.l inv1, norm32, scratch0 // s2.60
2991 muls.l inv1, dividend, result // s32.30
2992 xor i2p27, result_sign, round_scratch
2993 bge/u dividend_nsb, i43, tr.. (label)
2994 shari scratch0, 16, scratch0 // s-16.44
2995 muls.l sratch0_si, inv1, scratch0 // s-16.74
2996 sub result, round_scratch, result
2997 shari dividend, 14, scratch1 // s19.-14
2998 shari scratch0, 30, scratch0 // s-16.44
2999 muls.l scratch0, scratch1, round_scratch // s15.30
3000 label:
3001 sub result, round_scratch, result */
3002
3003 const bool likely = TARGET_DIVIDE_INV20L;
3004 if (likely)
3005 return
3006 "muls.l %2, %3, %0" "\n"
3007 " xor %12, %5, %7" "\n"
3008 " bge/l %4, %6, %10" "\n"
3009 " muls.l %2, %1, %8" "\n"
3010 " shari %8, 16, %8" "\n"
3011 " muls.l %8, %2, %8" "\n"
3012 " shari %3, 14, %9" "\n"
3013 " shari %8, 30, %8" "\n"
3014 " muls.l %8, %9, %8" "\n"
3015 " sub %0, %8, %0" "\n"
3016 "%11: add %0, %7, %0";
3017 else
3018 return
3019 "muls.l %2, %1, %8" "\n"
3020 " muls.l %2, %3, %0" "\n"
3021 " xor %12, %5, %7" "\n"
3022 " bge/u %4, %6, %10" "\n"
3023 " shari %8, 16, %8" "\n"
3024 " muls.l %8, %2, %8" "\n"
3025 " sub %0, %7, %0" "\n"
3026 " shari %3, 14, %9" "\n"
3027 " shari %8, 30, %8" "\n"
3028 " muls.l %8, %9, %7" "\n"
3029 "%11: sub %0, %7, %0";
3030 })
3031
3032 (define_insn_and_split "divsi_inv_fp"
3033 [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3034 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3035 (match_operand:SI 2 "register_operand" "rf")))
3036 (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3037 (clobber (match_operand:SI 4 "register_operand" "=r"))
3038 (clobber (match_operand:SI 5 "register_operand" "=r"))
3039 (clobber (match_operand:DF 6 "register_operand" "=r"))
3040 (clobber (match_operand:DF 7 "register_operand" "=r"))
3041 (clobber (match_operand:DF 8 "register_operand" "=r"))]
3042 "TARGET_SHMEDIA_FPU"
3043 "#"
3044 "&& (reload_in_progress || reload_completed)"
3045 [(set (match_dup 0) (match_dup 3))]
3046 ""
3047 [(set_attr "highpart" "must_split")])
3048
3049 ;; If a matching group of divide-by-inverse instructions is in the same
3050 ;; basic block after gcse & loop optimizations, we want to transform them
3051 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3052 (define_insn_and_split "*divsi_inv_fp_combine"
3053 [(set (match_operand:SI 0 "register_operand" "=f")
3054 (div:SI (match_operand:SI 1 "register_operand" "f")
3055 (match_operand:SI 2 "register_operand" "f")))
3056 (use (unspec:SI [(match_dup 1)
3057 (match_operand:SI 3 "" "")
3058 (unspec:SI [(match_operand:SI 4 "" "")
3059 (match_dup 3)
3060 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3061 (match_operand:DI 6 "" "")
3062 (const_int 0)
3063 (const_int 0)] UNSPEC_DIV_INV_M3))
3064 (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3065 (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3066 (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3067 (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3068 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3069 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3070 "#"
3071 "&& 1"
3072 [(set (match_dup 9) (float:DF (match_dup 1)))
3073 (set (match_dup 10) (float:DF (match_dup 2)))
3074 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3075 (set (match_dup 8)
3076 (fix:SI (match_dup 11)))
3077 (set (match_dup 0) (match_dup 8))]
3078 {
3079 if (! fp_arith_reg_operand (operands[1], SImode))
3080 {
3081 emit_move_insn (operands[7], operands[1]);
3082 operands[1] = operands[7];
3083 }
3084 if (! fp_arith_reg_operand (operands[2], SImode))
3085 {
3086 emit_move_insn (operands[8], operands[2]);
3087 operands[2] = operands[8];
3088 }
3089 }
3090 [(set_attr "highpart" "must_split")])
3091 \f
3092 ;; -------------------------------------------------------------------------
3093 ;; Multiplication instructions
3094 ;; -------------------------------------------------------------------------
3095
3096 (define_insn "umulhisi3_i"
3097 [(set (reg:SI MACL_REG)
3098 (mult:SI (zero_extend:SI
3099 (match_operand:HI 0 "arith_reg_operand" "r"))
3100 (zero_extend:SI
3101 (match_operand:HI 1 "arith_reg_operand" "r"))))]
3102 "TARGET_SH1"
3103 "mulu.w %1,%0"
3104 [(set_attr "type" "smpy")])
3105
3106 (define_insn "mulhisi3_i"
3107 [(set (reg:SI MACL_REG)
3108 (mult:SI (sign_extend:SI
3109 (match_operand:HI 0 "arith_reg_operand" "r"))
3110 (sign_extend:SI
3111 (match_operand:HI 1 "arith_reg_operand" "r"))))]
3112 "TARGET_SH1"
3113 "muls.w %1,%0"
3114 [(set_attr "type" "smpy")])
3115
3116 (define_expand "mulhisi3"
3117 [(set (reg:SI MACL_REG)
3118 (mult:SI (sign_extend:SI
3119 (match_operand:HI 1 "arith_reg_operand" ""))
3120 (sign_extend:SI
3121 (match_operand:HI 2 "arith_reg_operand" ""))))
3122 (set (match_operand:SI 0 "arith_reg_operand" "")
3123 (reg:SI MACL_REG))]
3124 "TARGET_SH1"
3125 {
3126 rtx insn, macl;
3127
3128 macl = gen_rtx_REG (SImode, MACL_REG);
3129 start_sequence ();
3130 emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3131 insn = get_insns ();
3132 end_sequence ();
3133 /* expand_binop can't find a suitable code in umul_widen_optab to
3134 make a REG_EQUAL note from, so make one here.
3135 See also smulsi3_highpart.
3136 ??? Alternatively, we could put this at the calling site of expand_binop,
3137 i.e. expand_expr. */
3138 /* Use emit_libcall_block for loop invariant code motion and to make
3139 a REG_EQUAL note. */
3140 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3141
3142 DONE;
3143 })
3144
3145 (define_expand "umulhisi3"
3146 [(set (reg:SI MACL_REG)
3147 (mult:SI (zero_extend:SI
3148 (match_operand:HI 1 "arith_reg_operand" ""))
3149 (zero_extend:SI
3150 (match_operand:HI 2 "arith_reg_operand" ""))))
3151 (set (match_operand:SI 0 "arith_reg_operand" "")
3152 (reg:SI MACL_REG))]
3153 "TARGET_SH1"
3154 {
3155 rtx insn, macl;
3156
3157 macl = gen_rtx_REG (SImode, MACL_REG);
3158 start_sequence ();
3159 emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3160 insn = get_insns ();
3161 end_sequence ();
3162 /* expand_binop can't find a suitable code in umul_widen_optab to
3163 make a REG_EQUAL note from, so make one here.
3164 See also smulsi3_highpart.
3165 ??? Alternatively, we could put this at the calling site of expand_binop,
3166 i.e. expand_expr. */
3167 /* Use emit_libcall_block for loop invariant code motion and to make
3168 a REG_EQUAL note. */
3169 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3170
3171 DONE;
3172 })
3173
3174 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3175 ;; a call to a routine which clobbers known registers.
3176
3177 (define_insn ""
3178 [(set (match_operand:SI 1 "register_operand" "=z")
3179 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3180 (clobber (reg:SI MACL_REG))
3181 (clobber (reg:SI T_REG))
3182 (clobber (reg:SI PR_REG))
3183 (clobber (reg:SI R3_REG))
3184 (clobber (reg:SI R2_REG))
3185 (clobber (reg:SI R1_REG))
3186 (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3187 "TARGET_SH1"
3188 "jsr @%0%#"
3189 [(set_attr "type" "sfunc")
3190 (set_attr "needs_delay_slot" "yes")])
3191
3192 (define_expand "mulsi3_call"
3193 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3194 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3195 (parallel[(set (match_operand:SI 0 "register_operand" "")
3196 (mult:SI (reg:SI R4_REG)
3197 (reg:SI R5_REG)))
3198 (clobber (reg:SI MACL_REG))
3199 (clobber (reg:SI T_REG))
3200 (clobber (reg:SI PR_REG))
3201 (clobber (reg:SI R3_REG))
3202 (clobber (reg:SI R2_REG))
3203 (clobber (reg:SI R1_REG))
3204 (use (match_operand:SI 3 "register_operand" ""))])]
3205 "TARGET_SH1"
3206 "")
3207
3208 (define_insn "mul_r"
3209 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3210 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3211 (match_operand:SI 2 "arith_reg_operand" "z")))]
3212 "TARGET_SH2A"
3213 "mulr %2,%0"
3214 [(set_attr "type" "dmpy")])
3215
3216 (define_insn "mul_l"
3217 [(set (reg:SI MACL_REG)
3218 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3219 (match_operand:SI 1 "arith_reg_operand" "r")))]
3220 "TARGET_SH2"
3221 "mul.l %1,%0"
3222 [(set_attr "type" "dmpy")])
3223
3224 (define_expand "mulsi3"
3225 [(set (reg:SI MACL_REG)
3226 (mult:SI (match_operand:SI 1 "arith_reg_operand" "")
3227 (match_operand:SI 2 "arith_reg_operand" "")))
3228 (set (match_operand:SI 0 "arith_reg_operand" "")
3229 (reg:SI MACL_REG))]
3230 "TARGET_SH1"
3231 {
3232 if (!TARGET_SH2)
3233 {
3234 /* The address must be set outside the libcall,
3235 since it goes into a pseudo. */
3236 rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
3237 rtx addr = force_reg (SImode, sym);
3238 rtx insns = gen_mulsi3_call (operands[0], operands[1],
3239 operands[2], addr);
3240 emit_insn (insns);
3241 }
3242 else
3243 {
3244 rtx macl = gen_rtx_REG (SImode, MACL_REG);
3245
3246 emit_insn (gen_mul_l (operands[1], operands[2]));
3247 /* consec_sets_giv can only recognize the first insn that sets a
3248 giv as the giv insn. So we must tag this also with a REG_EQUAL
3249 note. */
3250 emit_insn (gen_movsi_i ((operands[0]), macl));
3251 }
3252 DONE;
3253 })
3254
3255 (define_insn "mulsidi3_i"
3256 [(set (reg:SI MACH_REG)
3257 (truncate:SI
3258 (lshiftrt:DI
3259 (mult:DI
3260 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3261 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3262 (const_int 32))))
3263 (set (reg:SI MACL_REG)
3264 (mult:SI (match_dup 0)
3265 (match_dup 1)))]
3266 "TARGET_SH2"
3267 "dmuls.l %1,%0"
3268 [(set_attr "type" "dmpy")])
3269
3270 (define_expand "mulsidi3"
3271 [(set (match_operand:DI 0 "arith_reg_dest" "")
3272 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3273 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3274 "TARGET_SH2 || TARGET_SHMEDIA"
3275 {
3276 if (TARGET_SH2)
3277 {
3278 emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3279 DONE;
3280 }
3281 })
3282
3283 (define_insn "mulsidi3_media"
3284 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3285 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3286 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3287 "TARGET_SHMEDIA"
3288 "muls.l %1, %2, %0"
3289 [(set_attr "type" "dmpy_media")
3290 (set_attr "highpart" "ignore")])
3291
3292 (define_insn_and_split "mulsidi3_compact"
3293 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3294 (mult:DI
3295 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3296 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3297 (clobber (reg:SI MACH_REG))
3298 (clobber (reg:SI MACL_REG))]
3299 "TARGET_SH2"
3300 "#"
3301 "&& 1"
3302 [(const_int 0)]
3303 {
3304 rtx low_dst = gen_lowpart (SImode, operands[0]);
3305 rtx high_dst = gen_highpart (SImode, operands[0]);
3306
3307 emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3308
3309 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3310 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3311 /* We need something to tag the possible REG_EQUAL notes on to. */
3312 emit_move_insn (operands[0], operands[0]);
3313 DONE;
3314 })
3315
3316 (define_insn "umulsidi3_i"
3317 [(set (reg:SI MACH_REG)
3318 (truncate:SI
3319 (lshiftrt:DI
3320 (mult:DI
3321 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3322 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3323 (const_int 32))))
3324 (set (reg:SI MACL_REG)
3325 (mult:SI (match_dup 0)
3326 (match_dup 1)))]
3327 "TARGET_SH2"
3328 "dmulu.l %1,%0"
3329 [(set_attr "type" "dmpy")])
3330
3331 (define_expand "umulsidi3"
3332 [(set (match_operand:DI 0 "arith_reg_dest" "")
3333 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3334 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3335 "TARGET_SH2 || TARGET_SHMEDIA"
3336 {
3337 if (TARGET_SH2)
3338 {
3339 emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3340 DONE;
3341 }
3342 })
3343
3344 (define_insn "umulsidi3_media"
3345 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3346 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3347 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3348 "TARGET_SHMEDIA"
3349 "mulu.l %1, %2, %0"
3350 [(set_attr "type" "dmpy_media")
3351 (set_attr "highpart" "ignore")])
3352
3353 (define_insn_and_split "umulsidi3_compact"
3354 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3355 (mult:DI
3356 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3357 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3358 (clobber (reg:SI MACH_REG))
3359 (clobber (reg:SI MACL_REG))]
3360 "TARGET_SH2"
3361 "#"
3362 "&& 1"
3363 [(const_int 0)]
3364 {
3365 rtx low_dst = gen_lowpart (SImode, operands[0]);
3366 rtx high_dst = gen_highpart (SImode, operands[0]);
3367
3368 emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3369
3370 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3371 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3372 /* We need something to tag the possible REG_EQUAL notes on to. */
3373 emit_move_insn (operands[0], operands[0]);
3374 DONE;
3375 })
3376
3377 (define_insn "smulsi3_highpart_i"
3378 [(set (reg:SI MACH_REG)
3379 (truncate:SI
3380 (lshiftrt:DI
3381 (mult:DI
3382 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3383 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3384 (const_int 32))))
3385 (clobber (reg:SI MACL_REG))]
3386 "TARGET_SH2"
3387 "dmuls.l %1,%0"
3388 [(set_attr "type" "dmpy")])
3389
3390 (define_expand "smulsi3_highpart"
3391 [(parallel
3392 [(set (reg:SI MACH_REG)
3393 (truncate:SI
3394 (lshiftrt:DI
3395 (mult:DI
3396 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3397 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3398 (const_int 32))))
3399 (clobber (reg:SI MACL_REG))])
3400 (set (match_operand:SI 0 "arith_reg_operand" "")
3401 (reg:SI MACH_REG))]
3402 "TARGET_SH2"
3403 {
3404 rtx insn, mach;
3405
3406 mach = gen_rtx_REG (SImode, MACH_REG);
3407 start_sequence ();
3408 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3409 insn = get_insns ();
3410 end_sequence ();
3411 /* expand_binop can't find a suitable code in mul_highpart_optab to
3412 make a REG_EQUAL note from, so make one here.
3413 See also {,u}mulhisi.
3414 ??? Alternatively, we could put this at the calling site of expand_binop,
3415 i.e. expand_mult_highpart. */
3416 /* Use emit_libcall_block for loop invariant code motion and to make
3417 a REG_EQUAL note. */
3418 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3419
3420 DONE;
3421 })
3422
3423 (define_insn "umulsi3_highpart_i"
3424 [(set (reg:SI MACH_REG)
3425 (truncate:SI
3426 (lshiftrt:DI
3427 (mult:DI
3428 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3429 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3430 (const_int 32))))
3431 (clobber (reg:SI MACL_REG))]
3432 "TARGET_SH2"
3433 "dmulu.l %1,%0"
3434 [(set_attr "type" "dmpy")])
3435
3436 (define_expand "umulsi3_highpart"
3437 [(parallel
3438 [(set (reg:SI MACH_REG)
3439 (truncate:SI
3440 (lshiftrt:DI
3441 (mult:DI
3442 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3443 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3444 (const_int 32))))
3445 (clobber (reg:SI MACL_REG))])
3446 (set (match_operand:SI 0 "arith_reg_operand" "")
3447 (reg:SI MACH_REG))]
3448 "TARGET_SH2"
3449 {
3450 rtx insn, mach;
3451
3452 mach = gen_rtx_REG (SImode, MACH_REG);
3453 start_sequence ();
3454 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3455 insn = get_insns ();
3456 end_sequence ();
3457 /* Use emit_libcall_block for loop invariant code motion and to make
3458 a REG_EQUAL note. */
3459 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3460
3461 DONE;
3462 })
3463
3464 (define_insn_and_split "muldi3"
3465 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3466 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3467 (match_operand:DI 2 "arith_reg_operand" "r")))
3468 (clobber (match_scratch:DI 3 "=&r"))
3469 (clobber (match_scratch:DI 4 "=r"))]
3470 "TARGET_SHMEDIA"
3471 "#"
3472 "reload_completed"
3473 [(const_int 0)]
3474 {
3475 rtx op3_v2si, op2_v2si;
3476
3477 op3_v2si = operands[3];
3478 if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3479 {
3480 op3_v2si = XEXP (op3_v2si, 0);
3481 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3482 }
3483 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3484 op2_v2si = operands[2];
3485 if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3486 {
3487 op2_v2si = XEXP (op2_v2si, 0);
3488 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3489 }
3490 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3491 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3492 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3493 emit_insn (gen_umulsidi3_media (operands[4],
3494 sh_gen_truncate (SImode, operands[1], 0),
3495 sh_gen_truncate (SImode, operands[2], 0)));
3496 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3497 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3498 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3499 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3500 DONE;
3501 })
3502
3503 \f
3504 ;; -------------------------------------------------------------------------
3505 ;; Logical operations
3506 ;; -------------------------------------------------------------------------
3507
3508 (define_expand "andsi3"
3509 [(set (match_operand:SI 0 "arith_reg_operand" "")
3510 (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3511 (match_operand:SI 2 "logical_and_operand" "")))]
3512 ""
3513 {
3514 /* If it is possible to turn the and insn into a zero extension
3515 already, redundant zero extensions will be folded, which results
3516 in better code.
3517 Ideally the splitter of *andsi_compact would be enough, if reundant
3518 zero extensions were detected after the combine pass, which does not
3519 happen at the moment. */
3520 if (TARGET_SH1)
3521 {
3522 if (satisfies_constraint_Jmb (operands[2]))
3523 {
3524 emit_insn (gen_zero_extendqisi2 (operands[0],
3525 gen_lowpart (QImode, operands[1])));
3526 DONE;
3527 }
3528 else if (satisfies_constraint_Jmw (operands[2]))
3529 {
3530 emit_insn (gen_zero_extendhisi2 (operands[0],
3531 gen_lowpart (HImode, operands[1])));
3532 DONE;
3533 }
3534 }
3535 })
3536
3537 (define_insn_and_split "*andsi_compact"
3538 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
3539 (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
3540 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
3541 "TARGET_SH1"
3542 "@
3543 extu.b %1,%0
3544 extu.w %1,%0
3545 and %2,%0
3546 and %2,%0"
3547 "&& 1"
3548 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
3549 {
3550 if (satisfies_constraint_Jmb (operands[2]))
3551 operands[1] = gen_lowpart (QImode, operands[1]);
3552 else if (satisfies_constraint_Jmw (operands[2]))
3553 operands[1] = gen_lowpart (HImode, operands[1]);
3554 else
3555 FAIL;
3556 }
3557 [(set_attr "type" "arith")])
3558
3559 (define_insn "*andsi3_media"
3560 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3561 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3562 (match_operand:SI 2 "logical_operand" "r,I10")))]
3563 "TARGET_SHMEDIA"
3564 "@
3565 and %1, %2, %0
3566 andi %1, %2, %0"
3567 [(set_attr "type" "arith_media")])
3568
3569 (define_insn "*andsi3_bclr"
3570 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3571 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3572 (match_operand:SI 2 "const_int_operand" "Psz")))]
3573 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
3574 "bclr %W2,%0"
3575 [(set_attr "type" "arith")])
3576
3577 (define_insn_and_split "anddi3"
3578 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
3579 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
3580 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
3581 "TARGET_SHMEDIA"
3582 "@
3583 and %1, %2, %0
3584 andi %1, %2, %0
3585 #"
3586 "reload_completed
3587 && ! logical_operand (operands[2], DImode)"
3588 [(const_int 0)]
3589 {
3590 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
3591 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
3592 else
3593 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
3594 DONE;
3595 }
3596 [(set_attr "type" "arith_media")])
3597
3598 (define_insn "andcsi3"
3599 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3600 (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
3601 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
3602 "TARGET_SHMEDIA"
3603 "andc %1,%2,%0"
3604 [(set_attr "type" "arith_media")])
3605
3606 (define_insn "andcdi3"
3607 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3608 (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
3609 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
3610 "TARGET_SHMEDIA"
3611 "andc %1,%2,%0"
3612 [(set_attr "type" "arith_media")])
3613
3614 (define_expand "iorsi3"
3615 [(set (match_operand:SI 0 "arith_reg_operand" "")
3616 (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
3617 (match_operand:SI 2 "logical_operand" "")))]
3618 ""
3619 "")
3620
3621 (define_insn "*iorsi3_compact"
3622 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
3623 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3624 (match_operand:SI 2 "logical_operand" "r,K08")))]
3625 "TARGET_SH1
3626 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
3627 "or %2,%0"
3628 [(set_attr "type" "arith")])
3629
3630 (define_insn "*iorsi3_media"
3631 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3632 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3633 (match_operand:SI 2 "logical_operand" "r,I10")))]
3634 "TARGET_SHMEDIA"
3635 "@
3636 or %1, %2, %0
3637 ori %1, %2, %0"
3638 [(set_attr "type" "arith_media")])
3639
3640 (define_insn "*iorsi3_bset"
3641 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3642 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
3643 (match_operand:SI 2 "const_int_operand" "Pso")))]
3644 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
3645 "bset %V2,%0"
3646 [(set_attr "type" "arith")])
3647
3648 (define_insn "iordi3"
3649 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3650 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3651 (match_operand:DI 2 "logical_operand" "r,I10")))]
3652 "TARGET_SHMEDIA"
3653 "@
3654 or %1, %2, %0
3655 ori %1, %2, %0"
3656 [(set_attr "type" "arith_media")])
3657
3658 (define_insn_and_split "*logical_sidi3"
3659 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3660 (sign_extend:DI (match_operator:SI 3 "logical_operator"
3661 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3662 (match_operand:SI 2 "logical_operand" "r,I10")])))]
3663 "TARGET_SHMEDIA"
3664 "#"
3665 "&& reload_completed"
3666 [(set (match_dup 0) (match_dup 3))]
3667 {
3668 operands[3]
3669 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
3670 simplify_gen_subreg (DImode, operands[1], SImode, 0),
3671 simplify_gen_subreg (DImode, operands[2], SImode, 0));
3672 })
3673
3674 (define_insn_and_split "*logical_sidisi3"
3675 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3676 (truncate:SI (sign_extend:DI
3677 (match_operator:SI 3 "logical_operator"
3678 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3679 (match_operand:SI 2 "logical_operand" "r,I10")]))))]
3680 "TARGET_SHMEDIA"
3681 "#"
3682 "&& 1"
3683 [(set (match_dup 0) (match_dup 3))])
3684
3685 (define_insn_and_split "*logical_sidi3_2"
3686 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3687 (sign_extend:DI (truncate:SI (sign_extend:DI
3688 (match_operator:SI 3 "logical_operator"
3689 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
3690 (match_operand:SI 2 "logical_operand" "r,I10")])))))]
3691 "TARGET_SHMEDIA"
3692 "#"
3693 "&& 1"
3694 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
3695
3696 (define_expand "xorsi3"
3697 [(set (match_operand:SI 0 "arith_reg_operand" "")
3698 (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
3699 (match_operand:SI 2 "xor_operand" "")))]
3700 ""
3701 "")
3702
3703 (define_insn "*xorsi3_compact"
3704 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
3705 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
3706 (match_operand:SI 2 "logical_operand" "K08,r")))]
3707 "TARGET_SH1"
3708 "xor %2,%0"
3709 [(set_attr "type" "arith")])
3710
3711 ;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
3712 ;; of results where one of the inputs is a T bit store. Notice that this
3713 ;; pattern must not match during reload. If reload picks this pattern it
3714 ;; will be impossible to split it afterwards.
3715 (define_insn_and_split "*logical_op_t"
3716 [(set (match_operand:SI 0 "arith_reg_dest")
3717 (match_operator:SI 3 "logical_operator"
3718 [(match_operand:SI 1 "arith_reg_operand")
3719 (match_operand:SI 2 "t_reg_operand")]))]
3720 "TARGET_SH1 && can_create_pseudo_p ()"
3721 "#"
3722 "&& 1"
3723 [(set (match_dup 4) (reg:SI T_REG))
3724 (set (match_dup 0) (match_dup 3))]
3725 {
3726 operands[4] = gen_reg_rtx (SImode);
3727 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
3728 operands[1], operands[4]);
3729 })
3730
3731 (define_insn "*xorsi3_media"
3732 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
3733 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
3734 (match_operand:SI 2 "xor_operand" "r,I06")))]
3735 "TARGET_SHMEDIA"
3736 "@
3737 xor %1, %2, %0
3738 xori %1, %2, %0"
3739 [(set_attr "type" "arith_media")])
3740
3741 (define_insn "xordi3"
3742 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
3743 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
3744 (match_operand:DI 2 "xor_operand" "r,I06")))]
3745 "TARGET_SHMEDIA"
3746 "@
3747 xor %1, %2, %0
3748 xori %1, %2, %0"
3749 [(set_attr "type" "arith_media")])
3750
3751 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
3752 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
3753 (define_split
3754 [(set (match_operand:DI 0 "arith_reg_dest" "")
3755 (sign_extend:DI (match_operator 4 "binary_logical_operator"
3756 [(match_operand 1 "any_register_operand" "")
3757 (match_operand 2 "any_register_operand" "")])))]
3758 "TARGET_SHMEDIA"
3759 [(set (match_dup 5) (match_dup 4))
3760 (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
3761 {
3762 enum machine_mode inmode = GET_MODE (operands[1]);
3763 int offset = 0;
3764
3765 if (GET_CODE (operands[0]) == SUBREG)
3766 {
3767 offset = SUBREG_BYTE (operands[0]);
3768 operands[0] = SUBREG_REG (operands[0]);
3769 }
3770 gcc_assert (REG_P (operands[0]));
3771 if (! TARGET_LITTLE_ENDIAN)
3772 offset += 8 - GET_MODE_SIZE (inmode);
3773 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
3774 })
3775 \f
3776 ;; -------------------------------------------------------------------------
3777 ;; Shifts and rotates
3778 ;; -------------------------------------------------------------------------
3779
3780 (define_expand "rotldi3"
3781 [(set (match_operand:DI 0 "arith_reg_dest" "")
3782 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
3783 (match_operand:HI 2 "mextr_bit_offset" "")))]
3784 "TARGET_SHMEDIA"
3785 {
3786 if (! mextr_bit_offset (operands[2], HImode))
3787 FAIL;
3788 })
3789
3790 (define_insn "rotldi3_mextr"
3791 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3792 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
3793 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3794 "TARGET_SHMEDIA"
3795 {
3796 static char templ[16];
3797 sprintf (templ, "mextr%d %%1,%%1,%%0",
3798 8 - (int) (INTVAL (operands[2]) >> 3));
3799 return templ;
3800 }
3801 [(set_attr "type" "arith_media")])
3802
3803 (define_expand "rotrdi3"
3804 [(set (match_operand:DI 0 "arith_reg_dest" "")
3805 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
3806 (match_operand:HI 2 "mextr_bit_offset" "")))]
3807 "TARGET_SHMEDIA"
3808 {
3809 if (! mextr_bit_offset (operands[2], HImode))
3810 FAIL;
3811 })
3812
3813 (define_insn "rotrdi3_mextr"
3814 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3815 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
3816 (match_operand:HI 2 "mextr_bit_offset" "i")))]
3817 "TARGET_SHMEDIA"
3818 {
3819 static char templ[16];
3820 sprintf (templ, "mextr%d %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
3821 return templ;
3822 }
3823 [(set_attr "type" "arith_media")])
3824
3825 (define_split
3826 [(set (match_operand:DI 0 "arith_reg_dest" "")
3827 (ior:DI (zero_extend:DI (mem:QI (match_operand 1
3828 "ua_address_operand" "")))
3829 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
3830 (const_int 8))))
3831 (clobber (match_operand:DI 3 "register_operand" ""))]
3832 "TARGET_SHMEDIA"
3833 [(match_dup 4) (match_dup 5)]
3834 {
3835 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
3836 (operands[3], operands[1]));
3837 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
3838 GEN_INT (56), GEN_INT (8));
3839 })
3840
3841 (define_expand "rotrsi3"
3842 [(set (match_operand:SI 0 "arith_reg_dest")
3843 (rotatert:SI (match_operand:SI 1 "arith_reg_operand")
3844 (match_operand:SI 2 "const_int_operand")))]
3845 "TARGET_SH1"
3846 {
3847 HOST_WIDE_INT ival = INTVAL (operands[2]);
3848 if (ival == 1)
3849 {
3850 emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
3851 DONE;
3852 }
3853
3854 FAIL;
3855 })
3856
3857 (define_insn "rotrsi3_1"
3858 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3859 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3860 (const_int 1)))
3861 (set (reg:SI T_REG)
3862 (and:SI (match_dup 1) (const_int 1)))]
3863 "TARGET_SH1"
3864 "rotr %0"
3865 [(set_attr "type" "arith")])
3866
3867 ;; A slimplified version of rotr for combine.
3868 (define_insn "*rotrsi3_1"
3869 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3870 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
3871 (const_int 1)))
3872 (clobber (reg:SI T_REG))]
3873 "TARGET_SH1"
3874 "rotr %0"
3875 [(set_attr "type" "arith")])
3876
3877 (define_insn "rotlsi3_1"
3878 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3879 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3880 (const_int 1)))
3881 (set (reg:SI T_REG)
3882 (lshiftrt:SI (match_dup 1) (const_int 31)))]
3883 "TARGET_SH1"
3884 "rotl %0"
3885 [(set_attr "type" "arith")])
3886
3887 ;; A simplified version of rotl for combine.
3888 (define_insn "*rotlsi3_1"
3889 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3890 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3891 (const_int 1)))
3892 (clobber (reg:SI T_REG))]
3893 "TARGET_SH1"
3894 "rotl %0"
3895 [(set_attr "type" "arith")])
3896
3897 (define_insn "rotlsi3_31"
3898 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3899 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
3900 (const_int 31)))
3901 (clobber (reg:SI T_REG))]
3902 "TARGET_SH1"
3903 "rotr %0"
3904 [(set_attr "type" "arith")])
3905
3906 (define_insn "rotlsi3_16"
3907 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3908 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
3909 (const_int 16)))]
3910 "TARGET_SH1"
3911 "swap.w %1,%0"
3912 [(set_attr "type" "arith")])
3913
3914 (define_expand "rotlsi3"
3915 [(set (match_operand:SI 0 "arith_reg_dest")
3916 (rotate:SI (match_operand:SI 1 "arith_reg_operand")
3917 (match_operand:SI 2 "const_int_operand")))]
3918 "TARGET_SH1"
3919 {
3920 static const char rot_tab[] = {
3921 000, 000, 000, 000, 000, 000, 010, 001,
3922 001, 001, 011, 013, 003, 003, 003, 003,
3923 003, 003, 003, 003, 003, 013, 012, 002,
3924 002, 002, 010, 000, 000, 000, 000, 000,
3925 };
3926
3927 int count = INTVAL (operands[2]);
3928 int choice = rot_tab[count];
3929 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
3930 FAIL;
3931 choice &= 7;
3932 switch (choice)
3933 {
3934 case 0:
3935 emit_move_insn (operands[0], operands[1]);
3936 count -= (count & 16) * 2;
3937 break;
3938 case 3:
3939 emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
3940 count -= 16;
3941 break;
3942 case 1:
3943 case 2:
3944 {
3945 rtx parts[2];
3946 parts[0] = gen_reg_rtx (SImode);
3947 parts[1] = gen_reg_rtx (SImode);
3948 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
3949 emit_move_insn (parts[choice-1], operands[1]);
3950 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
3951 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
3952 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
3953 count = (count & ~16) - 8;
3954 }
3955 }
3956
3957 for (; count > 0; count--)
3958 emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
3959 for (; count < 0; count++)
3960 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
3961
3962 DONE;
3963 })
3964
3965 (define_insn "*rotlhi3_8"
3966 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
3967 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
3968 (const_int 8)))]
3969 "TARGET_SH1"
3970 "swap.b %1,%0"
3971 [(set_attr "type" "arith")])
3972
3973 (define_expand "rotlhi3"
3974 [(set (match_operand:HI 0 "arith_reg_operand")
3975 (rotate:HI (match_operand:HI 1 "arith_reg_operand")
3976 (match_operand:HI 2 "const_int_operand")))]
3977 "TARGET_SH1"
3978 {
3979 if (INTVAL (operands[2]) != 8)
3980 FAIL;
3981 })
3982
3983 ;; The rotcr insn is used primarily in DImode right shifts (arithmetic
3984 ;; and logical). It can also be used to implement things like
3985 ;; bool t = a == b;
3986 ;; int x = (y >> 1) | (t << 31);
3987 (define_insn "rotcr"
3988 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3989 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
3990 (const_int 1))
3991 (ashift:SI (match_operand:SI 2 "t_reg_operand")
3992 (const_int 31))))
3993 (set (reg:SI T_REG)
3994 (and:SI (match_dup 1) (const_int 1)))]
3995 "TARGET_SH1"
3996 "rotcr %0"
3997 [(set_attr "type" "arith")])
3998
3999 ;; Simplified rotcr version for combine, which allows arbitrary shift
4000 ;; amounts for the reg. If the shift amount is '1' rotcr can be used
4001 ;; directly. Otherwise we have to insert a shift in between.
4002 (define_insn_and_split "*rotcr"
4003 [(set (match_operand:SI 0 "arith_reg_dest")
4004 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4005 (match_operand:SI 2 "const_int_operand"))
4006 (ashift:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4007 (const_int 31))))
4008 (clobber (reg:SI T_REG))]
4009 "TARGET_SH1"
4010 "#"
4011 "&& can_create_pseudo_p ()"
4012 [(const_int 0)]
4013 {
4014 if (INTVAL (operands[2]) > 1)
4015 {
4016 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4017 rtx prev_set_t_insn = NULL_RTX;
4018 rtx tmp_t_reg = NULL_RTX;
4019
4020 /* If we're going to emit a shift sequence that clobbers the T_REG,
4021 try to find the previous insn that sets the T_REG and emit the
4022 shift insn before that insn, to remove the T_REG dependency.
4023 If the insn that sets the T_REG cannot be found, store the T_REG
4024 in a temporary reg and restore it after the shift. */
4025 if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4026 && ! sh_dynamicalize_shift_p (shift_count))
4027 {
4028 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4029
4030 /* Skip the nott insn, which was probably inserted by the splitter
4031 of *rotcr_neg_t. Don't use one of the recog functions
4032 here during insn splitting, since that causes problems in later
4033 passes. */
4034 if (prev_set_t_insn != NULL_RTX)
4035 {
4036 rtx pat = PATTERN (prev_set_t_insn);
4037 if (GET_CODE (pat) == SET
4038 && t_reg_operand (XEXP (pat, 0), SImode)
4039 && negt_reg_operand (XEXP (pat, 1), SImode))
4040 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4041 }
4042
4043 if (! (prev_set_t_insn != NULL_RTX
4044 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4045 && ! reg_referenced_p (get_t_reg_rtx (),
4046 PATTERN (prev_set_t_insn))))
4047 {
4048 prev_set_t_insn = NULL_RTX;
4049 tmp_t_reg = gen_reg_rtx (SImode);
4050 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4051 }
4052 }
4053
4054 rtx shift_result = gen_reg_rtx (SImode);
4055 rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4056 operands[1] = shift_result;
4057
4058 /* Emit the shift insn before the insn that sets T_REG, if possible. */
4059 if (prev_set_t_insn != NULL_RTX)
4060 emit_insn_before (shift_insn, prev_set_t_insn);
4061 else
4062 emit_insn (shift_insn);
4063
4064 /* Restore T_REG if it has been saved before. */
4065 if (tmp_t_reg != NULL_RTX)
4066 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4067 }
4068
4069 /* For the rotcr insn to work, operands[3] must be in T_REG.
4070 If it is not we can get it there by shifting it right one bit.
4071 In this case T_REG is not an input for this insn, thus we don't have to
4072 pay attention as of where to insert the shlr insn. */
4073 if (! t_reg_operand (operands[3], SImode))
4074 {
4075 /* We don't care about the shifted result here, only the T_REG. */
4076 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4077 operands[3] = get_t_reg_rtx ();
4078 }
4079
4080 emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4081 DONE;
4082 })
4083
4084 ;; If combine tries the same as above but with swapped operands, split
4085 ;; it so that it will try the pattern above.
4086 (define_split
4087 [(set (match_operand:SI 0 "arith_reg_dest")
4088 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4089 (const_int 31))
4090 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4091 (match_operand:SI 3 "const_int_operand"))))]
4092 "TARGET_SH1 && can_create_pseudo_p ()"
4093 [(parallel [(set (match_dup 0)
4094 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4095 (ashift:SI (match_dup 1) (const_int 31))))
4096 (clobber (reg:SI T_REG))])])
4097
4098 ;; rotcr combine bridge pattern which will make combine try out more
4099 ;; complex patterns.
4100 (define_insn_and_split "*rotcr"
4101 [(set (match_operand:SI 0 "arith_reg_dest")
4102 (ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
4103 "TARGET_SH1"
4104 "#"
4105 "&& 1"
4106 [(set (match_dup 0) (match_dup 1))
4107 (parallel [(set (match_dup 0)
4108 (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
4109 (ashift:SI (match_dup 1) (const_int 31))))
4110 (set (reg:SI T_REG)
4111 (and:SI (match_dup 0) (const_int 1)))])])
4112
4113 (define_insn_and_split "*rotcr"
4114 [(set (match_operand:SI 0 "arith_reg_dest")
4115 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4116 (const_int -2147483648)) ;; 0xffffffff80000000
4117 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4118 (const_int 1))))
4119 (clobber (reg:SI T_REG))]
4120 "TARGET_SH1"
4121 "#"
4122 "&& can_create_pseudo_p ()"
4123 [(const_int 0)]
4124 {
4125 rtx tmp = gen_reg_rtx (SImode);
4126 emit_insn (gen_shll (tmp, operands[1]));
4127 emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4128 DONE;
4129 })
4130
4131 ;; rotcr combine patterns for rotating in the negated T_REG value.
4132 (define_insn_and_split "*rotcr_neg_t"
4133 [(set (match_operand:SI 0 "arith_reg_dest")
4134 (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4135 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4136 (match_operand:SI 3 "const_int_operand"))))
4137 (clobber (reg:SI T_REG))]
4138 "TARGET_SH1"
4139 "#"
4140 "&& can_create_pseudo_p ()"
4141 [(parallel [(set (match_dup 0)
4142 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4143 (ashift:SI (reg:SI T_REG) (const_int 31))))
4144 (clobber (reg:SI T_REG))])]
4145 {
4146 emit_insn (gen_nott (get_t_reg_rtx ()));
4147 })
4148
4149 (define_insn_and_split "*rotcr_neg_t"
4150 [(set (match_operand:SI 0 "arith_reg_dest")
4151 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4152 (match_operand:SI 2 "const_int_operand"))
4153 (match_operand:SI 3 "negt_reg_shl31_operand")))
4154 (clobber (reg:SI T_REG))]
4155 "TARGET_SH1"
4156 "#"
4157 "&& can_create_pseudo_p ()"
4158 [(parallel [(set (match_dup 0)
4159 (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4160 (ashift:SI (reg:SI T_REG) (const_int 31))))
4161 (clobber (reg:SI T_REG))])]
4162 {
4163 emit_insn (gen_nott (get_t_reg_rtx ()));
4164 })
4165
4166 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4167 ;; SImode shift left
4168
4169 (define_expand "ashlsi3"
4170 [(set (match_operand:SI 0 "arith_reg_operand" "")
4171 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4172 (match_operand:SI 2 "shift_count_operand" "")))]
4173 ""
4174 {
4175 if (TARGET_SHMEDIA)
4176 {
4177 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4178 DONE;
4179 }
4180 if (TARGET_DYNSHIFT
4181 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4182 operands[2] = force_reg (SImode, operands[2]);
4183
4184 /* If the ashlsi3_* insn is going to clobber the T_REG it must be
4185 expanded here. */
4186 if (CONST_INT_P (operands[2])
4187 && sh_ashlsi_clobbers_t_reg_p (operands[2])
4188 && ! sh_dynamicalize_shift_p (operands[2]))
4189 {
4190 emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4191 operands[2]));
4192 DONE;
4193 }
4194
4195 /* Expand a library call for the dynamic shift. */
4196 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4197 {
4198 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4199 rtx funcaddr = gen_reg_rtx (Pmode);
4200 function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4201 emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4202
4203 DONE;
4204 }
4205 })
4206
4207 (define_insn "ashlsi3_k"
4208 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4209 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4210 (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4211 "TARGET_SH1"
4212 "@
4213 add %0,%0
4214 shll%O2 %0"
4215 [(set_attr "type" "arith")])
4216
4217 (define_insn_and_split "ashlsi3_d"
4218 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4219 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4220 (match_operand:SI 2 "shift_count_operand" "r")))]
4221 "TARGET_DYNSHIFT"
4222 "shld %2,%0"
4223 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4224 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4225 [(const_int 0)]
4226 {
4227 if (satisfies_constraint_P27 (operands[2]))
4228 {
4229 emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
4230 DONE;
4231 }
4232 else if (! satisfies_constraint_P27 (operands[2]))
4233 {
4234 /* This must happen before reload, otherwise the constant will be moved
4235 into a register due to the "r" constraint, after which this split
4236 cannot be done anymore.
4237 Unfortunately the move insn will not always be eliminated.
4238 Also, here we must not create a shift sequence that clobbers the
4239 T_REG. */
4240 emit_move_insn (operands[0], operands[1]);
4241 gen_shifty_op (ASHIFT, operands);
4242 DONE;
4243 }
4244
4245 FAIL;
4246 }
4247 [(set_attr "type" "dyn_shift")])
4248
4249 ;; If dynamic shifts are not available use a library function.
4250 ;; By specifying the pattern we reduce the number of call clobbered regs.
4251 ;; In order to make combine understand the truncation of the shift amount
4252 ;; operand we have to allow it to use pseudo regs for the shift operands.
4253 (define_insn "ashlsi3_d_call"
4254 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4255 (ashift:SI (reg:SI R4_REG)
4256 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4257 (const_int 31))))
4258 (use (match_operand:SI 2 "arith_reg_operand" "r"))
4259 (clobber (reg:SI T_REG))
4260 (clobber (reg:SI PR_REG))]
4261 "TARGET_SH1 && !TARGET_DYNSHIFT"
4262 "jsr @%2%#"
4263 [(set_attr "type" "sfunc")
4264 (set_attr "needs_delay_slot" "yes")])
4265
4266 (define_insn_and_split "ashlsi3_n"
4267 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4268 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4269 (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
4270 "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4271 "#"
4272 "&& (reload_completed
4273 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4274 [(const_int 0)]
4275 {
4276 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4277 {
4278 /* If this pattern was picked and dynamic shifts are supported, switch
4279 to dynamic shift pattern before reload. */
4280 operands[2] = force_reg (SImode, operands[2]);
4281 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4282 }
4283 else
4284 gen_shifty_op (ASHIFT, operands);
4285
4286 DONE;
4287 })
4288
4289 (define_insn_and_split "ashlsi3_n_clobbers_t"
4290 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4291 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4292 (match_operand:SI 2 "not_p27_shift_count_operand" "")))
4293 (clobber (reg:SI T_REG))]
4294 "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
4295 "#"
4296 "&& (reload_completed || INTVAL (operands[2]) == 31
4297 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4298 [(const_int 0)]
4299 {
4300 if (INTVAL (operands[2]) == 31)
4301 {
4302 /* If the shift amount is 31 we split into a different sequence before
4303 reload so that it gets a chance to allocate R0 for the sequence.
4304 If it fails to do so (due to pressure on R0), it will take one insn
4305 more for the and. */
4306 emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
4307 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4308 }
4309 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4310 {
4311 /* If this pattern was picked and dynamic shifts are supported, switch
4312 to dynamic shift pattern before reload. */
4313 operands[2] = force_reg (SImode, operands[2]);
4314 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
4315 }
4316 else
4317 gen_shifty_op (ASHIFT, operands);
4318
4319 DONE;
4320 })
4321
4322 (define_insn "shll"
4323 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4324 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
4325 (set (reg:SI T_REG)
4326 (lt:SI (match_dup 1) (const_int 0)))]
4327 "TARGET_SH1"
4328 "shll %0"
4329 [(set_attr "type" "arith")])
4330
4331 (define_insn "*ashlsi_c_void"
4332 [(set (reg:SI T_REG)
4333 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
4334 (clobber (match_scratch:SI 1 "=0"))]
4335 "TARGET_SH1 && cse_not_expected"
4336 "shll %0"
4337 [(set_attr "type" "arith")])
4338
4339 (define_peephole2
4340 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
4341 (set (reg:SI T_REG)
4342 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
4343 "TARGET_SH1
4344 && peep2_reg_dead_p (2, operands[0])
4345 && peep2_reg_dead_p (2, operands[1])"
4346 [(const_int 0)]
4347 {
4348 emit_insn (gen_shll (operands[1], operands[1]));
4349 DONE;
4350 })
4351
4352 (define_insn "ashlsi3_media"
4353 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4354 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4355 (match_operand:SI 2 "shift_count_operand" "r,n")))]
4356 "TARGET_SHMEDIA"
4357 "@
4358 shlld.l %1, %2, %0
4359 shlli.l %1, %2, %0"
4360 [(set_attr "type" "arith_media")
4361 (set_attr "highpart" "ignore")])
4362
4363 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4364 ;; HImode shift left
4365
4366 (define_expand "ashlhi3"
4367 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
4368 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
4369 (match_operand:SI 2 "nonmemory_operand" "")))
4370 (clobber (reg:SI T_REG))])]
4371 "TARGET_SH1"
4372 {
4373 if (!CONST_INT_P (operands[2]))
4374 FAIL;
4375 /* It may be possible to call gen_ashlhi3 directly with more generic
4376 operands. Make sure operands[1] is a HImode register here. */
4377 if (!arith_reg_operand (operands[1], HImode))
4378 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4379 })
4380
4381 (define_insn "ashlhi3_k"
4382 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
4383 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
4384 (match_operand:HI 2 "const_int_operand" "M,P27")))]
4385 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
4386 "@
4387 add %0,%0
4388 shll%O2 %0"
4389 [(set_attr "type" "arith")])
4390
4391 (define_insn_and_split "*ashlhi3_n"
4392 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4393 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
4394 (match_operand:HI 2 "const_int_operand" "n")))
4395 (clobber (reg:SI T_REG))]
4396 "TARGET_SH1"
4397 "#"
4398 "&& reload_completed"
4399 [(use (reg:SI R0_REG))]
4400 {
4401 gen_shifty_hi_op (ASHIFT, operands);
4402 DONE;
4403 })
4404
4405 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4406 ;; DImode shift left
4407
4408 (define_expand "ashldi3"
4409 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4410 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
4411 (match_operand:DI 2 "immediate_operand" "")))
4412 (clobber (reg:SI T_REG))])]
4413 ""
4414 {
4415 if (TARGET_SHMEDIA)
4416 {
4417 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
4418 DONE;
4419 }
4420 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
4421 {
4422 emit_insn (gen_ashldi3_k (operands[0], operands[1]));
4423 DONE;
4424 }
4425 else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
4426 {
4427 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
4428 DONE;
4429 }
4430 else
4431 FAIL;
4432 })
4433
4434 ;; Expander for DImode shift left with SImode operations.
4435 (define_expand "ashldi3_std"
4436 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4437 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4438 (match_operand:DI 2 "const_int_operand" "n")))]
4439 "TARGET_SH1 && INTVAL (operands[2]) < 32"
4440 {
4441 rtx low_src = gen_lowpart (SImode, operands[1]);
4442 rtx high_src = gen_highpart (SImode, operands[1]);
4443 rtx dst = gen_reg_rtx (DImode);
4444 rtx low_dst = gen_lowpart (SImode, dst);
4445 rtx high_dst = gen_highpart (SImode, dst);
4446 rtx tmp0 = gen_reg_rtx (SImode);
4447 rtx tmp1 = gen_reg_rtx (SImode);
4448
4449 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
4450 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
4451 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
4452 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
4453 emit_move_insn (operands[0], dst);
4454 DONE;
4455 })
4456
4457 ;; This should be an define_insn_and_split.
4458 (define_insn "ashldi3_k"
4459 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4460 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
4461 (const_int 1)))
4462 (clobber (reg:SI T_REG))]
4463 "TARGET_SH1"
4464 "shll %R0\;rotcl %S0"
4465 [(set_attr "length" "4")
4466 (set_attr "type" "arith")])
4467
4468 (define_insn "ashldi3_media"
4469 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4470 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4471 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4472 "TARGET_SHMEDIA"
4473 "@
4474 shlld %1, %2, %0
4475 shlli %1, %2, %0"
4476 [(set_attr "type" "arith_media")])
4477
4478 (define_insn "*ashldisi3_media"
4479 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4480 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
4481 (match_operand:DI 2 "const_int_operand" "n")))]
4482 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4483 "shlli.l %1, %2, %0"
4484 [(set_attr "type" "arith_media")
4485 (set_attr "highpart" "ignore")])
4486
4487 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4488 ;; SImode arithmetic shift right
4489 ;;
4490 ;; We can't do HImode right shifts correctly unless we start out with an
4491 ;; explicit zero / sign extension; doing that would result in worse overall
4492 ;; code, so just let the machine independent code widen the mode.
4493 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
4494
4495 (define_expand "ashrsi3"
4496 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
4497 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4498 (match_operand:SI 2 "nonmemory_operand" "")))
4499 (clobber (reg:SI T_REG))])]
4500 ""
4501 {
4502 if (TARGET_SHMEDIA)
4503 {
4504 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4505 DONE;
4506 }
4507 if (expand_ashiftrt (operands))
4508 DONE;
4509 else
4510 FAIL;
4511 })
4512
4513 (define_insn "shar"
4514 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4515 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4516 (const_int 1)))
4517 (set (reg:SI T_REG)
4518 (and:SI (match_dup 1) (const_int 1)))]
4519 "TARGET_SH1"
4520 "shar %0"
4521 [(set_attr "type" "arith")])
4522
4523 (define_insn "ashrsi3_k"
4524 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4525 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4526 (match_operand:SI 2 "const_int_operand" "M")))
4527 (clobber (reg:SI T_REG))]
4528 "TARGET_SH1 && INTVAL (operands[2]) == 1"
4529 "shar %0"
4530 [(set_attr "type" "arith")])
4531
4532 (define_insn_and_split "ashrsi2_16"
4533 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4534 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
4535 (const_int 16)))]
4536 "TARGET_SH1"
4537 "#"
4538 "&& 1"
4539 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
4540 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
4541 {
4542 operands[2] = gen_lowpart (HImode, operands[0]);
4543 })
4544
4545 (define_insn_and_split "ashrsi2_31"
4546 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4547 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4548 (const_int 31)))
4549 (clobber (reg:SI T_REG))]
4550 "TARGET_SH1"
4551 "#"
4552 "&& 1"
4553 [(const_int 0)]
4554 {
4555 emit_insn (gen_shll (operands[0], operands[1]));
4556 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
4557 DONE;
4558 })
4559
4560 (define_insn "ashrsi3_d"
4561 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4562 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4563 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4564 "TARGET_DYNSHIFT"
4565 "shad %2,%0"
4566 [(set_attr "type" "dyn_shift")])
4567
4568 (define_insn "ashrsi3_n"
4569 [(set (reg:SI R4_REG)
4570 (ashiftrt:SI (reg:SI R4_REG)
4571 (match_operand:SI 0 "const_int_operand" "i")))
4572 (clobber (reg:SI T_REG))
4573 (clobber (reg:SI PR_REG))
4574 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
4575 "TARGET_SH1"
4576 "jsr @%1%#"
4577 [(set_attr "type" "sfunc")
4578 (set_attr "needs_delay_slot" "yes")])
4579
4580 (define_insn "ashrsi3_media"
4581 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4582 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4583 (match_operand:SI 2 "shift_count_operand" "r,n")))]
4584 "TARGET_SHMEDIA"
4585 "@
4586 shard.l %1, %2, %0
4587 shari.l %1, %2, %0"
4588 [(set_attr "type" "arith_media")
4589 (set_attr "highpart" "ignore")])
4590
4591 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4592 ;; DImode arithmetic shift right
4593
4594 (define_expand "ashrdi3"
4595 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4596 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4597 (match_operand:DI 2 "immediate_operand" "")))
4598 (clobber (reg:SI T_REG))])]
4599 ""
4600 {
4601 if (TARGET_SHMEDIA)
4602 {
4603 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
4604 DONE;
4605 }
4606 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
4607 FAIL;
4608 })
4609
4610 (define_insn_and_split "ashrdi3_k"
4611 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4612 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4613 (const_int 1)))
4614 (clobber (reg:SI T_REG))]
4615 "TARGET_SH1"
4616 "#"
4617 "&& reload_completed"
4618 [(const_int 0)]
4619 {
4620 rtx high = gen_highpart (SImode, operands[0]);
4621 rtx low = gen_lowpart (SImode, operands[0]);
4622 emit_insn (gen_shar (high, high));
4623 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
4624 DONE;
4625 })
4626
4627 (define_insn "ashrdi3_media"
4628 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4629 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4630 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4631 "TARGET_SHMEDIA
4632 && (arith_reg_dest (operands[0], DImode)
4633 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
4634 "@
4635 shard %1, %2, %0
4636 shari %1, %2, %0"
4637 [(set_attr "type" "arith_media")])
4638
4639 (define_insn "*ashrdisi3_media"
4640 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4641 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4642 (match_operand:DI 2 "const_int_operand" "n")))]
4643 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4644 "shari.l %1, %2, %0"
4645 [(set_attr "type" "arith_media")
4646 (set_attr "highpart" "ignore")])
4647
4648 (define_insn "ashrdisi3_media_high"
4649 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4650 (truncate:SI
4651 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4652 (match_operand:DI 2 "const_int_operand" "n"))))]
4653 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
4654 "shari %1, %2, %0"
4655 [(set_attr "type" "arith_media")])
4656
4657 (define_insn "ashrdisi3_media_opaque"
4658 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4659 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
4660 (match_operand:DI 2 "const_int_operand" "n")]
4661 UNSPEC_ASHIFTRT))]
4662 "TARGET_SHMEDIA"
4663 "shari %1, %2, %0"
4664 [(set_attr "type" "arith_media")])
4665
4666 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4667 ;; SImode logical shift right
4668
4669 (define_expand "lshrsi3"
4670 [(set (match_operand:SI 0 "arith_reg_dest" "")
4671 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
4672 (match_operand:SI 2 "shift_count_operand" "")))]
4673 ""
4674 {
4675 if (TARGET_SHMEDIA)
4676 {
4677 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
4678 DONE;
4679 }
4680
4681 /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
4682 here, otherwise the pattern will never match due to the shift amount reg
4683 negation. */
4684 if (TARGET_DYNSHIFT
4685 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4686 {
4687 rtx neg_count = force_reg (SImode,
4688 gen_int_mode (- INTVAL (operands[2]), SImode));
4689 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
4690 DONE;
4691 }
4692
4693 if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
4694 {
4695 rtx neg_count = gen_reg_rtx (SImode);
4696 emit_insn (gen_negsi2 (neg_count, operands[2]));
4697 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
4698 DONE;
4699 }
4700
4701 /* If the lshrsi3_* insn is going to clobber the T_REG it must be
4702 expanded here. */
4703 if (CONST_INT_P (operands[2])
4704 && sh_lshrsi_clobbers_t_reg_p (operands[2])
4705 && ! sh_dynamicalize_shift_p (operands[2]))
4706 {
4707 emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
4708 operands[2]));
4709 DONE;
4710 }
4711
4712 /* Expand a library call for the dynamic shift. */
4713 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4714 {
4715 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4716 rtx funcaddr = gen_reg_rtx (Pmode);
4717 function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
4718 emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
4719 DONE;
4720 }
4721 })
4722
4723 (define_insn "lshrsi3_k"
4724 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4725 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4726 (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
4727 "TARGET_SH1"
4728 "shlr%O2 %0"
4729 [(set_attr "type" "arith")])
4730
4731 (define_insn_and_split "lshrsi3_d"
4732 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4733 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4734 (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
4735 "TARGET_DYNSHIFT"
4736 "shld %2,%0"
4737 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4738 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
4739 [(const_int 0)]
4740 {
4741 if (satisfies_constraint_P27 (operands[2]))
4742 {
4743 /* This will not be done for a shift amount of 1, because it would
4744 clobber the T_REG. */
4745 emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
4746 DONE;
4747 }
4748 else if (! satisfies_constraint_P27 (operands[2]))
4749 {
4750 /* This must happen before reload, otherwise the constant will be moved
4751 into a register due to the "r" constraint, after which this split
4752 cannot be done anymore.
4753 Unfortunately the move insn will not always be eliminated.
4754 Also, here we must not create a shift sequence that clobbers the
4755 T_REG. */
4756 emit_move_insn (operands[0], operands[1]);
4757 gen_shifty_op (LSHIFTRT, operands);
4758 DONE;
4759 }
4760
4761 FAIL;
4762 }
4763 [(set_attr "type" "dyn_shift")])
4764
4765 ;; If dynamic shifts are not available use a library function.
4766 ;; By specifying the pattern we reduce the number of call clobbered regs.
4767 ;; In order to make combine understand the truncation of the shift amount
4768 ;; operand we have to allow it to use pseudo regs for the shift operands.
4769 (define_insn "lshrsi3_d_call"
4770 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
4771 (lshiftrt:SI (reg:SI R4_REG)
4772 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
4773 (const_int 31))))
4774 (use (match_operand:SI 2 "arith_reg_operand" "r"))
4775 (clobber (reg:SI T_REG))
4776 (clobber (reg:SI PR_REG))]
4777 "TARGET_SH1 && !TARGET_DYNSHIFT"
4778 "jsr @%2%#"
4779 [(set_attr "type" "sfunc")
4780 (set_attr "needs_delay_slot" "yes")])
4781
4782 (define_insn_and_split "lshrsi3_n"
4783 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4784 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4785 (match_operand:SI 2 "not_p27_rshift_count_operand")))]
4786 "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
4787 "#"
4788 "&& (reload_completed
4789 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4790 [(const_int 0)]
4791 {
4792 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4793 {
4794 /* If this pattern was picked and dynamic shifts are supported, switch
4795 to dynamic shift pattern before reload. */
4796 operands[2] = force_reg (SImode,
4797 gen_int_mode (- INTVAL (operands[2]), SImode));
4798 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
4799 }
4800 else
4801 gen_shifty_op (LSHIFTRT, operands);
4802
4803 DONE;
4804 })
4805
4806 ;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
4807 ;; the shlr pattern.
4808 (define_insn_and_split "lshrsi3_n_clobbers_t"
4809 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4810 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4811 (match_operand:SI 2 "not_p27_rshift_count_operand")))
4812 (clobber (reg:SI T_REG))]
4813 "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
4814 "#"
4815 "&& (reload_completed || INTVAL (operands[2]) == 31
4816 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
4817 [(const_int 0)]
4818 {
4819 if (INTVAL (operands[2]) == 31)
4820 {
4821 emit_insn (gen_shll (operands[0], operands[1]));
4822 emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
4823 }
4824 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
4825 {
4826 /* If this pattern was picked and dynamic shifts are supported, switch
4827 to dynamic shift pattern before reload. */
4828 operands[2] = force_reg (SImode,
4829 gen_int_mode (- INTVAL (operands[2]), SImode));
4830 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
4831 }
4832 else
4833 gen_shifty_op (LSHIFTRT, operands);
4834
4835 DONE;
4836 })
4837
4838 (define_insn "shlr"
4839 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4840 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4841 (const_int 1)))
4842 (set (reg:SI T_REG)
4843 (and:SI (match_dup 1) (const_int 1)))]
4844 "TARGET_SH1"
4845 "shlr %0"
4846 [(set_attr "type" "arith")])
4847
4848 (define_insn "lshrsi3_media"
4849 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4850 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
4851 (match_operand:SI 2 "shift_count_operand" "r,n")))]
4852 "TARGET_SHMEDIA"
4853 "@
4854 shlrd.l %1, %2, %0
4855 shlri.l %1, %2, %0"
4856 [(set_attr "type" "arith_media")
4857 (set_attr "highpart" "ignore")])
4858
4859 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4860 ;; DImode logical shift right
4861
4862 (define_expand "lshrdi3"
4863 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
4864 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
4865 (match_operand:DI 2 "immediate_operand" "")))
4866 (clobber (reg:SI T_REG))])]
4867 ""
4868 {
4869 if (TARGET_SHMEDIA)
4870 {
4871 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
4872 DONE;
4873 }
4874 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
4875 FAIL;
4876 })
4877
4878 (define_insn_and_split "lshrdi3_k"
4879 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4880 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
4881 (const_int 1)))
4882 (clobber (reg:SI T_REG))]
4883 "TARGET_SH1"
4884 "#"
4885 "&& reload_completed"
4886 [(const_int 0)]
4887 {
4888 rtx high = gen_highpart (SImode, operands[0]);
4889 rtx low = gen_lowpart (SImode, operands[0]);
4890 emit_insn (gen_shlr (high, high));
4891 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
4892 DONE;
4893 })
4894
4895 (define_insn "lshrdi3_media"
4896 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
4897 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
4898 (match_operand:DI 2 "shift_count_operand" "r,n")))]
4899 "TARGET_SHMEDIA
4900 && (arith_reg_dest (operands[0], DImode)
4901 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
4902 "@
4903 shlrd %1, %2, %0
4904 shlri %1, %2, %0"
4905 [(set_attr "type" "arith_media")])
4906
4907 (define_insn "*lshrdisi3_media"
4908 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
4909 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
4910 (match_operand:DI 2 "const_int_operand" "n")))]
4911 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
4912 "shlri.l %1, %2, %0"
4913 [(set_attr "type" "arith_media")
4914 (set_attr "highpart" "ignore")])
4915
4916 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4917 ;; Combined left/right shifts
4918
4919 (define_split
4920 [(set (match_operand:SI 0 "register_operand" "")
4921 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4922 (match_operand:SI 2 "const_int_operand" ""))
4923 (match_operand:SI 3 "const_int_operand" "")))]
4924 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4925 [(use (reg:SI R0_REG))]
4926 {
4927 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
4928 FAIL;
4929 DONE;
4930 })
4931
4932 (define_split
4933 [(set (match_operand:SI 0 "register_operand" "")
4934 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
4935 (match_operand:SI 2 "const_int_operand" ""))
4936 (match_operand:SI 3 "const_int_operand" "")))
4937 (clobber (reg:SI T_REG))]
4938 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
4939 [(use (reg:SI R0_REG))]
4940 {
4941 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
4942 FAIL;
4943 DONE;
4944 })
4945
4946 (define_insn ""
4947 [(set (match_operand:SI 0 "register_operand" "=r")
4948 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4949 (match_operand:SI 2 "const_int_operand" "n"))
4950 (match_operand:SI 3 "const_int_operand" "n")))
4951 (clobber (reg:SI T_REG))]
4952 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
4953 "#"
4954 [(set (attr "length")
4955 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4956 (const_string "4")
4957 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4958 (const_string "6")
4959 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4960 (const_string "8")
4961 (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
4962 (const_string "10")
4963 (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
4964 (const_string "12")
4965 (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
4966 (const_string "14")
4967 (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
4968 (const_string "16")]
4969 (const_string "18")))
4970 (set_attr "type" "arith")])
4971
4972 (define_insn ""
4973 [(set (match_operand:SI 0 "register_operand" "=z")
4974 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
4975 (match_operand:SI 2 "const_int_operand" "n"))
4976 (match_operand:SI 3 "const_int_operand" "n")))
4977 (clobber (reg:SI T_REG))]
4978 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
4979 "#"
4980 [(set (attr "length")
4981 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
4982 (const_string "4")
4983 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
4984 (const_string "6")
4985 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
4986 (const_string "8")]
4987 (const_string "10")))
4988 (set_attr "type" "arith")])
4989
4990 ;; shift left / and combination with a scratch register: The combine pass
4991 ;; does not accept the individual instructions, even though they are
4992 ;; cheap. But it needs a precise description so that it is usable after
4993 ;; reload.
4994 (define_insn "and_shl_scratch"
4995 [(set (match_operand:SI 0 "register_operand" "=r,&r")
4996 (lshiftrt:SI
4997 (ashift:SI
4998 (and:SI
4999 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5000 (match_operand:SI 2 "const_int_operand" "N,n"))
5001 (match_operand:SI 3 "" "0,r"))
5002 (match_operand:SI 4 "const_int_operand" "n,n"))
5003 (match_operand:SI 5 "const_int_operand" "n,n")))
5004 (clobber (reg:SI T_REG))]
5005 "TARGET_SH1"
5006 "#"
5007 [(set (attr "length")
5008 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5009 (const_string "4")
5010 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5011 (const_string "6")
5012 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5013 (const_string "8")
5014 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5015 (const_string "10")]
5016 (const_string "12")))
5017 (set_attr "type" "arith")])
5018
5019 (define_split
5020 [(set (match_operand:SI 0 "register_operand" "")
5021 (lshiftrt:SI
5022 (ashift:SI
5023 (and:SI
5024 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5025 (match_operand:SI 2 "const_int_operand" ""))
5026 (match_operand:SI 3 "register_operand" ""))
5027 (match_operand:SI 4 "const_int_operand" ""))
5028 (match_operand:SI 5 "const_int_operand" "")))
5029 (clobber (reg:SI T_REG))]
5030 "TARGET_SH1"
5031 [(use (reg:SI R0_REG))]
5032 {
5033 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5034
5035 if (INTVAL (operands[2]))
5036 {
5037 gen_shifty_op (LSHIFTRT, operands);
5038 }
5039 emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5040 operands[2] = operands[4];
5041 gen_shifty_op (ASHIFT, operands);
5042 if (INTVAL (operands[5]))
5043 {
5044 operands[2] = operands[5];
5045 gen_shifty_op (LSHIFTRT, operands);
5046 }
5047 DONE;
5048 })
5049
5050 ;; signed left/right shift combination.
5051 (define_split
5052 [(set (match_operand:SI 0 "register_operand" "")
5053 (sign_extract:SI
5054 (ashift:SI (match_operand:SI 1 "register_operand" "")
5055 (match_operand:SI 2 "const_int_operand" ""))
5056 (match_operand:SI 3 "const_int_operand" "")
5057 (const_int 0)))
5058 (clobber (reg:SI T_REG))]
5059 "TARGET_SH1"
5060 [(use (reg:SI R0_REG))]
5061 {
5062 if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5063 FAIL;
5064 DONE;
5065 })
5066
5067 (define_insn "shl_sext_ext"
5068 [(set (match_operand:SI 0 "register_operand" "=r")
5069 (sign_extract:SI
5070 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5071 (match_operand:SI 2 "const_int_operand" "n"))
5072 (match_operand:SI 3 "const_int_operand" "n")
5073 (const_int 0)))
5074 (clobber (reg:SI T_REG))]
5075 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5076 "#"
5077 [(set (attr "length")
5078 (cond [(match_test "shl_sext_length (insn)")
5079 (const_string "2")
5080 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5081 (const_string "4")
5082 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5083 (const_string "6")
5084 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5085 (const_string "8")
5086 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5087 (const_string "10")
5088 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5089 (const_string "12")
5090 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5091 (const_string "14")
5092 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5093 (const_string "16")]
5094 (const_string "18")))
5095 (set_attr "type" "arith")])
5096
5097 (define_insn "shl_sext_sub"
5098 [(set (match_operand:SI 0 "register_operand" "=z")
5099 (sign_extract:SI
5100 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5101 (match_operand:SI 2 "const_int_operand" "n"))
5102 (match_operand:SI 3 "const_int_operand" "n")
5103 (const_int 0)))
5104 (clobber (reg:SI T_REG))]
5105 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
5106 "#"
5107 [(set (attr "length")
5108 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5109 (const_string "6")
5110 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5111 (const_string "8")
5112 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5113 (const_string "10")
5114 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5115 (const_string "12")]
5116 (const_string "14")))
5117 (set_attr "type" "arith")])
5118
5119 ;; These patterns are found in expansions of DImode shifts by 16, and
5120 ;; allow the xtrct instruction to be generated from C source.
5121
5122 (define_insn "xtrct_left"
5123 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5124 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5125 (const_int 16))
5126 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5127 (const_int 16))))]
5128 "TARGET_SH1"
5129 "xtrct %1,%0"
5130 [(set_attr "type" "arith")])
5131
5132 (define_insn "xtrct_right"
5133 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5134 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5135 (const_int 16))
5136 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5137 (const_int 16))))]
5138 "TARGET_SH1"
5139 "xtrct %2,%0"
5140 [(set_attr "type" "arith")])
5141
5142 ;; -------------------------------------------------------------------------
5143 ;; Unary arithmetic
5144 ;; -------------------------------------------------------------------------
5145
5146 (define_insn "negc"
5147 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5148 (neg:SI (plus:SI (reg:SI T_REG)
5149 (match_operand:SI 1 "arith_reg_operand" "r"))))
5150 (set (reg:SI T_REG)
5151 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
5152 (const_int 0)))]
5153 "TARGET_SH1"
5154 "negc %1,%0"
5155 [(set_attr "type" "arith")])
5156
5157 ;; A simplified version of the negc insn, where the exact value of the
5158 ;; T bit doesn't matter. This is easier for combine to pick up.
5159 ;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5160 ;; extra patterns for this case.
5161 (define_insn "*negc"
5162 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5163 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5164 (match_operand:SI 2 "t_reg_operand" "")))
5165 (clobber (reg:SI T_REG))]
5166 "TARGET_SH1"
5167 "negc %1,%0"
5168 [(set_attr "type" "arith")])
5169
5170 (define_insn "*negdi_media"
5171 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5172 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5173 "TARGET_SHMEDIA"
5174 "sub r63, %1, %0"
5175 [(set_attr "type" "arith_media")])
5176
5177 ;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
5178 ;; combined.
5179 (define_expand "negdi2"
5180 [(set (match_operand:DI 0 "arith_reg_dest" "")
5181 (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
5182 (clobber (reg:SI T_REG))]
5183 "TARGET_SH1"
5184 "")
5185
5186 (define_insn_and_split "*negdi2"
5187 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5188 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5189 "TARGET_SH1"
5190 "#"
5191 "TARGET_SH1"
5192 [(const_int 0)]
5193 {
5194 rtx low_src = gen_lowpart (SImode, operands[1]);
5195 rtx high_src = gen_highpart (SImode, operands[1]);
5196 rtx low_dst = gen_lowpart (SImode, operands[0]);
5197 rtx high_dst = gen_highpart (SImode, operands[0]);
5198
5199 emit_insn (gen_clrt ());
5200 emit_insn (gen_negc (low_dst, low_src));
5201 emit_insn (gen_negc (high_dst, high_src));
5202 DONE;
5203 })
5204
5205 (define_insn "negsi2"
5206 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5207 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5208 "TARGET_SH1"
5209 "neg %1,%0"
5210 [(set_attr "type" "arith")])
5211
5212 (define_insn_and_split "one_cmplsi2"
5213 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5214 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5215 "TARGET_SH1"
5216 "not %1,%0"
5217 "&& can_create_pseudo_p ()"
5218 [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
5219 (set (match_dup 0) (reg:SI T_REG))]
5220 {
5221 /* PR 54685
5222 If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
5223 sequence:
5224
5225 (set (reg0) (not:SI (reg0) (reg1)))
5226 (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
5227 (clobber (reg:SI T_REG))])
5228
5229 ... match and combine the sequence manually in the split pass after the
5230 combine pass. Notice that combine does try the target pattern of this
5231 split, but if the pattern is added it interferes with other patterns, in
5232 particular with the div0s comparisons.
5233 This could also be done with a peephole but doing it here before register
5234 allocation can save one temporary.
5235 When we're here, the not:SI pattern obviously has been matched already
5236 and we only have to see whether the following insn is the left shift. */
5237
5238 rtx i = next_nonnote_insn_bb (curr_insn);
5239 if (i == NULL_RTX || !NONJUMP_INSN_P (i))
5240 FAIL;
5241
5242 rtx p = PATTERN (i);
5243 if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
5244 FAIL;
5245
5246 rtx p0 = XVECEXP (p, 0, 0);
5247 rtx p1 = XVECEXP (p, 0, 1);
5248
5249 if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */
5250 GET_CODE (p0) == SET
5251 && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
5252 && REG_P (XEXP (XEXP (p0, 1), 0))
5253 && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
5254 && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
5255 && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
5256
5257 /* (clobber (reg:SI T_REG)) */
5258 && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
5259 && REGNO (XEXP (p1, 0)) == T_REG)
5260 {
5261 operands[0] = XEXP (p0, 0);
5262 set_insn_deleted (i);
5263 }
5264 else
5265 FAIL;
5266 }
5267 [(set_attr "type" "arith")])
5268
5269 (define_expand "one_cmpldi2"
5270 [(set (match_operand:DI 0 "arith_reg_dest" "")
5271 (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
5272 (const_int -1)))]
5273 "TARGET_SHMEDIA" "")
5274
5275 (define_expand "abssi2"
5276 [(set (match_operand:SI 0 "arith_reg_dest" "")
5277 (abs:SI (match_operand:SI 1 "arith_reg_operand" "")))
5278 (clobber (reg:SI T_REG))]
5279 "TARGET_SH1"
5280 "")
5281
5282 (define_insn_and_split "*abssi2"
5283 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5284 (abs:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
5285 "TARGET_SH1"
5286 "#"
5287 "TARGET_SH1"
5288 [(const_int 0)]
5289 {
5290 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5291 emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
5292 const1_rtx));
5293 DONE;
5294 })
5295
5296 (define_insn_and_split "*negabssi2"
5297 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5298 (neg:SI (abs:SI (match_operand:SI 1 "arith_reg_operand" "r"))))]
5299 "TARGET_SH1"
5300 "#"
5301 "TARGET_SH1"
5302 [(const_int 0)]
5303 {
5304 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
5305 emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
5306 const0_rtx));
5307 DONE;
5308 })
5309
5310 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
5311 ;; This can be used as some kind of conditional execution, which is useful
5312 ;; for abs.
5313 ;; Actually the instruction scheduling should decide whether to use a
5314 ;; zero-offset branch or not for any generic case involving a single
5315 ;; instruction on SH4 202.
5316
5317 (define_insn_and_split "negsi_cond"
5318 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5319 (if_then_else:SI (eq:SI (reg:SI T_REG)
5320 (match_operand:SI 3 "const_int_operand" "M,N"))
5321 (match_operand:SI 1 "arith_reg_operand" "0,0")
5322 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
5323 "TARGET_SH1 && TARGET_ZDCBRANCH"
5324 {
5325 static const char* alt[] =
5326 {
5327 "bt 0f" "\n"
5328 " neg %2,%0" "\n"
5329 "0:",
5330
5331 "bf 0f" "\n"
5332 " neg %2,%0" "\n"
5333 "0:"
5334 };
5335 return alt[which_alternative];
5336 }
5337 "TARGET_SH1 && ! TARGET_ZDCBRANCH"
5338 [(const_int 0)]
5339 {
5340 rtx skip_neg_label = gen_label_rtx ();
5341
5342 emit_insn (gen_movsi (operands[0], operands[1]));
5343
5344 emit_jump_insn (INTVAL (operands[3])
5345 ? gen_branch_true (skip_neg_label)
5346 : gen_branch_false (skip_neg_label));
5347
5348 emit_label_after (skip_neg_label,
5349 emit_insn (gen_negsi2 (operands[0], operands[1])));
5350 DONE;
5351 }
5352 [(set_attr "type" "arith") ;; poor approximation
5353 (set_attr "length" "4")])
5354
5355 (define_expand "absdi2"
5356 [(set (match_operand:DI 0 "arith_reg_dest" "")
5357 (abs:DI (match_operand:DI 1 "arith_reg_operand" "")))
5358 (clobber (reg:SI T_REG))]
5359 "TARGET_SH1"
5360 "")
5361
5362 (define_insn_and_split "*absdi2"
5363 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5364 (abs:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
5365 "TARGET_SH1"
5366 "#"
5367 "&& reload_completed"
5368 [(const_int 0)]
5369 {
5370 rtx high_src = gen_highpart (SImode, operands[1]);
5371 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5372 emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1],
5373 const1_rtx));
5374 DONE;
5375 })
5376
5377 (define_insn_and_split "*negabsdi2"
5378 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5379 (neg:DI (abs:DI (match_operand:DI 1 "arith_reg_operand" "r"))))]
5380 "TARGET_SH1"
5381 "#"
5382 "&& reload_completed"
5383 [(const_int 0)]
5384 {
5385 rtx high_src = gen_highpart (SImode, operands[1]);
5386 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
5387 emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1],
5388 const0_rtx));
5389 DONE;
5390 })
5391
5392 (define_insn_and_split "negdi_cond"
5393 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
5394 (if_then_else:DI (eq:SI (reg:SI T_REG)
5395 (match_operand:SI 3 "const_int_operand" "M,N"))
5396 (match_operand:DI 1 "arith_reg_operand" "r,r")
5397 (neg:DI (match_operand:DI 2 "arith_reg_operand" "1,1"))))]
5398 "TARGET_SH1"
5399 "#"
5400 "TARGET_SH1"
5401 [(const_int 0)]
5402 {
5403 rtx low_src = gen_lowpart (SImode, operands[1]);
5404 rtx high_src = gen_highpart (SImode, operands[1]);
5405 rtx low_dst = gen_lowpart (SImode, operands[0]);
5406 rtx high_dst = gen_highpart (SImode, operands[0]);
5407
5408 rtx skip_neg_label = gen_label_rtx ();
5409
5410 emit_insn (gen_movsi (low_dst, low_src));
5411 emit_insn (gen_movsi (high_dst, high_src));
5412
5413 emit_jump_insn (INTVAL (operands[3])
5414 ? gen_branch_true (skip_neg_label)
5415 : gen_branch_false (skip_neg_label));
5416
5417 if (!INTVAL (operands[3]))
5418 emit_insn (gen_clrt ());
5419
5420 emit_insn (gen_negc (low_dst, low_src));
5421 emit_label_after (skip_neg_label, emit_insn (gen_negc (high_dst, high_src)));
5422 DONE;
5423 })
5424
5425 (define_expand "bswapsi2"
5426 [(set (match_operand:SI 0 "arith_reg_dest" "")
5427 (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
5428 "TARGET_SH1"
5429 {
5430 if (! can_create_pseudo_p ())
5431 FAIL;
5432 else
5433 {
5434 rtx tmp0 = gen_reg_rtx (SImode);
5435 rtx tmp1 = gen_reg_rtx (SImode);
5436
5437 emit_insn (gen_swapbsi2 (tmp0, operands[1]));
5438 emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
5439 emit_insn (gen_swapbsi2 (operands[0], tmp1));
5440 DONE;
5441 }
5442 })
5443
5444 (define_insn "swapbsi2"
5445 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5446 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
5447 (const_int 4294901760))
5448 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5449 (const_int 65280))
5450 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5451 (const_int 255)))))]
5452 "TARGET_SH1"
5453 "swap.b %1,%0"
5454 [(set_attr "type" "arith")])
5455
5456 ;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
5457 ;; partial byte swap expressions such as...
5458 ;; ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
5459 ;; ...which are currently not handled by the tree optimizers.
5460 ;; The combine pass will not initially try to combine the full expression,
5461 ;; but only some sub-expressions. In such a case the *swapbisi2_and_shl8
5462 ;; pattern acts as an intermediate pattern that will eventually lead combine
5463 ;; to the swapbsi2 pattern above.
5464 ;; As a side effect this also improves code that does (x & 0xFF) << 8
5465 ;; or (x << 8) & 0xFF00.
5466 (define_insn_and_split "*swapbisi2_and_shl8"
5467 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5468 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5469 (const_int 8))
5470 (const_int 65280))
5471 (match_operand:SI 2 "arith_reg_operand" "r")))]
5472 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5473 "#"
5474 "&& can_create_pseudo_p ()"
5475 [(const_int 0)]
5476 {
5477 rtx tmp0 = gen_reg_rtx (SImode);
5478 rtx tmp1 = gen_reg_rtx (SImode);
5479
5480 emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
5481 emit_insn (gen_swapbsi2 (tmp1, tmp0));
5482 emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
5483 DONE;
5484 })
5485
5486 ;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
5487 ;; intermediate pattern that will help the combine pass arriving at swapbsi2.
5488 (define_insn_and_split "*swapbhisi2"
5489 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5490 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5491 (const_int 8))
5492 (const_int 65280))
5493 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
5494 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
5495 "#"
5496 "&& can_create_pseudo_p ()"
5497 [(const_int 0)]
5498 {
5499 rtx tmp = gen_reg_rtx (SImode);
5500
5501 emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
5502 emit_insn (gen_swapbsi2 (operands[0], tmp));
5503 DONE;
5504 })
5505
5506 ;; In some cases the swapbsi2 pattern might leave a sequence such as...
5507 ;; swap.b r4,r4
5508 ;; mov r4,r0
5509 ;;
5510 ;; which can be simplified to...
5511 ;; swap.b r4,r0
5512 (define_peephole2
5513 [(set (match_operand:SI 0 "arith_reg_dest" "")
5514 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5515 (const_int 4294901760))
5516 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5517 (const_int 65280))
5518 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5519 (const_int 255)))))
5520 (set (match_operand:SI 2 "arith_reg_dest" "")
5521 (match_dup 0))]
5522 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
5523 [(set (match_dup 2)
5524 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
5525 (const_int 4294901760))
5526 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
5527 (const_int 65280))
5528 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
5529 (const_int 255)))))])
5530
5531 \f
5532 ;; -------------------------------------------------------------------------
5533 ;; Zero extension instructions
5534 ;; -------------------------------------------------------------------------
5535
5536 (define_insn "zero_extendsidi2"
5537 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5538 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
5539 "TARGET_SHMEDIA"
5540 "addz.l %1, r63, %0"
5541 [(set_attr "type" "arith_media")
5542 (set_attr "highpart" "extend")])
5543
5544 (define_insn "zero_extendhidi2"
5545 [(set (match_operand:DI 0 "register_operand" "=r,r")
5546 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5547 "TARGET_SHMEDIA"
5548 "@
5549 #
5550 ld%M1.uw %m1, %0"
5551 [(set_attr "type" "*,load_media")
5552 (set (attr "highpart")
5553 (cond [(match_test "sh_contains_memref_p (insn)")
5554 (const_string "user")]
5555 (const_string "ignore")))])
5556
5557 (define_split
5558 [(set (match_operand:DI 0 "register_operand" "")
5559 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
5560 "TARGET_SHMEDIA && reload_completed"
5561 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
5562 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
5563 {
5564 if (GET_CODE (operands[1]) == TRUNCATE)
5565 operands[1] = XEXP (operands[1], 0);
5566 })
5567
5568 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
5569 ;; reload the entire truncate expression.
5570 (define_insn_and_split "*loaddi_trunc"
5571 [(set (match_operand 0 "any_register_operand" "=r")
5572 (truncate (match_operand:DI 1 "memory_operand" "m")))]
5573 "TARGET_SHMEDIA && reload_completed"
5574 "#"
5575 "TARGET_SHMEDIA && reload_completed"
5576 [(set (match_dup 0) (match_dup 1))]
5577 {
5578 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
5579 })
5580
5581 (define_insn "zero_extendqidi2"
5582 [(set (match_operand:DI 0 "register_operand" "=r,r")
5583 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5584 "TARGET_SHMEDIA"
5585 "@
5586 andi %1, 255, %0
5587 ld%M1.ub %m1, %0"
5588 [(set_attr "type" "arith_media,load_media")
5589 (set (attr "highpart")
5590 (cond [(match_test "sh_contains_memref_p (insn)")
5591 (const_string "user")]
5592 (const_string "ignore")))])
5593
5594 (define_expand "zero_extend<mode>si2"
5595 [(set (match_operand:SI 0 "arith_reg_dest")
5596 (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
5597
5598 (define_insn_and_split "*zero_extend<mode>si2_compact"
5599 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5600 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
5601 "TARGET_SH1"
5602 "extu.<bw> %1,%0"
5603 "&& can_create_pseudo_p ()"
5604 [(set (match_dup 0) (match_dup 2))]
5605 {
5606 /* Sometimes combine fails to combine a T bit or negated T bit store to a
5607 reg with a following zero extension. In the split pass after combine,
5608 try to figure the extended reg was set. If it originated from the T
5609 bit we can replace the zero extension with a reg move, which will be
5610 eliminated. Notice that this also helps the *cbranch_t splitter when
5611 it tries to post-combine tests and conditional branches, as it does not
5612 check for zero extensions. */
5613 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
5614 if (operands[2] == NULL_RTX)
5615 FAIL;
5616 }
5617 [(set_attr "type" "arith")])
5618
5619 (define_insn "*zero_extendhisi2_media"
5620 [(set (match_operand:SI 0 "register_operand" "=r,r")
5621 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5622 "TARGET_SHMEDIA"
5623 "@
5624 #
5625 ld%M1.uw %m1, %0"
5626 [(set_attr "type" "arith_media,load_media")
5627 (set (attr "highpart")
5628 (cond [(match_test "sh_contains_memref_p (insn)")
5629 (const_string "user")]
5630 (const_string "ignore")))])
5631
5632 (define_split
5633 [(set (match_operand:SI 0 "register_operand" "")
5634 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
5635 "TARGET_SHMEDIA && reload_completed"
5636 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5637 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5638 {
5639 rtx op1 = operands[1];
5640
5641 if (GET_CODE (op1) == TRUNCATE)
5642 op1 = XEXP (op1, 0);
5643 operands[2]
5644 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
5645 subreg_lowpart_offset (SImode, GET_MODE (op1)));
5646 })
5647
5648 (define_insn "*zero_extendqisi2_media"
5649 [(set (match_operand:SI 0 "register_operand" "=r,r")
5650 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5651 "TARGET_SHMEDIA"
5652 "@
5653 andi %1, 255, %0
5654 ld%M1.ub %m1, %0"
5655 [(set_attr "type" "arith_media,load_media")
5656 (set (attr "highpart")
5657 (cond [(match_test "sh_contains_memref_p (insn)")
5658 (const_string "user")]
5659 (const_string "ignore")))])
5660
5661 (define_insn "zero_extendqihi2"
5662 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
5663 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
5664 "TARGET_SH1"
5665 "extu.b %1,%0"
5666 [(set_attr "type" "arith")])
5667
5668 ;; SH2A supports two zero extending load instructions: movu.b and movu.w.
5669 ;; They could also be used for simple memory addresses like @Rn by setting
5670 ;; the displacement value to zero. However, doing so too early results in
5671 ;; missed opportunities for other optimizations such as post-inc or index
5672 ;; addressing loads.
5673 ;; Although the 'zero_extend_movu_operand' predicate does not allow simple
5674 ;; register addresses (an address without a displacement, index, post-inc),
5675 ;; zero-displacement addresses might be generated during reload, wich are
5676 ;; simplified to simple register addresses in turn. Thus, we have to
5677 ;; provide the Sdd and Sra alternatives in the patterns.
5678 (define_insn "*zero_extend<mode>si2_disp_mem"
5679 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5680 (zero_extend:SI
5681 (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
5682 "TARGET_SH2A"
5683 "@
5684 movu.<bw> %1,%0
5685 movu.<bw> @(0,%t1),%0"
5686 [(set_attr "type" "load")
5687 (set_attr "length" "4")])
5688
5689 ;; Convert the zero extending loads in sequences such as:
5690 ;; movu.b @(1,r5),r0 movu.w @(2,r5),r0
5691 ;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
5692 ;;
5693 ;; back to sign extending loads like:
5694 ;; mov.b @(1,r5),r0 mov.w @(2,r5),r0
5695 ;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
5696 ;;
5697 ;; if the extension type is irrelevant. The sign extending mov.{b|w} insn
5698 ;; is only 2 bytes in size if the displacement is {K04|K05}.
5699 ;; If the displacement is greater it doesn't matter, so we convert anyways.
5700 (define_peephole2
5701 [(set (match_operand:SI 0 "arith_reg_dest" "")
5702 (zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
5703 (set (match_operand 2 "general_operand" "")
5704 (match_operand 3 "arith_reg_operand" ""))]
5705 "TARGET_SH2A
5706 && REGNO (operands[0]) == REGNO (operands[3])
5707 && peep2_reg_dead_p (2, operands[0])
5708 && GET_MODE_SIZE (GET_MODE (operands[2]))
5709 <= GET_MODE_SIZE (GET_MODE (operands[1]))"
5710 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
5711 (set (match_dup 2) (match_dup 3))])
5712
5713 ;; Fold sequences such as
5714 ;; mov.b @r3,r7
5715 ;; extu.b r7,r7
5716 ;; into
5717 ;; movu.b @(0,r3),r7
5718 ;; This does not reduce the code size but the number of instructions is
5719 ;; halved, which results in faster code.
5720 (define_peephole2
5721 [(set (match_operand:SI 0 "arith_reg_dest" "")
5722 (sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
5723 (set (match_operand:SI 2 "arith_reg_dest" "")
5724 (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
5725 "TARGET_SH2A
5726 && GET_MODE (operands[1]) == GET_MODE (operands[3])
5727 && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
5728 && REGNO (operands[0]) == REGNO (operands[3])
5729 && (REGNO (operands[2]) == REGNO (operands[0])
5730 || peep2_reg_dead_p (2, operands[0]))"
5731 [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
5732 {
5733 operands[4]
5734 = replace_equiv_address (operands[1],
5735 gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
5736 const0_rtx));
5737 })
5738
5739 ;; -------------------------------------------------------------------------
5740 ;; Sign extension instructions
5741 ;; -------------------------------------------------------------------------
5742
5743 ;; ??? This should be a define expand.
5744 ;; ??? Or perhaps it should be dropped?
5745
5746 ;; convert_move generates good code for SH[1-4].
5747 (define_insn "extendsidi2"
5748 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
5749 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
5750 "TARGET_SHMEDIA"
5751 "@
5752 add.l %1, r63, %0
5753 ld%M1.l %m1, %0
5754 fmov.sl %1, %0"
5755 [(set_attr "type" "arith_media,load_media,fpconv_media")
5756 (set (attr "highpart")
5757 (cond [(match_test "sh_contains_memref_p (insn)")
5758 (const_string "user")]
5759 (const_string "extend")))])
5760
5761 (define_insn "extendhidi2"
5762 [(set (match_operand:DI 0 "register_operand" "=r,r")
5763 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5764 "TARGET_SHMEDIA"
5765 "@
5766 #
5767 ld%M1.w %m1, %0"
5768 [(set_attr "type" "*,load_media")
5769 (set (attr "highpart")
5770 (cond [(match_test "sh_contains_memref_p (insn)")
5771 (const_string "user")]
5772 (const_string "ignore")))])
5773
5774 (define_split
5775 [(set (match_operand:DI 0 "register_operand" "")
5776 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
5777 "TARGET_SHMEDIA && reload_completed"
5778 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
5779 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
5780 {
5781 if (GET_CODE (operands[1]) == TRUNCATE)
5782 operands[1] = XEXP (operands[1], 0);
5783 })
5784
5785 (define_insn "extendqidi2"
5786 [(set (match_operand:DI 0 "register_operand" "=r,r")
5787 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5788 "TARGET_SHMEDIA"
5789 "@
5790 #
5791 ld%M1.b %m1, %0"
5792 [(set_attr "type" "*,load_media")
5793 (set (attr "highpart")
5794 (cond [(match_test "sh_contains_memref_p (insn)")
5795 (const_string "user")]
5796 (const_string "ignore")))])
5797
5798 (define_split
5799 [(set (match_operand:DI 0 "register_operand" "")
5800 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
5801 "TARGET_SHMEDIA && reload_completed"
5802 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
5803 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
5804 {
5805 if (GET_CODE (operands[1]) == TRUNCATE)
5806 operands[1] = XEXP (operands[1], 0);
5807 })
5808
5809 (define_expand "extend<mode>si2"
5810 [(set (match_operand:SI 0 "arith_reg_dest")
5811 (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
5812
5813 (define_insn "*extendhisi2_media"
5814 [(set (match_operand:SI 0 "register_operand" "=r,r")
5815 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
5816 "TARGET_SHMEDIA"
5817 "@
5818 #
5819 ld%M1.w %m1, %0"
5820 [(set_attr "type" "arith_media,load_media")
5821 (set (attr "highpart")
5822 (cond [(match_test "sh_contains_memref_p (insn)")
5823 (const_string "user")]
5824 (const_string "ignore")))])
5825
5826 (define_split
5827 [(set (match_operand:SI 0 "register_operand" "")
5828 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
5829 "TARGET_SHMEDIA && reload_completed"
5830 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5831 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5832 {
5833 rtx op1 = operands[1];
5834 if (GET_CODE (op1) == TRUNCATE)
5835 op1 = XEXP (op1, 0);
5836 operands[2]
5837 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
5838 subreg_lowpart_offset (SImode, GET_MODE (op1)));
5839 })
5840
5841 (define_insn_and_split "*extend<mode>si2_compact_reg"
5842 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5843 (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
5844 "TARGET_SH1"
5845 "exts.<bw> %1,%0"
5846 "&& can_create_pseudo_p ()"
5847 [(set (match_dup 0) (match_dup 2))]
5848 {
5849 /* Sometimes combine fails to combine a T bit or negated T bit store to a
5850 reg with a following sign extension. In the split pass after combine,
5851 try to figure the extended reg was set. If it originated from the T
5852 bit we can replace the sign extension with a reg move, which will be
5853 eliminated. */
5854 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
5855 if (operands[2] == NULL_RTX)
5856 FAIL;
5857 }
5858 [(set_attr "type" "arith")])
5859
5860 ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
5861 ;; See movqi insns.
5862 (define_insn "*extend<mode>si2_compact_mem_disp"
5863 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
5864 (sign_extend:SI
5865 (mem:QIHI
5866 (plus:SI
5867 (match_operand:SI 1 "arith_reg_operand" "%r,r")
5868 (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
5869 "TARGET_SH1 && ! TARGET_SH2A
5870 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
5871 "@
5872 mov.<bw> @(%O2,%1),%0
5873 mov.<bw> @%1,%0"
5874 [(set_attr "type" "load")])
5875
5876 (define_insn "*extend<mode>si2_compact_mem_disp"
5877 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
5878 (sign_extend:SI
5879 (mem:QIHI
5880 (plus:SI
5881 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
5882 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
5883 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
5884 "@
5885 mov.<bw> @(%O2,%1),%0
5886 mov.<bw> @%1,%0
5887 mov.<bw> @(%O2,%1),%0"
5888 [(set_attr "type" "load")
5889 (set_attr "length" "2,2,4")])
5890
5891 ;; The *_snd patterns will take care of other QImode/HImode addressing
5892 ;; modes than displacement addressing. They must be defined _after_ the
5893 ;; displacement addressing patterns. Otherwise the displacement addressing
5894 ;; patterns will not be picked.
5895 (define_insn "*extend<mode>si2_compact_snd"
5896 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5897 (sign_extend:SI
5898 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
5899 "TARGET_SH1"
5900 "mov.<bw> %1,%0"
5901 [(set_attr "type" "load")])
5902
5903 (define_insn "*extendqisi2_media"
5904 [(set (match_operand:SI 0 "register_operand" "=r,r")
5905 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
5906 "TARGET_SHMEDIA"
5907 "@
5908 #
5909 ld%M1.b %m1, %0"
5910 [(set_attr "type" "arith_media,load_media")
5911 (set (attr "highpart")
5912 (cond [(match_test "sh_contains_memref_p (insn)")
5913 (const_string "user")]
5914 (const_string "ignore")))])
5915
5916 (define_split
5917 [(set (match_operand:SI 0 "register_operand" "")
5918 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
5919 "TARGET_SHMEDIA && reload_completed"
5920 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5921 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5922 {
5923 rtx op1 = operands[1];
5924 if (GET_CODE (op1) == TRUNCATE)
5925 op1 = XEXP (op1, 0);
5926 operands[2]
5927 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
5928 subreg_lowpart_offset (SImode, GET_MODE (op1)));
5929 })
5930
5931 (define_expand "extendqihi2"
5932 [(set (match_operand:HI 0 "arith_reg_dest" "")
5933 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))]
5934 ""
5935 "")
5936
5937 (define_insn "*extendqihi2_compact_reg"
5938 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
5939 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
5940 "TARGET_SH1"
5941 "exts.b %1,%0"
5942 [(set_attr "type" "arith")])
5943
5944 ;; It would seem useful to combine the truncXi patterns into the movXi
5945 ;; patterns, but unary operators are ignored when matching constraints,
5946 ;; so we need separate patterns.
5947 (define_insn "truncdisi2"
5948 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
5949 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
5950 "TARGET_SHMEDIA"
5951 "@
5952 add.l %1, r63, %0
5953 st%M0.l %m0, %1
5954 fst%M0.s %m0, %T1
5955 fmov.ls %1, %0
5956 fmov.sl %T1, %0
5957 fmov.s %T1, %0"
5958 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
5959 (set (attr "highpart")
5960 (cond [(match_test "sh_contains_memref_p (insn)")
5961 (const_string "user")]
5962 (const_string "extend")))])
5963
5964 (define_insn "truncdihi2"
5965 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
5966 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
5967 "TARGET_SHMEDIA"
5968 {
5969 static const char* alt[] =
5970 {
5971 "shlli %1,48,%0" "\n"
5972 " shlri %0,48,%0",
5973
5974 "st%M0.w %m0, %1"
5975 };
5976 return alt[which_alternative];
5977 }
5978 [(set_attr "type" "arith_media,store_media")
5979 (set_attr "length" "8,4")
5980 (set (attr "highpart")
5981 (cond [(match_test "sh_contains_memref_p (insn)")
5982 (const_string "user")]
5983 (const_string "extend")))])
5984
5985 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
5986 ; Because we use zero extension, we can't provide signed QImode compares
5987 ; using a simple compare or conditional branch insn.
5988 (define_insn "truncdiqi2"
5989 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
5990 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
5991 "TARGET_SHMEDIA"
5992 "@
5993 andi %1, 255, %0
5994 st%M0.b %m0, %1"
5995 [(set_attr "type" "arith_media,store")
5996 (set (attr "highpart")
5997 (cond [(match_test "sh_contains_memref_p (insn)")
5998 (const_string "user")]
5999 (const_string "extend")))])
6000 ;; -------------------------------------------------------------------------
6001 ;; Move instructions
6002 ;; -------------------------------------------------------------------------
6003
6004 ;; define push and pop so it is easy for sh.c
6005 ;; We can't use push and pop on SHcompact because the stack must always
6006 ;; be 8-byte aligned.
6007
6008 (define_expand "push"
6009 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6010 (match_operand:SI 0 "register_operand" "r,l,x"))]
6011 "TARGET_SH1 && ! TARGET_SH5"
6012 "")
6013
6014 (define_expand "pop"
6015 [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6016 (mem:SI (post_inc:SI (reg:SI SP_REG))))]
6017 "TARGET_SH1 && ! TARGET_SH5"
6018 "")
6019
6020 (define_expand "push_e"
6021 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6022 (match_operand:SF 0 "" ""))
6023 (use (reg:PSI FPSCR_REG))
6024 (clobber (scratch:SI))])]
6025 "TARGET_SH1 && ! TARGET_SH5"
6026 "")
6027
6028 (define_insn "push_fpul"
6029 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6030 "TARGET_SH2E && ! TARGET_SH5"
6031 "sts.l fpul,@-r15"
6032 [(set_attr "type" "fstore")
6033 (set_attr "late_fp_use" "yes")
6034 (set_attr "hit_stack" "yes")])
6035
6036 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6037 ;; so use that.
6038 (define_expand "push_4"
6039 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6040 (match_operand:DF 0 "" ""))
6041 (use (reg:PSI FPSCR_REG))
6042 (clobber (scratch:SI))])]
6043 "TARGET_SH1 && ! TARGET_SH5"
6044 "")
6045
6046 (define_expand "pop_e"
6047 [(parallel [(set (match_operand:SF 0 "" "")
6048 (mem:SF (post_inc:SI (reg:SI SP_REG))))
6049 (use (reg:PSI FPSCR_REG))
6050 (clobber (scratch:SI))])]
6051 "TARGET_SH1 && ! TARGET_SH5"
6052 "")
6053
6054 (define_insn "pop_fpul"
6055 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6056 "TARGET_SH2E && ! TARGET_SH5"
6057 "lds.l @r15+,fpul"
6058 [(set_attr "type" "load")
6059 (set_attr "hit_stack" "yes")])
6060
6061 (define_expand "pop_4"
6062 [(parallel [(set (match_operand:DF 0 "" "")
6063 (mem:DF (post_inc:SI (reg:SI SP_REG))))
6064 (use (reg:PSI FPSCR_REG))
6065 (clobber (scratch:SI))])]
6066 "TARGET_SH1 && ! TARGET_SH5"
6067 "")
6068
6069 (define_expand "push_fpscr"
6070 [(const_int 0)]
6071 "TARGET_SH2E"
6072 {
6073 rtx insn = emit_insn (gen_fpu_switch (gen_frame_mem (PSImode,
6074 gen_rtx_PRE_DEC (Pmode,
6075 stack_pointer_rtx)),
6076 get_fpscr_rtx ()));
6077 add_reg_note (insn, REG_INC, stack_pointer_rtx);
6078 DONE;
6079 })
6080
6081 (define_expand "pop_fpscr"
6082 [(const_int 0)]
6083 "TARGET_SH2E"
6084 {
6085 rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (),
6086 gen_frame_mem (PSImode,
6087 gen_rtx_POST_INC (Pmode,
6088 stack_pointer_rtx))));
6089 add_reg_note (insn, REG_INC, stack_pointer_rtx);
6090 DONE;
6091 })
6092
6093 ;; The clrt and sett patterns can happen as the result of optimization and
6094 ;; insn expansion.
6095 ;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6096 ;; In this case they might not disappear completely, because the T reg is
6097 ;; a fixed hard reg.
6098 ;; When DImode operations that use the T reg as carry/borrow are split into
6099 ;; individual SImode operations, the T reg is usually cleared before the
6100 ;; first SImode insn.
6101
6102 (define_insn "clrt"
6103 [(set (reg:SI T_REG) (const_int 0))]
6104 "TARGET_SH1"
6105 "clrt"
6106 [(set_attr "type" "mt_group")])
6107
6108 (define_insn "sett"
6109 [(set (reg:SI T_REG) (const_int 1))]
6110 "TARGET_SH1"
6111 "sett"
6112 [(set_attr "type" "mt_group")])
6113
6114 ;; Use the combine pass to transform sequences such as
6115 ;; mov r5,r0
6116 ;; add #1,r0
6117 ;; shll2 r0
6118 ;; mov.l @(r0,r4),r0
6119 ;; into
6120 ;; shll2 r5
6121 ;; add r4,r5
6122 ;; mov.l @(4,r5),r0
6123 ;;
6124 ;; See also PR 39423.
6125 ;; Notice that these patterns have a T_REG clobber, because the shift
6126 ;; sequence that will be split out might clobber the T_REG. Ideally, the
6127 ;; clobber would be added conditionally, depending on the result of
6128 ;; sh_ashlsi_clobbers_t_reg_p. When splitting out the shifts we must go
6129 ;; through the ashlsi3 expander in order to get the right shift insn --
6130 ;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
6131 ;; FIXME: Combine never tries this kind of patterns for DImode.
6132 (define_insn_and_split "*movsi_index_disp_load"
6133 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6134 (match_operand:SI 1 "mem_index_disp_operand" "m"))
6135 (clobber (reg:SI T_REG))]
6136 "TARGET_SH1"
6137 "#"
6138 "&& can_create_pseudo_p ()"
6139 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6140 (set (match_dup 0) (match_dup 7))]
6141 {
6142 rtx mem = operands[1];
6143 rtx plus0_rtx = XEXP (mem, 0);
6144 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6145 rtx mult_rtx = XEXP (plus1_rtx, 0);
6146
6147 operands[1] = XEXP (mult_rtx, 0);
6148 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6149 operands[3] = XEXP (plus1_rtx, 1);
6150 operands[4] = XEXP (plus0_rtx, 1);
6151 operands[5] = gen_reg_rtx (SImode);
6152 operands[6] = gen_reg_rtx (SImode);
6153 operands[7] =
6154 replace_equiv_address (mem,
6155 gen_rtx_PLUS (SImode, operands[6], operands[4]));
6156
6157 emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
6158 })
6159
6160 (define_insn_and_split "*movhi_index_disp_load"
6161 [(set (match_operand:SI 0 "arith_reg_dest")
6162 (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
6163 (clobber (reg:SI T_REG))]
6164 "TARGET_SH1"
6165 "#"
6166 "&& can_create_pseudo_p ()"
6167 [(const_int 0)]
6168 {
6169 rtx mem = operands[1];
6170 rtx plus0_rtx = XEXP (mem, 0);
6171 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6172 rtx mult_rtx = XEXP (plus1_rtx, 0);
6173
6174 rtx op_1 = XEXP (mult_rtx, 0);
6175 rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6176 rtx op_3 = XEXP (plus1_rtx, 1);
6177 rtx op_4 = XEXP (plus0_rtx, 1);
6178 rtx op_5 = gen_reg_rtx (SImode);
6179 rtx op_6 = gen_reg_rtx (SImode);
6180 rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6181
6182 emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6183 emit_insn (gen_addsi3 (op_6, op_5, op_3));
6184
6185 if (<CODE> == SIGN_EXTEND)
6186 {
6187 emit_insn (gen_extendhisi2 (operands[0], op_7));
6188 DONE;
6189 }
6190 else if (<CODE> == ZERO_EXTEND)
6191 {
6192 /* On SH2A the movu.w insn can be used for zero extending loads. */
6193 if (TARGET_SH2A)
6194 emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
6195 else
6196 {
6197 emit_insn (gen_extendhisi2 (operands[0], op_7));
6198 emit_insn (gen_zero_extendhisi2 (operands[0],
6199 gen_lowpart (HImode, operands[0])));
6200 }
6201 DONE;
6202 }
6203 else
6204 FAIL;
6205 })
6206
6207 (define_insn_and_split "*mov<mode>_index_disp_store"
6208 [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
6209 (match_operand:HISI 1 "arith_reg_operand" "r"))
6210 (clobber (reg:SI T_REG))]
6211 "TARGET_SH1"
6212 "#"
6213 "&& can_create_pseudo_p ()"
6214 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6215 (set (match_dup 7) (match_dup 1))]
6216 {
6217 rtx mem = operands[0];
6218 rtx plus0_rtx = XEXP (mem, 0);
6219 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6220 rtx mult_rtx = XEXP (plus1_rtx, 0);
6221
6222 operands[0] = XEXP (mult_rtx, 0);
6223 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6224 operands[3] = XEXP (plus1_rtx, 1);
6225 operands[4] = XEXP (plus0_rtx, 1);
6226 operands[5] = gen_reg_rtx (SImode);
6227 operands[6] = gen_reg_rtx (SImode);
6228 operands[7] =
6229 replace_equiv_address (mem,
6230 gen_rtx_PLUS (SImode, operands[6], operands[4]));
6231
6232 emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
6233 })
6234
6235 ;; t/r must come after r/r, lest reload will try to reload stuff like
6236 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
6237 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
6238 (define_insn "movsi_i"
6239 [(set (match_operand:SI 0 "general_movdst_operand"
6240 "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
6241 (match_operand:SI 1 "general_movsrc_operand"
6242 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
6243 "TARGET_SH1
6244 && ! TARGET_SH2E
6245 && ! TARGET_SH2A
6246 && (register_operand (operands[0], SImode)
6247 || register_operand (operands[1], SImode))"
6248 "@
6249 mov.l %1,%0
6250 mov %1,%0
6251 mov %1,%0
6252 mov.l %1,%0
6253 sts %1,%0
6254 sts %1,%0
6255 mov.l %1,%0
6256 sts.l %1,%0
6257 sts.l %1,%0
6258 lds %1,%0
6259 lds %1,%0
6260 lds.l %1,%0
6261 lds.l %1,%0
6262 fake %1,%0"
6263 [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,pcload_si")
6264 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
6265
6266 ;; t/r must come after r/r, lest reload will try to reload stuff like
6267 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
6268 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
6269 ;; will require a reload.
6270 ;; ??? We can't include f/f because we need the proper FPSCR setting when
6271 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
6272 (define_insn "movsi_ie"
6273 [(set (match_operand:SI 0 "general_movdst_operand"
6274 "=r,r,r,r,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
6275 (match_operand:SI 1 "general_movsrc_operand"
6276 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
6277 "(TARGET_SH2E || TARGET_SH2A)
6278 && (register_operand (operands[0], SImode)
6279 || register_operand (operands[1], SImode))"
6280 "@
6281 mov.l %1,%0
6282 mov %1,%0
6283 mov %1,%0
6284 movi20 %1,%0
6285 movi20s %1,%0
6286 mov.l %1,%0
6287 sts %1,%0
6288 sts %1,%0
6289 mov.l %1,%0
6290 sts.l %1,%0
6291 sts.l %1,%0
6292 lds %1,%0
6293 lds %1,%0
6294 lds.l %1,%0
6295 lds.l %1,%0
6296 lds.l %1,%0
6297 sts.l %1,%0
6298 fake %1,%0
6299 lds %1,%0
6300 sts %1,%0
6301 fsts fpul,%0
6302 flds %1,fpul
6303 fmov %1,%0
6304 ! move optimized away"
6305 [(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")
6306 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
6307 (set_attr_alternative "length"
6308 [(const_int 2)
6309 (const_int 2)
6310 (const_int 2)
6311 (const_int 4)
6312 (const_int 4)
6313 (if_then_else
6314 (match_test "TARGET_SH2A")
6315 (const_int 4) (const_int 2))
6316 (const_int 2)
6317 (const_int 2)
6318 (if_then_else
6319 (match_test "TARGET_SH2A")
6320 (const_int 4) (const_int 2))
6321 (const_int 2)
6322 (const_int 2)
6323 (const_int 2)
6324 (const_int 2)
6325 (const_int 2)
6326 (const_int 2)
6327 (const_int 2)
6328 (const_int 2)
6329 (const_int 2)
6330 (const_int 2)
6331 (const_int 2)
6332 (const_int 2)
6333 (const_int 2)
6334 (const_int 2)
6335 (const_int 0)])])
6336
6337 (define_insn "movsi_i_lowpart"
6338 [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
6339 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
6340 "TARGET_SH1
6341 && (register_operand (operands[0], SImode)
6342 || register_operand (operands[1], SImode))"
6343 "@
6344 mov.l %1,%0
6345 mov %1,%0
6346 mov %1,%0
6347 mov.l %1,%0
6348 sts %1,%0
6349 sts %1,%0
6350 mov.l %1,%0
6351 fake %1,%0"
6352 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
6353
6354 (define_insn_and_split "load_ra"
6355 [(set (match_operand:SI 0 "general_movdst_operand" "")
6356 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
6357 "TARGET_SH1"
6358 "#"
6359 "&& ! currently_expanding_to_rtl"
6360 [(set (match_dup 0) (match_dup 1))]
6361 {
6362 if (TARGET_SHCOMPACT && crtl->saves_all_registers)
6363 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
6364 })
6365
6366 ;; The '?'s in the following constraints may not reflect the time taken
6367 ;; to perform the move. They are there to discourage the use of floating-
6368 ;; point registers for storing integer values.
6369 (define_insn "*movsi_media"
6370 [(set (match_operand:SI 0 "general_movdst_operand"
6371 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
6372 (match_operand:SI 1 "general_movsrc_operand"
6373 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
6374 "TARGET_SHMEDIA_FPU
6375 && (register_operand (operands[0], SImode)
6376 || sh_register_operand (operands[1], SImode)
6377 || GET_CODE (operands[1]) == TRUNCATE)"
6378 "@
6379 add.l %1, r63, %0
6380 movi %1, %0
6381 #
6382 ld%M1.l %m1, %0
6383 st%M0.l %m0, %N1
6384 fld%M1.s %m1, %0
6385 fst%M0.s %m0, %1
6386 fmov.ls %N1, %0
6387 fmov.sl %1, %0
6388 fmov.s %1, %0
6389 ptabs %1, %0
6390 gettr %1, %0
6391 pt %1, %0"
6392 [(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")
6393 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
6394 (set (attr "highpart")
6395 (cond [(match_test "sh_contains_memref_p (insn)")
6396 (const_string "user")]
6397 (const_string "ignore")))])
6398
6399 (define_insn "*movsi_media_nofpu"
6400 [(set (match_operand:SI 0 "general_movdst_operand"
6401 "=r,r,r,r,m,*b,r,*b")
6402 (match_operand:SI 1 "general_movsrc_operand"
6403 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
6404 "TARGET_SHMEDIA
6405 && (register_operand (operands[0], SImode)
6406 || sh_register_operand (operands[1], SImode)
6407 || GET_CODE (operands[1]) == TRUNCATE)"
6408 "@
6409 add.l %1, r63, %0
6410 movi %1, %0
6411 #
6412 ld%M1.l %m1, %0
6413 st%M0.l %m0, %N1
6414 ptabs %1, %0
6415 gettr %1, %0
6416 pt %1, %0"
6417 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
6418 (set_attr "length" "4,4,8,4,4,4,4,12")
6419 (set (attr "highpart")
6420 (cond [(match_test "sh_contains_memref_p (insn)")
6421 (const_string "user")]
6422 (const_string "ignore")))])
6423
6424 (define_expand "movsi_const"
6425 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6426 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6427 (const_int 16)] UNSPEC_EXTRACT_S16)))
6428 (set (match_dup 0)
6429 (ior:SI (ashift:SI (match_dup 0) (const_int 16))
6430 (const:SI (unspec:SI [(match_dup 1)
6431 (const_int 0)] UNSPEC_EXTRACT_U16))))]
6432 "TARGET_SHMEDIA && reload_completed
6433 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6434 {
6435 if (GET_CODE (operands[1]) == LABEL_REF
6436 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
6437 LABEL_NUSES (XEXP (operands[1], 0)) += 2;
6438 else if (GOTOFF_P (operands[1]))
6439 {
6440 rtx unspec = XEXP (operands[1], 0);
6441
6442 if (! UNSPEC_GOTOFF_P (unspec))
6443 {
6444 unspec = XEXP (unspec, 0);
6445 if (! UNSPEC_GOTOFF_P (unspec))
6446 abort ();
6447 }
6448 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
6449 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
6450 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
6451 }
6452 })
6453
6454 (define_expand "movsi_const_16bit"
6455 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
6456 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
6457 (const_int 0)] UNSPEC_EXTRACT_S16)))]
6458 "TARGET_SHMEDIA && flag_pic && reload_completed
6459 && GET_CODE (operands[1]) == SYMBOL_REF"
6460 "")
6461
6462 (define_split
6463 [(set (match_operand:SI 0 "arith_reg_dest" "")
6464 (match_operand:SI 1 "immediate_operand" ""))]
6465 "TARGET_SHMEDIA && reload_completed
6466 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6467 [(const_int 0)]
6468 {
6469 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
6470
6471 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
6472
6473 DONE;
6474 })
6475
6476 (define_split
6477 [(set (match_operand:SI 0 "register_operand" "")
6478 (match_operand:SI 1 "immediate_operand" ""))]
6479 "TARGET_SHMEDIA && reload_completed
6480 && ((CONST_INT_P (operands[1])
6481 && ! satisfies_constraint_I16 (operands[1]))
6482 || GET_CODE (operands[1]) == CONST_DOUBLE)"
6483 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6484
6485 (define_expand "movsi"
6486 [(set (match_operand:SI 0 "general_movdst_operand" "")
6487 (match_operand:SI 1 "general_movsrc_operand" ""))]
6488 ""
6489 {
6490 prepare_move_operands (operands, SImode);
6491 })
6492
6493 (define_expand "ic_invalidate_line"
6494 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
6495 (match_dup 1)] UNSPEC_ICACHE)
6496 (clobber (scratch:SI))])]
6497 "TARGET_HARD_SH4 || TARGET_SH5"
6498 {
6499 if (TARGET_SHMEDIA)
6500 {
6501 emit_insn (gen_ic_invalidate_line_media (operands[0]));
6502 DONE;
6503 }
6504 else if (TARGET_SHCOMPACT)
6505 {
6506 operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
6507 operands[1] = force_reg (Pmode, operands[1]);
6508 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
6509 DONE;
6510 }
6511 else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
6512 {
6513 emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
6514 DONE;
6515 }
6516 operands[0] = force_reg (Pmode, operands[0]);
6517 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
6518 Pmode)));
6519 })
6520
6521 ;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing
6522 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
6523 ;; the requirement *1*00 for associative address writes. The alignment of
6524 ;; %0 implies that its least significant bit is cleared,
6525 ;; thus we clear the V bit of a matching entry if there is one.
6526 (define_insn "ic_invalidate_line_i"
6527 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
6528 (match_operand:SI 1 "register_operand" "r")]
6529 UNSPEC_ICACHE)
6530 (clobber (match_scratch:SI 2 "=&r"))]
6531 "TARGET_HARD_SH4"
6532 {
6533 return "ocbwb @%0" "\n"
6534 " extu.w %0,%2" "\n"
6535 " or %1,%2" "\n"
6536 " mov.l %0,@%2";
6537 }
6538 [(set_attr "length" "8")
6539 (set_attr "type" "cwb")])
6540
6541 (define_insn "ic_invalidate_line_sh4a"
6542 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
6543 UNSPEC_ICACHE)]
6544 "TARGET_SH4A_ARCH || TARGET_SH4_300"
6545 {
6546 return "ocbwb @%0" "\n"
6547 " synco" "\n"
6548 " icbi @%0";
6549 }
6550 [(set_attr "length" "16") ;; FIXME: Why 16 and not 6? Looks like typo.
6551 (set_attr "type" "cwb")])
6552
6553 ;; ??? could make arg 0 an offsettable memory operand to allow to save
6554 ;; an add in the code that calculates the address.
6555 (define_insn "ic_invalidate_line_media"
6556 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
6557 UNSPEC_ICACHE)]
6558 "TARGET_SHMEDIA"
6559 {
6560 return "ocbwb %0,0" "\n"
6561 " synco" "\n"
6562 " icbi %0,0" "\n"
6563 " synci";
6564 }
6565 [(set_attr "length" "16")
6566 (set_attr "type" "invalidate_line_media")])
6567
6568 (define_insn "ic_invalidate_line_compact"
6569 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6570 (match_operand:SI 1 "register_operand" "r")]
6571 UNSPEC_ICACHE)
6572 (clobber (reg:SI PR_REG))]
6573 "TARGET_SHCOMPACT"
6574 "jsr @%1%#"
6575 [(set_attr "type" "sfunc")
6576 (set_attr "needs_delay_slot" "yes")])
6577
6578 (define_expand "initialize_trampoline"
6579 [(match_operand:SI 0 "" "")
6580 (match_operand:SI 1 "" "")
6581 (match_operand:SI 2 "" "")]
6582 "TARGET_SHCOMPACT"
6583 {
6584 rtx sfun, tramp;
6585
6586 tramp = force_reg (Pmode, operands[0]);
6587 sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
6588 SFUNC_STATIC));
6589 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
6590 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
6591
6592 emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
6593 DONE;
6594 })
6595
6596 (define_insn "initialize_trampoline_compact"
6597 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
6598 (match_operand:SI 1 "register_operand" "r")
6599 (reg:SI R2_REG) (reg:SI R3_REG)]
6600 UNSPEC_INIT_TRAMP)
6601
6602 (clobber (reg:SI PR_REG))]
6603 "TARGET_SHCOMPACT"
6604 "jsr @%1%#"
6605 [(set_attr "type" "sfunc")
6606 (set_attr "needs_delay_slot" "yes")])
6607
6608 (define_expand "movhi"
6609 [(set (match_operand:HI 0 "general_movdst_operand" "")
6610 (match_operand:HI 1 "general_movsrc_operand" ""))]
6611 ""
6612 {
6613 prepare_move_operands (operands, HImode);
6614 })
6615
6616 (define_expand "movqi"
6617 [(set (match_operand:QI 0 "general_operand" "")
6618 (match_operand:QI 1 "general_operand" ""))]
6619 ""
6620 {
6621 prepare_move_operands (operands, QImode);
6622 })
6623
6624 ;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be
6625 ;; selected to copy QImode regs. If one of them happens to be allocated
6626 ;; on the stack, reload will stick to movqi insn and generate wrong
6627 ;; displacement addressing because of the generic m alternatives.
6628 ;; With the movqi_reg_reg being specified before movqi it will be initially
6629 ;; picked to load/store regs. If the regs regs are on the stack reload will
6630 ;; try other insns and not stick to movqi_reg_reg.
6631 ;; The same applies to the movhi variants.
6632 ;;
6633 ;; Notice, that T bit is not allowed as a mov src operand here. This is to
6634 ;; avoid things like (set (reg:QI) (subreg:QI (reg:SI T_REG) 0)), which
6635 ;; introduces zero extensions after T bit stores and redundant reg copies.
6636 ;;
6637 ;; FIXME: We can't use 'arith_reg_operand' (which disallows T_REG) as a
6638 ;; predicate for the mov src operand because reload will have trouble
6639 ;; reloading MAC subregs otherwise. For that probably special patterns
6640 ;; would be required.
6641 (define_insn "*mov<mode>_reg_reg"
6642 [(set (match_operand:QIHI 0 "arith_reg_dest" "=r")
6643 (match_operand:QIHI 1 "register_operand" "r"))]
6644 "TARGET_SH1 && !t_reg_operand (operands[1], VOIDmode)"
6645 "mov %1,%0"
6646 [(set_attr "type" "move")])
6647
6648 ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
6649 ;; "enabled" attribute as it is done in other targets.
6650 (define_insn "*mov<mode>_store_mem_disp04"
6651 [(set (mem:QIHI
6652 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
6653 (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
6654 (match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
6655 "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
6656 "@
6657 mov.<bw> %2,@(%O1,%0)
6658 mov.<bw> %2,@%0"
6659 [(set_attr "type" "store")])
6660
6661 (define_insn "*mov<mode>_store_mem_disp12"
6662 [(set (mem:QIHI
6663 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
6664 (match_operand:SI 1 "const_int_operand" "<disp12>")))
6665 (match_operand:QIHI 2 "arith_reg_operand" "r"))]
6666 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
6667 "mov.<bw> %2,@(%O1,%0)"
6668 [(set_attr "type" "store")
6669 (set_attr "length" "4")])
6670
6671 (define_insn "*mov<mode>_load_mem_disp04"
6672 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
6673 (mem:QIHI
6674 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
6675 (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
6676 "TARGET_SH1 && ! TARGET_SH2A
6677 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6678 "@
6679 mov.<bw> @(%O2,%1),%0
6680 mov.<bw> @%1,%0"
6681 [(set_attr "type" "load")])
6682
6683 (define_insn "*mov<mode>_load_mem_disp12"
6684 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
6685 (mem:QIHI
6686 (plus:SI
6687 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6688 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
6689 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6690 "@
6691 mov.<bw> @(%O2,%1),%0
6692 mov.<bw> @%1,%0
6693 mov.<bw> @(%O2,%1),%0"
6694 [(set_attr "type" "load")
6695 (set_attr "length" "2,2,4")])
6696
6697 ;; The m constraints basically allow any kind of addresses to be used with any
6698 ;; source/target register as the other operand. This is not true for
6699 ;; displacement addressing modes on anything but SH2A. That's why the
6700 ;; specialized load/store insns are specified above.
6701 (define_insn "*movqi"
6702 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,l")
6703 (match_operand:QI 1 "general_movsrc_operand" "i,m,r,l,r"))]
6704 "TARGET_SH1
6705 && (arith_reg_operand (operands[0], QImode)
6706 || arith_reg_operand (operands[1], QImode))"
6707 "@
6708 mov %1,%0
6709 mov.b %1,%0
6710 mov.b %1,%0
6711 sts %1,%0
6712 lds %1,%0"
6713 [(set_attr "type" "movi8,load,store,prget,prset")])
6714
6715 (define_insn "*movhi"
6716 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l")
6717 (match_operand:HI 1 "general_movsrc_operand" "Q,i,m,r,l,r"))]
6718 "TARGET_SH1
6719 && (arith_reg_operand (operands[0], HImode)
6720 || arith_reg_operand (operands[1], HImode))"
6721 "@
6722 mov.w %1,%0
6723 mov %1,%0
6724 mov.w %1,%0
6725 mov.w %1,%0
6726 sts %1,%0
6727 lds %1,%0"
6728 [(set_attr "type" "pcload,movi8,load,store,prget,prset")])
6729
6730 (define_insn "*movqi_media"
6731 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
6732 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
6733 "TARGET_SHMEDIA
6734 && (arith_reg_operand (operands[0], QImode)
6735 || extend_reg_or_0_operand (operands[1], QImode))"
6736 "@
6737 add.l %1, r63, %0
6738 movi %1, %0
6739 ld%M1.ub %m1, %0
6740 st%M0.b %m0, %N1"
6741 [(set_attr "type" "arith_media,arith_media,load_media,store_media")
6742 (set (attr "highpart")
6743 (cond [(match_test "sh_contains_memref_p (insn)")
6744 (const_string "user")]
6745 (const_string "ignore")))])
6746
6747 (define_expand "reload_inqi"
6748 [(set (match_operand:SI 2 "" "=&r")
6749 (match_operand:QI 1 "inqhi_operand" ""))
6750 (set (match_operand:QI 0 "arith_reg_operand" "=r")
6751 (truncate:QI (match_dup 3)))]
6752 "TARGET_SHMEDIA"
6753 {
6754 rtx inner = XEXP (operands[1], 0);
6755 int regno = REGNO (inner);
6756
6757 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
6758 operands[1] = gen_rtx_REG (SImode, regno);
6759 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
6760 })
6761
6762 (define_insn "*movhi_media"
6763 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
6764 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
6765 "TARGET_SHMEDIA
6766 && (arith_reg_operand (operands[0], HImode)
6767 || arith_reg_or_0_operand (operands[1], HImode))"
6768 "@
6769 add.l %1, r63, %0
6770 movi %1, %0
6771 #
6772 ld%M1.w %m1, %0
6773 st%M0.w %m0, %N1"
6774 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
6775 (set (attr "highpart")
6776 (cond [(match_test "sh_contains_memref_p (insn)")
6777 (const_string "user")]
6778 (const_string "ignore")))])
6779
6780 (define_split
6781 [(set (match_operand:HI 0 "register_operand" "")
6782 (match_operand:HI 1 "immediate_operand" ""))]
6783 "TARGET_SHMEDIA && reload_completed
6784 && ! satisfies_constraint_I16 (operands[1])"
6785 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
6786
6787 (define_expand "reload_inhi"
6788 [(set (match_operand:SI 2 "" "=&r")
6789 (match_operand:HI 1 "inqhi_operand" ""))
6790 (set (match_operand:HI 0 "arith_reg_operand" "=r")
6791 (truncate:HI (match_dup 3)))]
6792 "TARGET_SHMEDIA"
6793 {
6794 rtx inner = XEXP (operands[1], 0);
6795 int regno = REGNO (inner);
6796
6797 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
6798 operands[1] = gen_rtx_REG (SImode, regno);
6799 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
6800 })
6801
6802 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
6803 ;; compiled with -m2 -ml -O3 -funroll-loops
6804 (define_insn "*movdi_i"
6805 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
6806 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
6807 "TARGET_SH1
6808 && (arith_reg_operand (operands[0], DImode)
6809 || arith_reg_operand (operands[1], DImode))"
6810 {
6811 return output_movedouble (insn, operands, DImode);
6812 }
6813 [(set_attr "length" "4")
6814 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
6815
6816 ;; If the output is a register and the input is memory or a register, we have
6817 ;; to be careful and see which word needs to be loaded first.
6818
6819 (define_split
6820 [(set (match_operand:DI 0 "general_movdst_operand" "")
6821 (match_operand:DI 1 "general_movsrc_operand" ""))]
6822 "TARGET_SH1 && reload_completed"
6823 [(set (match_dup 2) (match_dup 3))
6824 (set (match_dup 4) (match_dup 5))]
6825 {
6826 int regno;
6827
6828 if ((MEM_P (operands[0])
6829 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
6830 || (MEM_P (operands[1])
6831 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
6832 FAIL;
6833
6834 switch (GET_CODE (operands[0]))
6835 {
6836 case REG:
6837 regno = REGNO (operands[0]);
6838 break;
6839 case SUBREG:
6840 regno = subreg_regno (operands[0]);
6841 break;
6842 case MEM:
6843 regno = -1;
6844 break;
6845 default:
6846 gcc_unreachable ();
6847 }
6848
6849 if (regno == -1
6850 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
6851 {
6852 operands[2] = operand_subword (operands[0], 0, 0, DImode);
6853 operands[3] = operand_subword (operands[1], 0, 0, DImode);
6854 operands[4] = operand_subword (operands[0], 1, 0, DImode);
6855 operands[5] = operand_subword (operands[1], 1, 0, DImode);
6856 }
6857 else
6858 {
6859 operands[2] = operand_subword (operands[0], 1, 0, DImode);
6860 operands[3] = operand_subword (operands[1], 1, 0, DImode);
6861 operands[4] = operand_subword (operands[0], 0, 0, DImode);
6862 operands[5] = operand_subword (operands[1], 0, 0, DImode);
6863 }
6864
6865 if (operands[2] == 0 || operands[3] == 0
6866 || operands[4] == 0 || operands[5] == 0)
6867 FAIL;
6868 })
6869
6870 ;; The '?'s in the following constraints may not reflect the time taken
6871 ;; to perform the move. They are there to discourage the use of floating-
6872 ;; point registers for storing integer values.
6873 (define_insn "*movdi_media"
6874 [(set (match_operand:DI 0 "general_movdst_operand"
6875 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
6876 (match_operand:DI 1 "general_movsrc_operand"
6877 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
6878 "TARGET_SHMEDIA_FPU
6879 && (register_operand (operands[0], DImode)
6880 || sh_register_operand (operands[1], DImode))"
6881 "@
6882 add %1, r63, %0
6883 movi %1, %0
6884 #
6885 ld%M1.q %m1, %0
6886 st%M0.q %m0, %N1
6887 fld%M1.d %m1, %0
6888 fst%M0.d %m0, %1
6889 fmov.qd %N1, %0
6890 fmov.dq %1, %0
6891 fmov.d %1, %0
6892 ptabs %1, %0
6893 gettr %1, %0
6894 pt %1, %0"
6895 [(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")
6896 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
6897
6898 (define_insn "*movdi_media_nofpu"
6899 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
6900 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
6901 "TARGET_SHMEDIA
6902 && (register_operand (operands[0], DImode)
6903 || sh_register_operand (operands[1], DImode))"
6904 "@
6905 add %1, r63, %0
6906 movi %1, %0
6907 #
6908 ld%M1.q %m1, %0
6909 st%M0.q %m0, %N1
6910 ptabs %1, %0
6911 gettr %1, %0
6912 pt %1, %0"
6913 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
6914 (set_attr "length" "4,4,16,4,4,4,4,*")])
6915
6916 (define_insn "*movdi_media_I16"
6917 [(set (match_operand:DI 0 "ext_dest_operand" "=r")
6918 (match_operand:DI 1 "const_int_operand" "I16"))]
6919 "TARGET_SHMEDIA && reload_completed"
6920 "movi %1, %0"
6921 [(set_attr "type" "arith_media")
6922 (set_attr "length" "4")])
6923
6924 (define_split
6925 [(set (match_operand:DI 0 "arith_reg_dest" "")
6926 (match_operand:DI 1 "immediate_operand" ""))]
6927 "TARGET_SHMEDIA && reload_completed
6928 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6929 [(set (match_dup 0) (match_dup 1))]
6930 {
6931 rtx insn;
6932
6933 if (TARGET_SHMEDIA64)
6934 insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
6935 else
6936 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
6937
6938 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
6939
6940 DONE;
6941 })
6942
6943 (define_expand "movdi_const"
6944 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
6945 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
6946 (const_int 48)] UNSPEC_EXTRACT_S16)))
6947 (set (match_dup 0)
6948 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
6949 (const:DI (unspec:DI [(match_dup 1)
6950 (const_int 32)] UNSPEC_EXTRACT_U16))))
6951 (set (match_dup 0)
6952 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
6953 (const:DI (unspec:DI [(match_dup 1)
6954 (const_int 16)] UNSPEC_EXTRACT_U16))))
6955 (set (match_dup 0)
6956 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
6957 (const:DI (unspec:DI [(match_dup 1)
6958 (const_int 0)] UNSPEC_EXTRACT_U16))))]
6959 "TARGET_SHMEDIA64 && reload_completed
6960 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6961 {
6962 sh_mark_label (operands[1], 4);
6963 })
6964
6965 (define_expand "movdi_const_32bit"
6966 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
6967 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
6968 (const_int 16)] UNSPEC_EXTRACT_S16)))
6969 (set (match_dup 0)
6970 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
6971 (const:DI (unspec:DI [(match_dup 1)
6972 (const_int 0)] UNSPEC_EXTRACT_U16))))]
6973 "TARGET_SHMEDIA32 && reload_completed
6974 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
6975 {
6976 sh_mark_label (operands[1], 2);
6977 })
6978
6979 (define_expand "movdi_const_16bit"
6980 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
6981 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
6982 (const_int 0)] UNSPEC_EXTRACT_S16)))]
6983 "TARGET_SHMEDIA && flag_pic && reload_completed
6984 && GET_CODE (operands[1]) == SYMBOL_REF"
6985 "")
6986
6987 (define_split
6988 [(set (match_operand:DI 0 "ext_dest_operand" "")
6989 (match_operand:DI 1 "immediate_operand" ""))]
6990 "TARGET_SHMEDIA && reload_completed
6991 && CONST_INT_P (operands[1])
6992 && ! satisfies_constraint_I16 (operands[1])"
6993 [(set (match_dup 0) (match_dup 2))
6994 (match_dup 1)]
6995 {
6996 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
6997 unsigned HOST_WIDE_INT low = val;
6998 unsigned HOST_WIDE_INT high = val;
6999 unsigned HOST_WIDE_INT sign;
7000 unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7001
7002 /* Zero-extend the 16 least-significant bits. */
7003 low &= 0xffff;
7004
7005 /* Arithmetic shift right the word by 16 bits. */
7006 high >>= 16;
7007 if (GET_CODE (operands[0]) == SUBREG
7008 && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7009 {
7010 high &= 0xffff;
7011 high ^= 0x8000;
7012 high -= 0x8000;
7013 }
7014 else
7015 {
7016 sign = 1;
7017 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7018 high ^= sign;
7019 high -= sign;
7020 }
7021 do
7022 {
7023 /* If we can't generate the constant with a two-insn movi / shori
7024 sequence, try some other strategies. */
7025 if (! CONST_OK_FOR_I16 (high))
7026 {
7027 /* Try constant load / left shift. We know VAL != 0. */
7028 val2 = val ^ (val-1);
7029 if (val2 > 0x1ffff)
7030 {
7031 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7032
7033 if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7034 || (! CONST_OK_FOR_I16 (high >> 16)
7035 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7036 {
7037 val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7038 operands[1] = gen_ashldi3_media (operands[0], operands[0],
7039 GEN_INT (trailing_zeroes));
7040 break;
7041 }
7042 }
7043 /* Try constant load / right shift. */
7044 val2 = (val >> 15) + 1;
7045 if (val2 == (val2 & -val2))
7046 {
7047 int shift = 49 - exact_log2 (val2);
7048
7049 val2 = trunc_int_for_mode (val << shift, DImode);
7050 if (CONST_OK_FOR_I16 (val2))
7051 {
7052 operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7053 GEN_INT (shift));
7054 break;
7055 }
7056 }
7057 /* Try mperm.w . */
7058 val2 = val & 0xffff;
7059 if ((val >> 16 & 0xffff) == val2
7060 && (val >> 32 & 0xffff) == val2
7061 && (val >> 48 & 0xffff) == val2)
7062 {
7063 val2 = (HOST_WIDE_INT) val >> 48;
7064 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7065 operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7066 break;
7067 }
7068 /* Try movi / mshflo.l */
7069 val2 = (HOST_WIDE_INT) val >> 32;
7070 if (val2 == ((unsigned HOST_WIDE_INT)
7071 trunc_int_for_mode (val, SImode)))
7072 {
7073 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7074 operands[0]);
7075 break;
7076 }
7077 /* Try movi / mshflo.l w/ r63. */
7078 val2 = val + ((HOST_WIDE_INT) -1 << 32);
7079 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7080 {
7081 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7082 const0_rtx);
7083 break;
7084 }
7085 }
7086 val2 = high;
7087 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7088 }
7089 while (0);
7090 operands[2] = GEN_INT (val2);
7091 })
7092
7093 (define_split
7094 [(set (match_operand:DI 0 "ext_dest_operand" "")
7095 (match_operand:DI 1 "immediate_operand" ""))]
7096 "TARGET_SHMEDIA && reload_completed
7097 && GET_CODE (operands[1]) == CONST_DOUBLE"
7098 [(set (match_dup 0) (match_dup 2))
7099 (set (match_dup 0)
7100 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7101 {
7102 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7103 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7104 unsigned HOST_WIDE_INT val = low;
7105 unsigned HOST_WIDE_INT sign;
7106
7107 /* Zero-extend the 16 least-significant bits. */
7108 val &= 0xffff;
7109 operands[1] = GEN_INT (val);
7110
7111 /* Arithmetic shift right the double-word by 16 bits. */
7112 low >>= 16;
7113 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7114 high >>= 16;
7115 sign = 1;
7116 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7117 high ^= sign;
7118 high -= sign;
7119
7120 /* This will only be true if high is a sign-extension of low, i.e.,
7121 it must be either 0 or (unsigned)-1, and be zero iff the
7122 most-significant bit of low is set. */
7123 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7124 operands[2] = GEN_INT (low);
7125 else
7126 operands[2] = immed_double_const (low, high, DImode);
7127 })
7128
7129 (define_insn "shori_media"
7130 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
7131 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7132 (const_int 16))
7133 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
7134 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
7135 "@
7136 shori %u2, %0
7137 #"
7138 [(set_attr "type" "arith_media,*")])
7139
7140 (define_insn "*shori_media_si"
7141 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7142 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7143 (const_int 16))
7144 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
7145 "TARGET_SHMEDIA"
7146 "shori %u2, %0")
7147
7148 (define_expand "movdi"
7149 [(set (match_operand:DI 0 "general_movdst_operand" "")
7150 (match_operand:DI 1 "general_movsrc_operand" ""))]
7151 ""
7152 {
7153 prepare_move_operands (operands, DImode);
7154 })
7155
7156 (define_insn "movdf_media"
7157 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7158 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7159 "TARGET_SHMEDIA_FPU
7160 && (register_operand (operands[0], DFmode)
7161 || sh_register_operand (operands[1], DFmode))"
7162 "@
7163 fmov.d %1, %0
7164 fmov.qd %N1, %0
7165 fmov.dq %1, %0
7166 add %1, r63, %0
7167 #
7168 fld%M1.d %m1, %0
7169 fst%M0.d %m0, %1
7170 ld%M1.q %m1, %0
7171 st%M0.q %m0, %N1"
7172 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")])
7173
7174 (define_insn "movdf_media_nofpu"
7175 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7176 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
7177 "TARGET_SHMEDIA
7178 && (register_operand (operands[0], DFmode)
7179 || sh_register_operand (operands[1], DFmode))"
7180 "@
7181 add %1, r63, %0
7182 #
7183 ld%M1.q %m1, %0
7184 st%M0.q %m0, %N1"
7185 [(set_attr "type" "arith_media,*,load_media,store_media")])
7186
7187 (define_split
7188 [(set (match_operand:DF 0 "arith_reg_dest" "")
7189 (match_operand:DF 1 "immediate_operand" ""))]
7190 "TARGET_SHMEDIA && reload_completed"
7191 [(set (match_dup 3) (match_dup 2))]
7192 {
7193 int endian = WORDS_BIG_ENDIAN ? 1 : 0;
7194 long values[2];
7195 REAL_VALUE_TYPE value;
7196
7197 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
7198 REAL_VALUE_TO_TARGET_DOUBLE (value, values);
7199
7200 if (HOST_BITS_PER_WIDE_INT >= 64)
7201 operands[2] = immed_double_const ((unsigned long) values[endian]
7202 | ((HOST_WIDE_INT) values[1 - endian]
7203 << 32), 0, DImode);
7204 else
7205 {
7206 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
7207 operands[2] = immed_double_const (values[endian], values[1 - endian],
7208 DImode);
7209 }
7210
7211 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
7212 })
7213
7214 ;; ??? This should be a define expand.
7215
7216 (define_insn "movdf_k"
7217 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7218 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
7219 "TARGET_SH1
7220 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
7221 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
7222 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
7223 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
7224 && (arith_reg_operand (operands[0], DFmode)
7225 || arith_reg_operand (operands[1], DFmode))"
7226 {
7227 return output_movedouble (insn, operands, DFmode);
7228 }
7229 [(set_attr "length" "4")
7230 (set_attr "type" "move,pcload,load,store")])
7231
7232 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
7233 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
7234 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
7235 ;; the d/m/c/X alternative, which is split later into single-precision
7236 ;; instructions. And when not optimizing, no splits are done before fixing
7237 ;; up pcloads, so we need usable length information for that.
7238 (define_insn "movdf_i4"
7239 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
7240 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
7241 (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
7242 (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
7243 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7244 && (arith_reg_operand (operands[0], DFmode)
7245 || arith_reg_operand (operands[1], DFmode))"
7246 {
7247 switch (which_alternative)
7248 {
7249 case 0:
7250 if (TARGET_FMOVD)
7251 return "fmov %1,%0";
7252 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
7253 return "fmov %R1,%R0" "\n"
7254 " fmov %S1,%S0";
7255 else
7256 return "fmov %S1,%S0" "\n"
7257 " fmov %R1,%R0";
7258 case 3:
7259 case 4:
7260 return "fmov.d %1,%0";
7261 default:
7262 return "#";
7263 }
7264 }
7265 [(set_attr_alternative "length"
7266 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
7267 (const_int 4)
7268 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7269 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7270 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
7271 (const_int 4)
7272 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
7273 ;; We can't use 4-byte push/pop on SHcompact, so we have to
7274 ;; increment or decrement r15 explicitly.
7275 (if_then_else
7276 (match_test "TARGET_SHCOMPACT")
7277 (const_int 10) (const_int 8))
7278 (if_then_else
7279 (match_test "TARGET_SHCOMPACT")
7280 (const_int 10) (const_int 8))])
7281 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
7282 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
7283 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
7284 (const_string "double")
7285 (const_string "none")))])
7286
7287 ;; Moving DFmode between fp/general registers through memory
7288 ;; (the top of the stack) is faster than moving through fpul even for
7289 ;; little endian. Because the type of an instruction is important for its
7290 ;; scheduling, it is beneficial to split these operations, rather than
7291 ;; emitting them in one single chunk, even if this will expose a stack
7292 ;; use that will prevent scheduling of other stack accesses beyond this
7293 ;; instruction.
7294 (define_split
7295 [(set (match_operand:DF 0 "register_operand" "")
7296 (match_operand:DF 1 "register_operand" ""))
7297 (use (match_operand:PSI 2 "fpscr_operand" ""))
7298 (clobber (match_scratch:SI 3 "=X"))]
7299 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
7300 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
7301 [(const_int 0)]
7302 {
7303 rtx insn, tos;
7304
7305 if (TARGET_SH5 && true_regnum (operands[1]) < 16)
7306 {
7307 emit_move_insn (stack_pointer_rtx,
7308 plus_constant (Pmode, stack_pointer_rtx, -8));
7309 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7310 }
7311 else
7312 tos = gen_tmp_stack_mem (DFmode,
7313 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
7314 insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
7315 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
7316 add_reg_note (insn, REG_INC, stack_pointer_rtx);
7317 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7318 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
7319 else
7320 tos = gen_tmp_stack_mem (DFmode,
7321 gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
7322 insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
7323 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
7324 emit_move_insn (stack_pointer_rtx,
7325 plus_constant (Pmode, stack_pointer_rtx, 8));
7326 else
7327 add_reg_note (insn, REG_INC, stack_pointer_rtx);
7328 DONE;
7329 })
7330
7331 ;; local-alloc sometimes allocates scratch registers even when not required,
7332 ;; so we must be prepared to handle these.
7333
7334 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
7335 (define_split
7336 [(set (match_operand:DF 0 "general_movdst_operand" "")
7337 (match_operand:DF 1 "general_movsrc_operand" ""))
7338 (use (match_operand:PSI 2 "fpscr_operand" ""))
7339 (clobber (match_scratch:SI 3 ""))]
7340 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
7341 && reload_completed
7342 && true_regnum (operands[0]) < 16
7343 && true_regnum (operands[1]) < 16"
7344 [(set (match_dup 0) (match_dup 1))]
7345 {
7346 /* If this was a reg <-> mem operation with base + index reg addressing,
7347 we have to handle this in a special way. */
7348 rtx mem = operands[0];
7349 int store_p = 1;
7350 if (! memory_operand (mem, DFmode))
7351 {
7352 mem = operands[1];
7353 store_p = 0;
7354 }
7355 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
7356 mem = SUBREG_REG (mem);
7357 if (MEM_P (mem))
7358 {
7359 rtx addr = XEXP (mem, 0);
7360 if (GET_CODE (addr) == PLUS
7361 && REG_P (XEXP (addr, 0))
7362 && REG_P (XEXP (addr, 1)))
7363 {
7364 int offset;
7365 rtx reg0 = gen_rtx_REG (Pmode, 0);
7366 rtx regop = operands[store_p], word0 ,word1;
7367
7368 if (GET_CODE (regop) == SUBREG)
7369 alter_subreg (&regop);
7370 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
7371 offset = 2;
7372 else
7373 offset = 4;
7374 mem = copy_rtx (mem);
7375 PUT_MODE (mem, SImode);
7376 word0 = gen_rtx_SUBREG (SImode, regop, 0);
7377 alter_subreg (&word0);
7378 word1 = gen_rtx_SUBREG (SImode, regop, 4);
7379 alter_subreg (&word1);
7380 if (store_p || ! refers_to_regno_p (REGNO (word0),
7381 REGNO (word0) + 1, addr, 0))
7382 {
7383 emit_insn (store_p
7384 ? gen_movsi_ie (mem, word0)
7385 : gen_movsi_ie (word0, mem));
7386 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7387 mem = copy_rtx (mem);
7388 emit_insn (store_p
7389 ? gen_movsi_ie (mem, word1)
7390 : gen_movsi_ie (word1, mem));
7391 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7392 }
7393 else
7394 {
7395 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
7396 emit_insn (gen_movsi_ie (word1, mem));
7397 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
7398 mem = copy_rtx (mem);
7399 emit_insn (gen_movsi_ie (word0, mem));
7400 }
7401 DONE;
7402 }
7403 }
7404 })
7405
7406 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
7407 (define_split
7408 [(set (match_operand:DF 0 "register_operand" "")
7409 (match_operand:DF 1 "memory_operand" ""))
7410 (use (match_operand:PSI 2 "fpscr_operand" ""))
7411 (clobber (reg:SI R0_REG))]
7412 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
7413 [(parallel [(set (match_dup 0) (match_dup 1))
7414 (use (match_dup 2))
7415 (clobber (scratch:SI))])]
7416 "")
7417
7418 (define_expand "reload_indf__frn"
7419 [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
7420 (match_operand:DF 1 "immediate_operand" "FQ"))
7421 (use (reg:PSI FPSCR_REG))
7422 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
7423 "TARGET_SH1"
7424 "")
7425
7426 (define_expand "reload_outdf__RnFRm"
7427 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
7428 (match_operand:DF 1 "register_operand" "af,r"))
7429 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
7430 "TARGET_SH1"
7431 "")
7432
7433 ;; Simplify no-op moves.
7434 (define_split
7435 [(set (match_operand:SF 0 "register_operand" "")
7436 (match_operand:SF 1 "register_operand" ""))
7437 (use (match_operand:PSI 2 "fpscr_operand" ""))
7438 (clobber (match_scratch:SI 3 ""))]
7439 "TARGET_SH2E && reload_completed
7440 && true_regnum (operands[0]) == true_regnum (operands[1])"
7441 [(set (match_dup 0) (match_dup 0))]
7442 "")
7443
7444 ;; fmovd substitute post-reload splits
7445 (define_split
7446 [(set (match_operand:DF 0 "register_operand" "")
7447 (match_operand:DF 1 "register_operand" ""))
7448 (use (match_operand:PSI 2 "fpscr_operand" ""))
7449 (clobber (match_scratch:SI 3 ""))]
7450 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
7451 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7452 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7453 [(const_int 0)]
7454 {
7455 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
7456 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
7457 gen_rtx_REG (SFmode, src), operands[2]));
7458 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
7459 gen_rtx_REG (SFmode, src + 1), operands[2]));
7460 DONE;
7461 })
7462
7463 (define_split
7464 [(set (match_operand:DF 0 "register_operand" "")
7465 (mem:DF (match_operand:SI 1 "register_operand" "")))
7466 (use (match_operand:PSI 2 "fpscr_operand" ""))
7467 (clobber (match_scratch:SI 3 ""))]
7468 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7469 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
7470 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
7471 [(const_int 0)]
7472 {
7473 int regno = true_regnum (operands[0]);
7474 rtx insn;
7475 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
7476 rtx mem2
7477 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
7478 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7479 regno + !! TARGET_LITTLE_ENDIAN),
7480 mem2, operands[2]));
7481 add_reg_note (insn, REG_INC, operands[1]);
7482 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
7483 regno + ! TARGET_LITTLE_ENDIAN),
7484 change_address (mem, SFmode, NULL_RTX),
7485 operands[2]));
7486 DONE;
7487 })
7488
7489 (define_split
7490 [(set (match_operand:DF 0 "register_operand" "")
7491 (match_operand:DF 1 "memory_operand" ""))
7492 (use (match_operand:PSI 2 "fpscr_operand" ""))
7493 (clobber (match_scratch:SI 3 ""))]
7494 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7495 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
7496 [(const_int 0)]
7497 {
7498 int regno = true_regnum (operands[0]);
7499 rtx addr, insn;
7500 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
7501 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
7502 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
7503
7504 operands[1] = copy_rtx (mem2);
7505 addr = XEXP (mem2, 0);
7506
7507 switch (GET_CODE (addr))
7508 {
7509 case REG:
7510 /* This is complicated. If the register is an arithmetic register
7511 we can just fall through to the REG+DISP case below. Otherwise
7512 we have to use a combination of POST_INC and REG addressing... */
7513 if (! arith_reg_operand (operands[1], SFmode))
7514 {
7515 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
7516 insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
7517 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7518
7519 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7520
7521 /* If we have modified the stack pointer, the value that we have
7522 read with post-increment might be modified by an interrupt,
7523 so write it back. */
7524 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
7525 emit_insn (gen_push_e (reg0));
7526 else
7527 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), GEN_INT (-4)));
7528 break;
7529 }
7530 /* Fall through. */
7531
7532 case PLUS:
7533 emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7534 operands[1] = copy_rtx (operands[1]);
7535 XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
7536 emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7537 break;
7538
7539 case POST_INC:
7540 insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
7541 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7542
7543 insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
7544 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7545 break;
7546
7547 default:
7548 debug_rtx (addr);
7549 gcc_unreachable ();
7550 }
7551
7552 DONE;
7553 })
7554
7555 (define_split
7556 [(set (match_operand:DF 0 "memory_operand" "")
7557 (match_operand:DF 1 "register_operand" ""))
7558 (use (match_operand:PSI 2 "fpscr_operand" ""))
7559 (clobber (match_scratch:SI 3 ""))]
7560 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
7561 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
7562 [(const_int 0)]
7563 {
7564 int regno = true_regnum (operands[1]);
7565 rtx insn, addr;
7566 rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
7567 rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
7568
7569 operands[0] = copy_rtx (operands[0]);
7570 PUT_MODE (operands[0], SFmode);
7571 addr = XEXP (operands[0], 0);
7572
7573 switch (GET_CODE (addr))
7574 {
7575 case REG:
7576 /* This is complicated. If the register is an arithmetic register
7577 we can just fall through to the REG+DISP case below. Otherwise
7578 we have to use a combination of REG and PRE_DEC addressing... */
7579 if (! arith_reg_operand (operands[0], SFmode))
7580 {
7581 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
7582 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7583
7584 operands[0] = copy_rtx (operands[0]);
7585 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
7586
7587 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7588 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7589 break;
7590 }
7591 /* Fall through. */
7592
7593 case PLUS:
7594 /* Since REG+DISP addressing has already been decided upon by gcc
7595 we can rely upon it having chosen an arithmetic register as the
7596 register component of the address. Just emit the lower numbered
7597 register first, to the lower address, then the higher numbered
7598 register to the higher address. */
7599 emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7600
7601 operands[0] = copy_rtx (operands[0]);
7602 XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
7603
7604 emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7605 break;
7606
7607 case PRE_DEC:
7608 /* This is easy. Output the word to go to the higher address
7609 first (ie the word in the higher numbered register) then the
7610 word to go to the lower address. */
7611
7612 insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
7613 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7614
7615 insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
7616 add_reg_note (insn, REG_INC, XEXP (addr, 0));
7617 break;
7618
7619 default:
7620 /* FAIL; */
7621 debug_rtx (addr);
7622 gcc_unreachable ();
7623 }
7624
7625 DONE;
7626 })
7627
7628 ;; If the output is a register and the input is memory or a register, we have
7629 ;; to be careful and see which word needs to be loaded first.
7630
7631 (define_split
7632 [(set (match_operand:DF 0 "general_movdst_operand" "")
7633 (match_operand:DF 1 "general_movsrc_operand" ""))]
7634 "TARGET_SH1 && reload_completed"
7635 [(set (match_dup 2) (match_dup 3))
7636 (set (match_dup 4) (match_dup 5))]
7637 {
7638 int regno;
7639
7640 if ((MEM_P (operands[0])
7641 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7642 || (MEM_P (operands[1])
7643 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7644 FAIL;
7645
7646 switch (GET_CODE (operands[0]))
7647 {
7648 case REG:
7649 regno = REGNO (operands[0]);
7650 break;
7651 case SUBREG:
7652 regno = subreg_regno (operands[0]);
7653 break;
7654 case MEM:
7655 regno = -1;
7656 break;
7657 default:
7658 gcc_unreachable ();
7659 }
7660
7661 if (regno == -1
7662 || ! refers_to_regno_p (regno, regno + 1, operands[1], 0))
7663 {
7664 operands[2] = operand_subword (operands[0], 0, 0, DFmode);
7665 operands[3] = operand_subword (operands[1], 0, 0, DFmode);
7666 operands[4] = operand_subword (operands[0], 1, 0, DFmode);
7667 operands[5] = operand_subword (operands[1], 1, 0, DFmode);
7668 }
7669 else
7670 {
7671 operands[2] = operand_subword (operands[0], 1, 0, DFmode);
7672 operands[3] = operand_subword (operands[1], 1, 0, DFmode);
7673 operands[4] = operand_subword (operands[0], 0, 0, DFmode);
7674 operands[5] = operand_subword (operands[1], 0, 0, DFmode);
7675 }
7676
7677 if (operands[2] == 0 || operands[3] == 0
7678 || operands[4] == 0 || operands[5] == 0)
7679 FAIL;
7680 })
7681
7682 (define_expand "movdf"
7683 [(set (match_operand:DF 0 "general_movdst_operand" "")
7684 (match_operand:DF 1 "general_movsrc_operand" ""))]
7685 ""
7686 {
7687 prepare_move_operands (operands, DFmode);
7688 if (TARGET_SHMEDIA)
7689 {
7690 if (TARGET_SHMEDIA_FPU)
7691 emit_insn (gen_movdf_media (operands[0], operands[1]));
7692 else
7693 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
7694 DONE;
7695 }
7696 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
7697 {
7698 emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
7699 DONE;
7700 }
7701 })
7702
7703 ;;This is incompatible with the way gcc uses subregs.
7704 ;;(define_insn "movv2sf_i"
7705 ;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
7706 ;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
7707 ;; "TARGET_SHMEDIA_FPU
7708 ;; && (fp_arith_reg_operand (operands[0], V2SFmode)
7709 ;; || fp_arith_reg_operand (operands[1], V2SFmode))"
7710 ;; "@
7711 ;; #
7712 ;; fld%M1.p %m1, %0
7713 ;; fst%M0.p %m0, %1"
7714 ;; [(set_attr "type" "*,fload_media,fstore_media")])
7715
7716 (define_insn_and_split "movv2sf_i"
7717 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
7718 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
7719 "TARGET_SHMEDIA_FPU"
7720 "#"
7721 "TARGET_SHMEDIA_FPU && reload_completed"
7722 [(set (match_dup 0) (match_dup 1))]
7723 {
7724 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
7725 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
7726 })
7727
7728 (define_expand "movv2sf"
7729 [(set (match_operand:V2SF 0 "general_movdst_operand" "")
7730 (match_operand:V2SF 1 "nonimmediate_operand" ""))]
7731 "TARGET_SHMEDIA_FPU"
7732 {
7733 prepare_move_operands (operands, V2SFmode);
7734 })
7735
7736 (define_expand "addv2sf3"
7737 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7738 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7739 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7740 "TARGET_SHMEDIA_FPU"
7741 {
7742 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
7743 DONE;
7744 })
7745
7746 (define_expand "subv2sf3"
7747 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7748 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7749 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7750 "TARGET_SHMEDIA_FPU"
7751 {
7752 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
7753 DONE;
7754 })
7755
7756 (define_expand "mulv2sf3"
7757 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7758 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7759 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7760 "TARGET_SHMEDIA_FPU"
7761 {
7762 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
7763 DONE;
7764 })
7765
7766 (define_expand "divv2sf3"
7767 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
7768 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
7769 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
7770 "TARGET_SHMEDIA_FPU"
7771 {
7772 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
7773 DONE;
7774 })
7775
7776 (define_insn_and_split "*movv4sf_i"
7777 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
7778 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
7779 "TARGET_SHMEDIA_FPU"
7780 "#"
7781 "&& reload_completed"
7782 [(const_int 0)]
7783 {
7784 int i;
7785
7786 for (i = 0; i < 4/2; i++)
7787 {
7788 rtx x, y;
7789
7790 if (MEM_P (operands[0]))
7791 x = adjust_address (operands[0], V2SFmode,
7792 i * GET_MODE_SIZE (V2SFmode));
7793 else
7794 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
7795
7796 if (MEM_P (operands[1]))
7797 y = adjust_address (operands[1], V2SFmode,
7798 i * GET_MODE_SIZE (V2SFmode));
7799 else
7800 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
7801
7802 emit_insn (gen_movv2sf_i (x, y));
7803 }
7804
7805 DONE;
7806 }
7807 [(set_attr "length" "8")])
7808
7809 (define_expand "movv4sf"
7810 [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
7811 (match_operand:V4SF 1 "general_operand" ""))]
7812 "TARGET_SHMEDIA_FPU"
7813 {
7814 prepare_move_operands (operands, V4SFmode);
7815 })
7816
7817 (define_insn_and_split "*movv16sf_i"
7818 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
7819 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
7820 "TARGET_SHMEDIA_FPU"
7821 "#"
7822 "&& reload_completed"
7823 [(const_int 0)]
7824 {
7825 int i;
7826
7827 for (i = 0; i < 16/2; i++)
7828 {
7829 rtx x,y;
7830
7831 if (MEM_P (operands[0]))
7832 x = adjust_address (operands[0], V2SFmode,
7833 i * GET_MODE_SIZE (V2SFmode));
7834 else
7835 {
7836 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
7837 alter_subreg (&x);
7838 }
7839
7840 if (MEM_P (operands[1]))
7841 y = adjust_address (operands[1], V2SFmode,
7842 i * GET_MODE_SIZE (V2SFmode));
7843 else
7844 {
7845 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
7846 alter_subreg (&y);
7847 }
7848
7849 emit_insn (gen_movv2sf_i (x, y));
7850 }
7851
7852 DONE;
7853 }
7854 [(set_attr "length" "32")])
7855
7856 (define_expand "movv16sf"
7857 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
7858 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
7859 "TARGET_SHMEDIA_FPU"
7860 {
7861 prepare_move_operands (operands, V16SFmode);
7862 })
7863
7864 (define_insn "movsf_media"
7865 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7866 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7867 "TARGET_SHMEDIA_FPU
7868 && (register_operand (operands[0], SFmode)
7869 || sh_register_operand (operands[1], SFmode))"
7870 "@
7871 fmov.s %1, %0
7872 fmov.ls %N1, %0
7873 fmov.sl %1, %0
7874 add.l %1, r63, %0
7875 #
7876 fld%M1.s %m1, %0
7877 fst%M0.s %m0, %1
7878 ld%M1.l %m1, %0
7879 st%M0.l %m0, %N1"
7880 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
7881 (set (attr "highpart")
7882 (cond [(match_test "sh_contains_memref_p (insn)")
7883 (const_string "user")]
7884 (const_string "ignore")))])
7885
7886 (define_insn "movsf_media_nofpu"
7887 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
7888 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
7889 "TARGET_SHMEDIA
7890 && (register_operand (operands[0], SFmode)
7891 || sh_register_operand (operands[1], SFmode))"
7892 "@
7893 add.l %1, r63, %0
7894 #
7895 ld%M1.l %m1, %0
7896 st%M0.l %m0, %N1"
7897 [(set_attr "type" "arith_media,*,load_media,store_media")
7898 (set (attr "highpart")
7899 (cond [(match_test "sh_contains_memref_p (insn)")
7900 (const_string "user")]
7901 (const_string "ignore")))])
7902
7903 (define_split
7904 [(set (match_operand:SF 0 "arith_reg_dest" "")
7905 (match_operand:SF 1 "immediate_operand" ""))]
7906 "TARGET_SHMEDIA && reload_completed
7907 && ! FP_REGISTER_P (true_regnum (operands[0]))"
7908 [(set (match_dup 3) (match_dup 2))]
7909 {
7910 long values;
7911 REAL_VALUE_TYPE value;
7912
7913 REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
7914 REAL_VALUE_TO_TARGET_SINGLE (value, values);
7915 operands[2] = GEN_INT (values);
7916
7917 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
7918 })
7919
7920 (define_insn "movsf_i"
7921 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
7922 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))]
7923 "TARGET_SH1
7924 && (! TARGET_SH2E
7925 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
7926 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
7927 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
7928 && (arith_reg_operand (operands[0], SFmode)
7929 || arith_reg_operand (operands[1], SFmode))"
7930 "@
7931 mov %1,%0
7932 mov #0,%0
7933 mov.l %1,%0
7934 mov.l %1,%0
7935 mov.l %1,%0
7936 lds %1,%0
7937 sts %1,%0"
7938 [(set_attr "type" "move,move,pcload,load,store,move,move")])
7939
7940 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
7941 ;; update_flow_info would not know where to put REG_EQUAL notes
7942 ;; when the destination changes mode.
7943 (define_insn "movsf_ie"
7944 [(set (match_operand:SF 0 "general_movdst_operand"
7945 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
7946 (match_operand:SF 1 "general_movsrc_operand"
7947 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
7948 (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"))
7949 (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
7950 "TARGET_SH2E
7951 && (arith_reg_operand (operands[0], SFmode)
7952 || arith_reg_operand (operands[1], SFmode)
7953 || arith_reg_operand (operands[3], SImode)
7954 || (fpul_operand (operands[0], SFmode)
7955 && memory_operand (operands[1], SFmode)
7956 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
7957 || (fpul_operand (operands[1], SFmode)
7958 && memory_operand (operands[0], SFmode)
7959 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
7960 "@
7961 fmov %1,%0
7962 mov %1,%0
7963 fldi0 %0
7964 fldi1 %0
7965 #
7966 fmov.s %1,%0
7967 fmov.s %1,%0
7968 mov.l %1,%0
7969 mov.l %1,%0
7970 mov.l %1,%0
7971 fsts fpul,%0
7972 flds %1,fpul
7973 lds.l %1,%0
7974 #
7975 sts %1,%0
7976 lds %1,%0
7977 sts.l %1,%0
7978 lds.l %1,%0
7979 ! move optimized away"
7980 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
7981 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
7982 (set_attr_alternative "length"
7983 [(const_int 2)
7984 (const_int 2)
7985 (const_int 2)
7986 (const_int 2)
7987 (const_int 4)
7988 (if_then_else
7989 (match_test "TARGET_SH2A")
7990 (const_int 4) (const_int 2))
7991 (if_then_else
7992 (match_test "TARGET_SH2A")
7993 (const_int 4) (const_int 2))
7994 (const_int 2)
7995 (if_then_else
7996 (match_test "TARGET_SH2A")
7997 (const_int 4) (const_int 2))
7998 (if_then_else
7999 (match_test "TARGET_SH2A")
8000 (const_int 4) (const_int 2))
8001 (const_int 2)
8002 (const_int 2)
8003 (const_int 2)
8004 (const_int 4)
8005 (const_int 2)
8006 (const_int 2)
8007 (const_int 2)
8008 (const_int 2)
8009 (const_int 0)])
8010 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8011 (const_string "single")
8012 (const_string "single")))])
8013
8014 (define_split
8015 [(set (match_operand:SF 0 "register_operand" "")
8016 (match_operand:SF 1 "register_operand" ""))
8017 (use (match_operand:PSI 2 "fpscr_operand" ""))
8018 (clobber (reg:SI FPUL_REG))]
8019 "TARGET_SH1"
8020 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
8021 (use (match_dup 2))
8022 (clobber (scratch:SI))])
8023 (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
8024 (use (match_dup 2))
8025 (clobber (scratch:SI))])]
8026 "")
8027
8028 (define_expand "movsf"
8029 [(set (match_operand:SF 0 "general_movdst_operand" "")
8030 (match_operand:SF 1 "general_movsrc_operand" ""))]
8031 ""
8032 {
8033 prepare_move_operands (operands, SFmode);
8034 if (TARGET_SHMEDIA)
8035 {
8036 if (TARGET_SHMEDIA_FPU)
8037 emit_insn (gen_movsf_media (operands[0], operands[1]));
8038 else
8039 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8040 DONE;
8041 }
8042 if (TARGET_SH2E)
8043 {
8044 emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
8045 DONE;
8046 }
8047 })
8048
8049 (define_insn "mov_nop"
8050 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
8051 "TARGET_SH2E"
8052 ""
8053 [(set_attr "length" "0")
8054 (set_attr "type" "nil")])
8055
8056 (define_expand "reload_insf__frn"
8057 [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
8058 (match_operand:SF 1 "immediate_operand" "FQ"))
8059 (use (reg:PSI FPSCR_REG))
8060 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8061 "TARGET_SH1"
8062 "")
8063
8064 (define_expand "reload_insi__i_fpul"
8065 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
8066 (match_operand:SI 1 "immediate_operand" "i"))
8067 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8068 "TARGET_SH1"
8069 "")
8070
8071 (define_expand "ptabs"
8072 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
8073 "TARGET_SHMEDIA"
8074 {
8075 if (!TARGET_PT_FIXED)
8076 {
8077 rtx eq = operands[1];
8078
8079 /* ??? For canonical RTL we really should remove any CONST from EQ
8080 before wrapping it in the AND, and finally wrap the EQ into a
8081 const if is constant. However, for reload we must expose the
8082 input register or symbolic constant, and we can't have
8083 different insn structures outside of the operands for different
8084 alternatives of the same pattern. */
8085 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
8086 GEN_INT (3));
8087 operands[1]
8088 = (gen_rtx_IF_THEN_ELSE
8089 (PDImode,
8090 eq,
8091 gen_rtx_MEM (PDImode, operands[1]),
8092 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
8093 PDImode, operands[1])));
8094 }
8095 })
8096
8097 ;; expanded by ptabs expander.
8098 (define_insn "*extendsipdi_media"
8099 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8100 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
8101 "r,Csy")
8102 (const_int 3))
8103 (const_int 3))
8104 (mem:PDI (match_dup 1))
8105 (sign_extend:PDI (match_dup 1))))]
8106 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8107 "@
8108 ptabs %1, %0
8109 pt %1, %0"
8110 [(set_attr "type" "ptabs_media,pt_media")
8111 (set_attr "length" "4,*")])
8112
8113 (define_insn "*truncdipdi_media"
8114 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
8115 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
8116 "r,Csy")
8117 (const_int 3))
8118 (const_int 3))
8119 (mem:PDI (match_dup 1))
8120 (truncate:PDI (match_dup 1))))]
8121 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
8122 "@
8123 ptabs %1, %0
8124 pt %1, %0"
8125 [(set_attr "type" "ptabs_media,pt_media")
8126 (set_attr "length" "4,*")])
8127
8128 (define_insn "*movsi_y"
8129 [(set (match_operand:SI 0 "register_operand" "=y,y")
8130 (match_operand:SI 1 "immediate_operand" "Qi,I08"))
8131 (clobber (match_scratch:SI 2 "=&z,r"))]
8132 "TARGET_SH2E
8133 && (reload_in_progress || reload_completed)"
8134 "#"
8135 [(set_attr "length" "4")
8136 (set_attr "type" "pcload,move")])
8137
8138 (define_split
8139 [(set (match_operand:SI 0 "register_operand" "")
8140 (match_operand:SI 1 "immediate_operand" ""))
8141 (clobber (match_operand:SI 2 "register_operand" ""))]
8142 "TARGET_SH1"
8143 [(set (match_dup 2) (match_dup 1))
8144 (set (match_dup 0) (match_dup 2))]
8145 "")
8146 \f
8147 ;; ------------------------------------------------------------------------
8148 ;; Define the real conditional branch instructions.
8149 ;; ------------------------------------------------------------------------
8150
8151 (define_expand "branch_true"
8152 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
8153 (label_ref (match_operand 0))
8154 (pc)))]
8155 "TARGET_SH1")
8156
8157 (define_expand "branch_false"
8158 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8159 (label_ref (match_operand 0))
8160 (pc)))]
8161 "TARGET_SH1")
8162
8163 (define_insn_and_split "*cbranch_t"
8164 [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
8165 (label_ref (match_operand 0))
8166 (pc)))]
8167 "TARGET_SH1"
8168 {
8169 return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
8170 }
8171 "&& can_create_pseudo_p ()"
8172 [(set (pc) (if_then_else (eq (reg:SI T_REG) (match_dup 2))
8173 (label_ref (match_dup 0))
8174 (pc)))]
8175 {
8176 /* Try to find missed test and branch combine opportunities which result
8177 in redundant T bit tests before conditional branches.
8178 FIXME: Probably this would not be needed if CCmode was used
8179 together with TARGET_FIXED_CONDITION_CODE_REGS. */
8180
8181 const int treg_value = sh_eval_treg_value (operands[1]);
8182 operands[2] = NULL_RTX;
8183
8184 /* Scan the insns backwards for an insn that sets the T bit by testing a
8185 reg against zero like:
8186 (set (reg T_REG) (eq (reg) (const_int 0))) */
8187 rtx testing_insn = NULL_RTX;
8188 rtx tested_reg = NULL_RTX;
8189
8190 set_of_reg s0 = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn,
8191 prev_nonnote_insn_bb);
8192 if (s0.set_src != NULL_RTX
8193 && GET_CODE (s0.set_src) == EQ
8194 && REG_P (XEXP (s0.set_src, 0))
8195 && satisfies_constraint_Z (XEXP (s0.set_src, 1)))
8196 {
8197 testing_insn = s0.insn;
8198 tested_reg = XEXP (s0.set_src, 0);
8199 }
8200 else
8201 FAIL;
8202
8203 /* Continue scanning the insns backwards and try to find the insn that
8204 sets the tested reg which we found above. If the reg is set by storing
8205 the T bit or the negated T bit we can eliminate the test insn before
8206 the branch. Notice that the branch condition has to be inverted if the
8207 test is eliminated. */
8208
8209 /* If the T bit is used between the testing insn and the brach insn
8210 leave it alone. */
8211 if (reg_used_between_p (get_t_reg_rtx (), testing_insn, curr_insn))
8212 FAIL;
8213
8214 while (true)
8215 {
8216 set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn,
8217 prev_nonnote_insn_bb);
8218 if (s1.set_src == NULL_RTX)
8219 break;
8220
8221 if (t_reg_operand (s1.set_src, VOIDmode))
8222 operands[2] = GEN_INT (treg_value ^ 1);
8223 else if (negt_reg_operand (s1.set_src, VOIDmode))
8224 operands[2] = GEN_INT (treg_value);
8225 else if (REG_P (s1.set_src))
8226 {
8227 /* If it's a reg-reg copy follow the copied reg. This can
8228 happen e.g. when T bit store zero-extensions are
8229 eliminated. */
8230 tested_reg = s1.set_src;
8231 s0.insn = s1.insn;
8232 continue;
8233 }
8234
8235 /* It's only safe to remove the testing insn if the T bit is not
8236 modified between the testing insn and the insn that stores the
8237 T bit. Notice that some T bit stores such as negc also modify
8238 the T bit. */
8239 if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn)
8240 || modified_in_p (get_t_reg_rtx (), s1.insn))
8241 operands[2] = NULL_RTX;
8242
8243 break;
8244 }
8245
8246 if (operands[2] == NULL_RTX)
8247 FAIL;
8248
8249 set_insn_deleted (testing_insn);
8250 }
8251 [(set_attr "type" "cbranch")])
8252
8253 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
8254 ;; which destination is too far away.
8255 ;; The const_int_operand is distinct for each branch target; it avoids
8256 ;; unwanted matches with redundant_insn.
8257 (define_insn "block_branch_redirect"
8258 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
8259 "TARGET_SH1"
8260 ""
8261 [(set_attr "length" "0")])
8262
8263 ;; This one has the additional purpose to record a possible scratch register
8264 ;; for the following branch.
8265 ;; ??? Unfortunately, just setting the scratch register is not good enough,
8266 ;; because the insn then might be deemed dead and deleted. And we can't
8267 ;; make the use in the jump insn explicit because that would disable
8268 ;; delay slot scheduling from the target.
8269 (define_insn "indirect_jump_scratch"
8270 [(set (match_operand:SI 0 "register_operand" "=r")
8271 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
8272 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
8273 "TARGET_SH1"
8274 ""
8275 [(set_attr "length" "0")])
8276
8277 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
8278 ;; being pulled into the delay slot of a condbranch that has been made to
8279 ;; jump around the unconditional jump because it was out of range.
8280 (define_insn "stuff_delay_slot"
8281 [(set (pc)
8282 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
8283 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
8284 "TARGET_SH1"
8285 ""
8286 [(set_attr "length" "0")
8287 (set_attr "cond_delay_slot" "yes")])
8288 \f
8289 ;; Conditional branch insns
8290
8291 (define_expand "cbranchint4_media"
8292 [(set (pc)
8293 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
8294 [(match_operand 1 "" "")
8295 (match_operand 2 "" "")])
8296 (match_operand 3 "" "")
8297 (pc)))]
8298 "TARGET_SHMEDIA"
8299 {
8300 enum machine_mode mode = GET_MODE (operands[1]);
8301 if (mode == VOIDmode)
8302 mode = GET_MODE (operands[2]);
8303 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
8304 {
8305 operands[1] = force_reg (mode, operands[1]);
8306 if (CONSTANT_P (operands[2])
8307 && (! satisfies_constraint_I06 (operands[2])))
8308 operands[2] = force_reg (mode, operands[2]);
8309 }
8310 else
8311 {
8312 if (operands[1] != const0_rtx)
8313 operands[1] = force_reg (mode, operands[1]);
8314 if (operands[2] != const0_rtx)
8315 operands[2] = force_reg (mode, operands[2]);
8316 }
8317 switch (GET_CODE (operands[0]))
8318 {
8319 case LEU:
8320 case LE:
8321 case LTU:
8322 case LT:
8323 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
8324 VOIDmode, operands[2], operands[1]);
8325 operands[1] = XEXP (operands[0], 0);
8326 operands[2] = XEXP (operands[0], 1);
8327 break;
8328 default:
8329 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
8330 VOIDmode, operands[1], operands[2]);
8331 break;
8332 }
8333 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8334 })
8335
8336 (define_expand "cbranchfp4_media"
8337 [(set (pc)
8338 (if_then_else (match_operator 0 "sh_float_comparison_operator"
8339 [(match_operand 1 "" "")
8340 (match_operand 2 "" "")])
8341 (match_operand 3 "" "")
8342 (pc)))]
8343 "TARGET_SHMEDIA"
8344 {
8345 rtx tmp = gen_reg_rtx (SImode);
8346 rtx cmp;
8347 if (GET_CODE (operands[0]) == NE)
8348 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
8349 else
8350 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
8351 operands[1], operands[2]);
8352
8353 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
8354
8355 if (GET_CODE (cmp) == GET_CODE (operands[0]))
8356 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
8357 else
8358 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
8359 operands[1] = tmp;
8360 operands[2] = const0_rtx;
8361 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
8362 })
8363
8364 (define_insn "*beq_media_i"
8365 [(set (pc)
8366 (if_then_else (match_operator 3 "equality_comparison_operator"
8367 [(match_operand:DI 1 "arith_reg_operand" "r,r")
8368 (match_operand:DI 2 "arith_operand" "r,I06")])
8369 (match_operand 0 "target_operand" "b,b")
8370 (pc)))]
8371 "TARGET_SHMEDIA"
8372 "@
8373 b%o3%' %1, %2, %0%>
8374 b%o3i%' %1, %2, %0%>"
8375 [(set_attr "type" "cbranch_media")])
8376
8377 (define_insn "*beq_media_i32"
8378 [(set (pc)
8379 (if_then_else (match_operator 3 "equality_comparison_operator"
8380 [(match_operand:SI 1 "arith_reg_operand" "r,r")
8381 (match_operand:SI 2 "arith_operand" "r,I06")])
8382 (match_operand 0 "target_operand" "b,b")
8383 (pc)))]
8384 "TARGET_SHMEDIA"
8385 "@
8386 b%o3%' %1, %2, %0%>
8387 b%o3i%' %1, %2, %0%>"
8388 [(set_attr "type" "cbranch_media")])
8389
8390 (define_insn "*bgt_media_i"
8391 [(set (pc)
8392 (if_then_else (match_operator 3 "greater_comparison_operator"
8393 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8394 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8395 (match_operand 0 "target_operand" "b")
8396 (pc)))]
8397 "TARGET_SHMEDIA"
8398 "b%o3%' %N1, %N2, %0%>"
8399 [(set_attr "type" "cbranch_media")])
8400
8401 (define_insn "*bgt_media_i32"
8402 [(set (pc)
8403 (if_then_else (match_operator 3 "greater_comparison_operator"
8404 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8405 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8406 (match_operand 0 "target_operand" "b")
8407 (pc)))]
8408 "TARGET_SHMEDIA"
8409 "b%o3%' %N1, %N2, %0%>"
8410 [(set_attr "type" "cbranch_media")])
8411
8412 ;; These are only needed to make invert_jump() happy - otherwise, jump
8413 ;; optimization will be silently disabled.
8414 (define_insn "*blt_media_i"
8415 [(set (pc)
8416 (if_then_else (match_operator 3 "less_comparison_operator"
8417 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
8418 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
8419 (match_operand 0 "target_operand" "b")
8420 (pc)))]
8421 "TARGET_SHMEDIA"
8422 "b%o3%' %N2, %N1, %0%>"
8423 [(set_attr "type" "cbranch_media")])
8424
8425 (define_insn "*blt_media_i32"
8426 [(set (pc)
8427 (if_then_else (match_operator 3 "less_comparison_operator"
8428 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
8429 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
8430 (match_operand 0 "target_operand" "b")
8431 (pc)))]
8432 "TARGET_SHMEDIA"
8433 "b%o3%' %N2, %N1, %0%>"
8434 [(set_attr "type" "cbranch_media")])
8435
8436 ;; combiner splitter for test-and-branch on single bit in register. This
8437 ;; is endian dependent because the non-paradoxical subreg looks different
8438 ;; on big endian.
8439 (define_split
8440 [(set (pc)
8441 (if_then_else
8442 (match_operator 3 "equality_comparison_operator"
8443 [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1
8444 "extend_reg_operand" "")
8445 0)
8446 (const_int 1)
8447 (match_operand 2
8448 "const_int_operand" "")) 0)
8449 (const_int 0)])
8450 (match_operand 0 "target_operand" "")
8451 (pc)))
8452 (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
8453 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
8454 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
8455 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
8456 {
8457 operands[5] = GEN_INT (31 - INTVAL (operands[2]));
8458 operands[6] = (GET_CODE (operands[3]) == EQ
8459 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
8460 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
8461 })
8462
8463 ; operand 0 is the loop count pseudo register
8464 ; operand 1 is the number of loop iterations or 0 if it is unknown
8465 ; operand 2 is the maximum number of loop iterations
8466 ; operand 3 is the number of levels of enclosed loops
8467 ; operand 4 is the label to jump to at the top of the loop
8468
8469 (define_expand "doloop_end"
8470 [(parallel [(set (pc) (if_then_else
8471 (ne:SI (match_operand:SI 0 "" "")
8472 (const_int 1))
8473 (label_ref (match_operand 4 "" ""))
8474 (pc)))
8475 (set (match_dup 0)
8476 (plus:SI (match_dup 0) (const_int -1)))
8477 (clobber (reg:SI T_REG))])
8478 (match_operand 5 "" "")]
8479 "TARGET_SH2"
8480 {
8481 if (GET_MODE (operands[0]) != SImode)
8482 FAIL;
8483 emit_insn (gen_doloop_end_split (operands[0], operands[4], operands[0]));
8484 DONE;
8485 })
8486
8487 (define_insn_and_split "doloop_end_split"
8488 [(set (pc)
8489 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
8490 (const_int 1))
8491 (label_ref (match_operand 1 "" ""))
8492 (pc)))
8493 (set (match_operand:SI 0 "arith_reg_dest" "=r")
8494 (plus (match_dup 2) (const_int -1)))
8495 (clobber (reg:SI T_REG))]
8496 "TARGET_SH2"
8497 "#"
8498 ""
8499 [(parallel [(set (reg:SI T_REG)
8500 (eq:SI (match_dup 2) (const_int 1)))
8501 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
8502 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
8503 (label_ref (match_dup 1))
8504 (pc)))]
8505 ""
8506 [(set_attr "type" "cbranch")])
8507
8508 \f
8509 ;; ------------------------------------------------------------------------
8510 ;; Jump and linkage insns
8511 ;; ------------------------------------------------------------------------
8512
8513 (define_insn "jump_compact"
8514 [(set (pc)
8515 (label_ref (match_operand 0 "" "")))]
8516 "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
8517 {
8518 /* The length is 16 if the delay slot is unfilled. */
8519 if (get_attr_length(insn) > 4)
8520 return output_far_jump(insn, operands[0]);
8521 else
8522 return "bra %l0%#";
8523 }
8524 [(set_attr "type" "jump")
8525 (set_attr "needs_delay_slot" "yes")])
8526
8527 ;; ??? It would be much saner to explicitly use the scratch register
8528 ;; in the jump insn, and have indirect_jump_scratch only set it,
8529 ;; but fill_simple_delay_slots would refuse to do delay slot filling
8530 ;; from the target then, as it uses simplejump_p.
8531 ;;(define_insn "jump_compact_far"
8532 ;; [(set (pc)
8533 ;; (label_ref (match_operand 0 "" "")))
8534 ;; (use (match_operand 1 "register_operand" "r")]
8535 ;; "TARGET_SH1"
8536 ;; "* return output_far_jump(insn, operands[0], operands[1]);"
8537 ;; [(set_attr "type" "jump")
8538 ;; (set_attr "needs_delay_slot" "yes")])
8539
8540 (define_insn "jump_media"
8541 [(set (pc)
8542 (match_operand 0 "target_operand" "b"))]
8543 "TARGET_SHMEDIA"
8544 "blink %0, r63%>"
8545 [(set_attr "type" "jump_media")])
8546
8547 (define_expand "jump"
8548 [(set (pc)
8549 (label_ref (match_operand 0 "" "")))]
8550 ""
8551 {
8552 if (TARGET_SH1)
8553 emit_jump_insn (gen_jump_compact (operands[0]));
8554 else if (TARGET_SHMEDIA)
8555 {
8556 if (reload_in_progress || reload_completed)
8557 FAIL;
8558 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode,
8559 operands[0])));
8560 }
8561 DONE;
8562 })
8563
8564 (define_insn "force_mode_for_call"
8565 [(use (reg:PSI FPSCR_REG))]
8566 "TARGET_SHCOMPACT"
8567 ""
8568 [(set_attr "length" "0")
8569 (set (attr "fp_mode")
8570 (if_then_else (eq_attr "fpu_single" "yes")
8571 (const_string "single") (const_string "double")))])
8572
8573 (define_insn "calli"
8574 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8575 (match_operand 1 "" ""))
8576 (use (reg:PSI FPSCR_REG))
8577 (clobber (reg:SI PR_REG))]
8578 "TARGET_SH1"
8579 {
8580 if (TARGET_SH2A && (dbr_sequence_length () == 0))
8581 return "jsr/n @%0";
8582 else
8583 return "jsr @%0%#";
8584 }
8585 [(set_attr "type" "call")
8586 (set (attr "fp_mode")
8587 (if_then_else (eq_attr "fpu_single" "yes")
8588 (const_string "single") (const_string "double")))
8589 (set_attr "needs_delay_slot" "yes")
8590 (set_attr "fp_set" "unknown")])
8591
8592 ;; This is TBR relative jump instruction for SH2A architecture.
8593 ;; Its use is enabled assigning an attribute "function_vector"
8594 ;; and the vector number to a function during its declaration.
8595
8596 (define_insn "calli_tbr_rel"
8597 [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
8598 (match_operand 1 "" ""))
8599 (use (reg:PSI FPSCR_REG))
8600 (clobber (reg:SI PR_REG))]
8601 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
8602 {
8603 unsigned HOST_WIDE_INT vect_num;
8604 vect_num = sh2a_get_function_vector_number (operands[0]);
8605 operands[2] = GEN_INT (vect_num * 4);
8606
8607 return "jsr/n @@(%O2,tbr)";
8608 }
8609 [(set_attr "type" "call")
8610 (set (attr "fp_mode")
8611 (if_then_else (eq_attr "fpu_single" "yes")
8612 (const_string "single") (const_string "double")))
8613 (set_attr "needs_delay_slot" "no")
8614 (set_attr "fp_set" "unknown")])
8615
8616 ;; This is a pc-rel call, using bsrf, for use with PIC.
8617
8618 (define_insn "calli_pcrel"
8619 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8620 (match_operand 1 "" ""))
8621 (use (reg:PSI FPSCR_REG))
8622 (use (reg:SI PIC_REG))
8623 (use (match_operand 2 "" ""))
8624 (clobber (reg:SI PR_REG))]
8625 "TARGET_SH2"
8626 {
8627 return "bsrf %0" "\n"
8628 "%O2:%#";
8629 }
8630 [(set_attr "type" "call")
8631 (set (attr "fp_mode")
8632 (if_then_else (eq_attr "fpu_single" "yes")
8633 (const_string "single") (const_string "double")))
8634 (set_attr "needs_delay_slot" "yes")
8635 (set_attr "fp_set" "unknown")])
8636
8637 (define_insn_and_split "call_pcrel"
8638 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
8639 (match_operand 1 "" ""))
8640 (use (reg:PSI FPSCR_REG))
8641 (use (reg:SI PIC_REG))
8642 (clobber (reg:SI PR_REG))
8643 (clobber (match_scratch:SI 2 "=r"))]
8644 "TARGET_SH2"
8645 "#"
8646 "reload_completed"
8647 [(const_int 0)]
8648 {
8649 rtx lab = PATTERN (gen_call_site ());
8650
8651 if (SYMBOL_REF_LOCAL_P (operands[0]))
8652 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
8653 else
8654 emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
8655 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
8656 DONE;
8657 }
8658 [(set_attr "type" "call")
8659 (set (attr "fp_mode")
8660 (if_then_else (eq_attr "fpu_single" "yes")
8661 (const_string "single") (const_string "double")))
8662 (set_attr "needs_delay_slot" "yes")
8663 (set_attr "fp_set" "unknown")])
8664
8665 (define_insn "call_compact"
8666 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8667 (match_operand 1 "" ""))
8668 (match_operand 2 "immediate_operand" "n")
8669 (use (reg:SI R0_REG))
8670 (use (reg:SI R1_REG))
8671 (use (reg:PSI FPSCR_REG))
8672 (clobber (reg:SI PR_REG))]
8673 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8674 "jsr @%0%#"
8675 [(set_attr "type" "call")
8676 (set (attr "fp_mode")
8677 (if_then_else (eq_attr "fpu_single" "yes")
8678 (const_string "single") (const_string "double")))
8679 (set_attr "needs_delay_slot" "yes")])
8680
8681 (define_insn "call_compact_rettramp"
8682 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8683 (match_operand 1 "" ""))
8684 (match_operand 2 "immediate_operand" "n")
8685 (use (reg:SI R0_REG))
8686 (use (reg:SI R1_REG))
8687 (use (reg:PSI FPSCR_REG))
8688 (clobber (reg:SI R10_REG))
8689 (clobber (reg:SI PR_REG))]
8690 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8691 "jsr @%0%#"
8692 [(set_attr "type" "call")
8693 (set (attr "fp_mode")
8694 (if_then_else (eq_attr "fpu_single" "yes")
8695 (const_string "single") (const_string "double")))
8696 (set_attr "needs_delay_slot" "yes")])
8697
8698 (define_insn "call_media"
8699 [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
8700 (match_operand 1 "" ""))
8701 (clobber (reg:DI PR_MEDIA_REG))]
8702 "TARGET_SHMEDIA"
8703 "blink %0, r18"
8704 [(set_attr "type" "jump_media")])
8705
8706 (define_insn "call_valuei"
8707 [(set (match_operand 0 "" "=rf")
8708 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8709 (match_operand 2 "" "")))
8710 (use (reg:PSI FPSCR_REG))
8711 (clobber (reg:SI PR_REG))]
8712 "TARGET_SH1"
8713 {
8714 if (TARGET_SH2A && (dbr_sequence_length () == 0))
8715 return "jsr/n @%1";
8716 else
8717 return "jsr @%1%#";
8718 }
8719 [(set_attr "type" "call")
8720 (set (attr "fp_mode")
8721 (if_then_else (eq_attr "fpu_single" "yes")
8722 (const_string "single") (const_string "double")))
8723 (set_attr "needs_delay_slot" "yes")
8724 (set_attr "fp_set" "unknown")])
8725
8726 ;; This is TBR relative jump instruction for SH2A architecture.
8727 ;; Its use is enabled by assigning an attribute "function_vector"
8728 ;; and the vector number to a function during its declaration.
8729
8730 (define_insn "call_valuei_tbr_rel"
8731 [(set (match_operand 0 "" "=rf")
8732 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8733 (match_operand 2 "" "")))
8734 (use (reg:PSI FPSCR_REG))
8735 (clobber (reg:SI PR_REG))]
8736 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
8737 {
8738 unsigned HOST_WIDE_INT vect_num;
8739 vect_num = sh2a_get_function_vector_number (operands[1]);
8740 operands[3] = GEN_INT (vect_num * 4);
8741
8742 return "jsr/n @@(%O3,tbr)";
8743 }
8744 [(set_attr "type" "call")
8745 (set (attr "fp_mode")
8746 (if_then_else (eq_attr "fpu_single" "yes")
8747 (const_string "single") (const_string "double")))
8748 (set_attr "needs_delay_slot" "no")
8749 (set_attr "fp_set" "unknown")])
8750
8751 (define_insn "call_valuei_pcrel"
8752 [(set (match_operand 0 "" "=rf")
8753 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8754 (match_operand 2 "" "")))
8755 (use (reg:PSI FPSCR_REG))
8756 (use (reg:SI PIC_REG))
8757 (use (match_operand 3 "" ""))
8758 (clobber (reg:SI PR_REG))]
8759 "TARGET_SH2"
8760 {
8761 return "bsrf %1" "\n"
8762 "%O3:%#";
8763 }
8764 [(set_attr "type" "call")
8765 (set (attr "fp_mode")
8766 (if_then_else (eq_attr "fpu_single" "yes")
8767 (const_string "single") (const_string "double")))
8768 (set_attr "needs_delay_slot" "yes")
8769 (set_attr "fp_set" "unknown")])
8770
8771 (define_insn_and_split "call_value_pcrel"
8772 [(set (match_operand 0 "" "=rf")
8773 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
8774 (match_operand 2 "" "")))
8775 (use (reg:PSI FPSCR_REG))
8776 (use (reg:SI PIC_REG))
8777 (clobber (reg:SI PR_REG))
8778 (clobber (match_scratch:SI 3 "=r"))]
8779 "TARGET_SH2"
8780 "#"
8781 "reload_completed"
8782 [(const_int 0)]
8783 {
8784 rtx lab = PATTERN (gen_call_site ());
8785
8786 if (SYMBOL_REF_LOCAL_P (operands[1]))
8787 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
8788 else
8789 emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
8790 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
8791 operands[2], copy_rtx (lab)));
8792 DONE;
8793 }
8794 [(set_attr "type" "call")
8795 (set (attr "fp_mode")
8796 (if_then_else (eq_attr "fpu_single" "yes")
8797 (const_string "single") (const_string "double")))
8798 (set_attr "needs_delay_slot" "yes")
8799 (set_attr "fp_set" "unknown")])
8800
8801 (define_insn "call_value_compact"
8802 [(set (match_operand 0 "" "=rf")
8803 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8804 (match_operand 2 "" "")))
8805 (match_operand 3 "immediate_operand" "n")
8806 (use (reg:SI R0_REG))
8807 (use (reg:SI R1_REG))
8808 (use (reg:PSI FPSCR_REG))
8809 (clobber (reg:SI PR_REG))]
8810 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8811 "jsr @%1%#"
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" "yes")])
8817
8818 (define_insn "call_value_compact_rettramp"
8819 [(set (match_operand 0 "" "=rf")
8820 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
8821 (match_operand 2 "" "")))
8822 (match_operand 3 "immediate_operand" "n")
8823 (use (reg:SI R0_REG))
8824 (use (reg:SI R1_REG))
8825 (use (reg:PSI FPSCR_REG))
8826 (clobber (reg:SI R10_REG))
8827 (clobber (reg:SI PR_REG))]
8828 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
8829 "jsr @%1%#"
8830 [(set_attr "type" "call")
8831 (set (attr "fp_mode")
8832 (if_then_else (eq_attr "fpu_single" "yes")
8833 (const_string "single") (const_string "double")))
8834 (set_attr "needs_delay_slot" "yes")])
8835
8836 (define_insn "call_value_media"
8837 [(set (match_operand 0 "" "=rf")
8838 (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
8839 (match_operand 2 "" "")))
8840 (clobber (reg:DI PR_MEDIA_REG))]
8841 "TARGET_SHMEDIA"
8842 "blink %1, r18"
8843 [(set_attr "type" "jump_media")])
8844
8845 (define_expand "call"
8846 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
8847 (match_operand 1 "" ""))
8848 (match_operand 2 "" "")
8849 (use (reg:PSI FPSCR_REG))
8850 (clobber (reg:SI PR_REG))])]
8851 ""
8852 {
8853 if (TARGET_SHMEDIA)
8854 {
8855 operands[0] = shmedia_prepare_call_address (operands[0], 0);
8856 emit_call_insn (gen_call_media (operands[0], operands[1]));
8857 DONE;
8858 }
8859 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
8860 {
8861 rtx cookie_rtx = operands[2];
8862 long cookie = INTVAL (cookie_rtx);
8863 rtx func = XEXP (operands[0], 0);
8864 rtx r0, r1;
8865
8866 if (flag_pic)
8867 {
8868 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8869 {
8870 rtx reg = gen_reg_rtx (Pmode);
8871
8872 emit_insn (gen_symGOTPLT2reg (reg, func));
8873 func = reg;
8874 }
8875 else
8876 func = legitimize_pic_address (func, Pmode, 0);
8877 }
8878
8879 r0 = gen_rtx_REG (SImode, R0_REG);
8880 r1 = gen_rtx_REG (SImode, R1_REG);
8881
8882 /* Since such a call function may use all call-clobbered
8883 registers, we force a mode switch earlier, so that we don't
8884 run out of registers when adjusting fpscr for the call. */
8885 emit_insn (gen_force_mode_for_call ());
8886
8887 operands[0]
8888 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
8889 operands[0] = force_reg (SImode, operands[0]);
8890
8891 emit_move_insn (r0, func);
8892 emit_move_insn (r1, cookie_rtx);
8893
8894 if (cookie & CALL_COOKIE_RET_TRAMP (1))
8895 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
8896 operands[2]));
8897 else
8898 emit_call_insn (gen_call_compact (operands[0], operands[1],
8899 operands[2]));
8900
8901 DONE;
8902 }
8903 else if (TARGET_SHCOMPACT && flag_pic
8904 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8905 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
8906 {
8907 rtx reg = gen_reg_rtx (Pmode);
8908
8909 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
8910 XEXP (operands[0], 0) = reg;
8911 }
8912 if (!flag_pic && TARGET_SH2A
8913 && MEM_P (operands[0])
8914 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
8915 {
8916 if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
8917 {
8918 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
8919 operands[1]));
8920 DONE;
8921 }
8922 }
8923 if (flag_pic && TARGET_SH2
8924 && MEM_P (operands[0])
8925 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
8926 {
8927 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
8928 DONE;
8929 }
8930 else
8931 {
8932 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
8933 operands[1] = operands[2];
8934 }
8935
8936 emit_call_insn (gen_calli (operands[0], operands[1]));
8937 DONE;
8938 })
8939
8940 (define_insn "call_pop_compact"
8941 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8942 (match_operand 1 "" ""))
8943 (match_operand 2 "immediate_operand" "n")
8944 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8945 (match_operand 3 "immediate_operand" "n")))
8946 (use (reg:SI R0_REG))
8947 (use (reg:SI R1_REG))
8948 (use (reg:PSI FPSCR_REG))
8949 (clobber (reg:SI PR_REG))]
8950 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8951 "jsr @%0%#"
8952 [(set_attr "type" "call")
8953 (set (attr "fp_mode")
8954 (if_then_else (eq_attr "fpu_single" "yes")
8955 (const_string "single") (const_string "double")))
8956 (set_attr "needs_delay_slot" "yes")])
8957
8958 (define_insn "call_pop_compact_rettramp"
8959 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
8960 (match_operand 1 "" ""))
8961 (match_operand 2 "immediate_operand" "n")
8962 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8963 (match_operand 3 "immediate_operand" "n")))
8964 (use (reg:SI R0_REG))
8965 (use (reg:SI R1_REG))
8966 (use (reg:PSI FPSCR_REG))
8967 (clobber (reg:SI R10_REG))
8968 (clobber (reg:SI PR_REG))]
8969 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
8970 "jsr @%0%#"
8971 [(set_attr "type" "call")
8972 (set (attr "fp_mode")
8973 (if_then_else (eq_attr "fpu_single" "yes")
8974 (const_string "single") (const_string "double")))
8975 (set_attr "needs_delay_slot" "yes")])
8976
8977 (define_expand "call_pop"
8978 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
8979 (match_operand 1 "" ""))
8980 (match_operand 2 "" "")
8981 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
8982 (match_operand 3 "" "")))])]
8983 "TARGET_SHCOMPACT"
8984 {
8985 rtx cookie_rtx;
8986 long cookie;
8987 rtx func;
8988 rtx r0, r1;
8989
8990 gcc_assert (operands[2] && INTVAL (operands[2]));
8991 cookie_rtx = operands[2];
8992 cookie = INTVAL (cookie_rtx);
8993 func = XEXP (operands[0], 0);
8994
8995 if (flag_pic)
8996 {
8997 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
8998 {
8999 rtx reg = gen_reg_rtx (Pmode);
9000 emit_insn (gen_symGOTPLT2reg (reg, func));
9001 func = reg;
9002 }
9003 else
9004 func = legitimize_pic_address (func, Pmode, 0);
9005 }
9006
9007 r0 = gen_rtx_REG (SImode, R0_REG);
9008 r1 = gen_rtx_REG (SImode, R1_REG);
9009
9010 /* Since such a call function may use all call-clobbered
9011 registers, we force a mode switch earlier, so that we don't
9012 run out of registers when adjusting fpscr for the call. */
9013 emit_insn (gen_force_mode_for_call ());
9014
9015 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9016 SFUNC_GOT);
9017 operands[0] = force_reg (SImode, operands[0]);
9018
9019 emit_move_insn (r0, func);
9020 emit_move_insn (r1, cookie_rtx);
9021
9022 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9023 emit_call_insn (gen_call_pop_compact_rettramp
9024 (operands[0], operands[1], operands[2], operands[3]));
9025 else
9026 emit_call_insn (gen_call_pop_compact
9027 (operands[0], operands[1], operands[2], operands[3]));
9028
9029 DONE;
9030 })
9031
9032 (define_expand "call_value"
9033 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9034 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9035 (match_operand 2 "" "")))
9036 (match_operand 3 "" "")
9037 (use (reg:PSI FPSCR_REG))
9038 (clobber (reg:SI PR_REG))])]
9039 ""
9040 {
9041 if (TARGET_SHMEDIA)
9042 {
9043 operands[1] = shmedia_prepare_call_address (operands[1], 0);
9044 emit_call_insn (gen_call_value_media (operands[0], operands[1],
9045 operands[2]));
9046 DONE;
9047 }
9048 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9049 {
9050 rtx cookie_rtx = operands[3];
9051 long cookie = INTVAL (cookie_rtx);
9052 rtx func = XEXP (operands[1], 0);
9053 rtx r0, r1;
9054
9055 if (flag_pic)
9056 {
9057 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9058 {
9059 rtx reg = gen_reg_rtx (Pmode);
9060
9061 emit_insn (gen_symGOTPLT2reg (reg, func));
9062 func = reg;
9063 }
9064 else
9065 func = legitimize_pic_address (func, Pmode, 0);
9066 }
9067
9068 r0 = gen_rtx_REG (SImode, R0_REG);
9069 r1 = gen_rtx_REG (SImode, R1_REG);
9070
9071 /* Since such a call function may use all call-clobbered
9072 registers, we force a mode switch earlier, so that we don't
9073 run out of registers when adjusting fpscr for the call. */
9074 emit_insn (gen_force_mode_for_call ());
9075
9076 operands[1]
9077 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9078 operands[1] = force_reg (SImode, operands[1]);
9079
9080 emit_move_insn (r0, func);
9081 emit_move_insn (r1, cookie_rtx);
9082
9083 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9084 emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9085 operands[1],
9086 operands[2],
9087 operands[3]));
9088 else
9089 emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9090 operands[2], operands[3]));
9091
9092 DONE;
9093 }
9094 else if (TARGET_SHCOMPACT && flag_pic
9095 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9096 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9097 {
9098 rtx reg = gen_reg_rtx (Pmode);
9099
9100 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9101 XEXP (operands[1], 0) = reg;
9102 }
9103 if (!flag_pic && TARGET_SH2A
9104 && MEM_P (operands[1])
9105 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9106 {
9107 if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9108 {
9109 emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9110 XEXP (operands[1], 0), operands[2]));
9111 DONE;
9112 }
9113 }
9114 if (flag_pic && TARGET_SH2
9115 && MEM_P (operands[1])
9116 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9117 {
9118 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
9119 operands[2]));
9120 DONE;
9121 }
9122 else
9123 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9124
9125 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
9126 DONE;
9127 })
9128
9129 (define_insn "sibcalli"
9130 [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
9131 (match_operand 1 "" ""))
9132 (use (reg:PSI FPSCR_REG))
9133 (return)]
9134 "TARGET_SH1"
9135 "jmp @%0%#"
9136 [(set_attr "needs_delay_slot" "yes")
9137 (set (attr "fp_mode")
9138 (if_then_else (eq_attr "fpu_single" "yes")
9139 (const_string "single") (const_string "double")))
9140 (set_attr "type" "jump_ind")])
9141
9142 (define_insn "sibcalli_pcrel"
9143 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
9144 (match_operand 1 "" ""))
9145 (use (match_operand 2 "" ""))
9146 (use (reg:PSI FPSCR_REG))
9147 (return)]
9148 "TARGET_SH2"
9149 {
9150 return "braf %0" "\n"
9151 "%O2:%#";
9152 }
9153 [(set_attr "needs_delay_slot" "yes")
9154 (set (attr "fp_mode")
9155 (if_then_else (eq_attr "fpu_single" "yes")
9156 (const_string "single") (const_string "double")))
9157 (set_attr "type" "jump_ind")])
9158
9159 ;; This uses an unspec to describe that the symbol_ref is very close.
9160 (define_insn "sibcalli_thunk"
9161 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
9162 UNSPEC_THUNK))
9163 (match_operand 1 "" ""))
9164 (use (reg:PSI FPSCR_REG))
9165 (return)]
9166 "TARGET_SH1"
9167 "bra %O0"
9168 [(set_attr "needs_delay_slot" "yes")
9169 (set (attr "fp_mode")
9170 (if_then_else (eq_attr "fpu_single" "yes")
9171 (const_string "single") (const_string "double")))
9172 (set_attr "type" "jump")
9173 (set_attr "length" "2")])
9174
9175 (define_insn_and_split "sibcall_pcrel"
9176 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9177 (match_operand 1 "" ""))
9178 (use (reg:PSI FPSCR_REG))
9179 (clobber (match_scratch:SI 2 "=k"))
9180 (return)]
9181 "TARGET_SH2"
9182 "#"
9183 "reload_completed"
9184 [(const_int 0)]
9185 {
9186 rtx lab = PATTERN (gen_call_site ());
9187 rtx call_insn;
9188
9189 emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
9190 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
9191 copy_rtx (lab)));
9192 SIBLING_CALL_P (call_insn) = 1;
9193 DONE;
9194 }
9195 [(set_attr "needs_delay_slot" "yes")
9196 (set (attr "fp_mode")
9197 (if_then_else (eq_attr "fpu_single" "yes")
9198 (const_string "single") (const_string "double")))
9199 (set_attr "type" "jump_ind")])
9200
9201 (define_insn "sibcall_compact"
9202 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
9203 (match_operand 1 "" ""))
9204 (return)
9205 (use (match_operand:SI 2 "register_operand" "z,x"))
9206 (use (reg:SI R1_REG))
9207 (use (reg:PSI FPSCR_REG))
9208 ;; We want to make sure the `x' above will only match MACH_REG
9209 ;; because sibcall_epilogue may clobber MACL_REG.
9210 (clobber (reg:SI MACL_REG))]
9211 "TARGET_SHCOMPACT"
9212 {
9213 static const char* alt[] =
9214 {
9215 "jmp @%0%#",
9216
9217 "jmp @%0" "\n"
9218 " sts %2,r0"
9219 };
9220 return alt[which_alternative];
9221 }
9222 [(set_attr "needs_delay_slot" "yes,no")
9223 (set_attr "length" "2,4")
9224 (set (attr "fp_mode") (const_string "single"))
9225 (set_attr "type" "jump_ind")])
9226
9227 (define_insn "sibcall_media"
9228 [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
9229 (match_operand 1 "" ""))
9230 (use (reg:SI PR_MEDIA_REG))
9231 (return)]
9232 "TARGET_SHMEDIA"
9233 "blink %0, r63"
9234 [(set_attr "type" "jump_media")])
9235
9236 (define_expand "sibcall"
9237 [(parallel
9238 [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9239 (match_operand 1 "" ""))
9240 (match_operand 2 "" "")
9241 (use (reg:PSI FPSCR_REG))
9242 (return)])]
9243 ""
9244 {
9245 if (TARGET_SHMEDIA)
9246 {
9247 operands[0] = shmedia_prepare_call_address (operands[0], 1);
9248 emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
9249 DONE;
9250 }
9251 else if (TARGET_SHCOMPACT && operands[2]
9252 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9253 {
9254 rtx cookie_rtx = operands[2];
9255 long cookie = INTVAL (cookie_rtx);
9256 rtx func = XEXP (operands[0], 0);
9257 rtx mach, r1;
9258
9259 if (flag_pic)
9260 {
9261 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9262 {
9263 rtx reg = gen_reg_rtx (Pmode);
9264
9265 emit_insn (gen_symGOT2reg (reg, func));
9266 func = reg;
9267 }
9268 else
9269 func = legitimize_pic_address (func, Pmode, 0);
9270 }
9271
9272 /* FIXME: if we could tell whether all argument registers are
9273 already taken, we could decide whether to force the use of
9274 MACH_REG or to stick to R0_REG. Unfortunately, there's no
9275 simple way to tell. We could use the CALL_COOKIE, but we
9276 can't currently tell a register used for regular argument
9277 passing from one that is unused. If we leave it up to reload
9278 to decide which register to use, it seems to always choose
9279 R0_REG, which leaves no available registers in SIBCALL_REGS
9280 to hold the address of the trampoline. */
9281 mach = gen_rtx_REG (SImode, MACH_REG);
9282 r1 = gen_rtx_REG (SImode, R1_REG);
9283
9284 /* Since such a call function may use all call-clobbered
9285 registers, we force a mode switch earlier, so that we don't
9286 run out of registers when adjusting fpscr for the call. */
9287 emit_insn (gen_force_mode_for_call ());
9288
9289 operands[0]
9290 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9291 operands[0] = force_reg (SImode, operands[0]);
9292
9293 /* We don't need a return trampoline, since the callee will
9294 return directly to the upper caller. */
9295 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9296 {
9297 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9298 cookie_rtx = GEN_INT (cookie);
9299 }
9300
9301 emit_move_insn (mach, func);
9302 emit_move_insn (r1, cookie_rtx);
9303
9304 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
9305 DONE;
9306 }
9307 else if (TARGET_SHCOMPACT && flag_pic
9308 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9309 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9310 {
9311 rtx reg = gen_reg_rtx (Pmode);
9312
9313 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
9314 XEXP (operands[0], 0) = reg;
9315 }
9316 if (flag_pic && TARGET_SH2
9317 && MEM_P (operands[0])
9318 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9319 /* The PLT needs the PIC register, but the epilogue would have
9320 to restore it, so we can only use PC-relative PIC calls for
9321 static functions. */
9322 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9323 {
9324 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
9325 DONE;
9326 }
9327 else
9328 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9329
9330 emit_call_insn (gen_sibcalli (operands[0], operands[1]));
9331 DONE;
9332 })
9333
9334 (define_insn "sibcall_valuei"
9335 [(set (match_operand 0 "" "=rf")
9336 (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
9337 (match_operand 2 "" "")))
9338 (use (reg:PSI FPSCR_REG))
9339 (return)]
9340 "TARGET_SH1"
9341 "jmp @%1%#"
9342 [(set_attr "needs_delay_slot" "yes")
9343 (set (attr "fp_mode")
9344 (if_then_else (eq_attr "fpu_single" "yes")
9345 (const_string "single") (const_string "double")))
9346 (set_attr "type" "jump_ind")])
9347
9348 (define_insn "sibcall_valuei_pcrel"
9349 [(set (match_operand 0 "" "=rf")
9350 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
9351 (match_operand 2 "" "")))
9352 (use (match_operand 3 "" ""))
9353 (use (reg:PSI FPSCR_REG))
9354 (return)]
9355 "TARGET_SH2"
9356 {
9357 return "braf %1" "\n"
9358 "%O3:%#";
9359 }
9360 [(set_attr "needs_delay_slot" "yes")
9361 (set (attr "fp_mode")
9362 (if_then_else (eq_attr "fpu_single" "yes")
9363 (const_string "single") (const_string "double")))
9364 (set_attr "type" "jump_ind")])
9365
9366 (define_insn_and_split "sibcall_value_pcrel"
9367 [(set (match_operand 0 "" "=rf")
9368 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9369 (match_operand 2 "" "")))
9370 (use (reg:PSI FPSCR_REG))
9371 (clobber (match_scratch:SI 3 "=k"))
9372 (return)]
9373 "TARGET_SH2"
9374 "#"
9375 "reload_completed"
9376 [(const_int 0)]
9377 {
9378 rtx lab = PATTERN (gen_call_site ());
9379 rtx call_insn;
9380
9381 emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
9382 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
9383 operands[3],
9384 operands[2],
9385 copy_rtx (lab)));
9386 SIBLING_CALL_P (call_insn) = 1;
9387 DONE;
9388 }
9389 [(set_attr "needs_delay_slot" "yes")
9390 (set (attr "fp_mode")
9391 (if_then_else (eq_attr "fpu_single" "yes")
9392 (const_string "single") (const_string "double")))
9393 (set_attr "type" "jump_ind")])
9394
9395 (define_insn "sibcall_value_compact"
9396 [(set (match_operand 0 "" "=rf,rf")
9397 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
9398 (match_operand 2 "" "")))
9399 (return)
9400 (use (match_operand:SI 3 "register_operand" "z,x"))
9401 (use (reg:SI R1_REG))
9402 (use (reg:PSI FPSCR_REG))
9403 ;; We want to make sure the `x' above will only match MACH_REG
9404 ;; because sibcall_epilogue may clobber MACL_REG.
9405 (clobber (reg:SI MACL_REG))]
9406 "TARGET_SHCOMPACT"
9407 {
9408 static const char* alt[] =
9409 {
9410 "jmp @%1%#",
9411
9412 "jmp @%1" "\n"
9413 " sts %3,r0"
9414 };
9415 return alt[which_alternative];
9416 }
9417 [(set_attr "needs_delay_slot" "yes,no")
9418 (set_attr "length" "2,4")
9419 (set (attr "fp_mode") (const_string "single"))
9420 (set_attr "type" "jump_ind")])
9421
9422 (define_insn "sibcall_value_media"
9423 [(set (match_operand 0 "" "=rf")
9424 (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
9425 (match_operand 2 "" "")))
9426 (use (reg:SI PR_MEDIA_REG))
9427 (return)]
9428 "TARGET_SHMEDIA"
9429 "blink %1, r63"
9430 [(set_attr "type" "jump_media")])
9431
9432 (define_expand "sibcall_value"
9433 [(parallel
9434 [(set (match_operand 0 "arith_reg_operand" "")
9435 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9436 (match_operand 2 "" "")))
9437 (match_operand 3 "" "")
9438 (use (reg:PSI FPSCR_REG))
9439 (return)])]
9440 ""
9441 {
9442 if (TARGET_SHMEDIA)
9443 {
9444 operands[1] = shmedia_prepare_call_address (operands[1], 1);
9445 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
9446 operands[2]));
9447 DONE;
9448 }
9449 else if (TARGET_SHCOMPACT && operands[3]
9450 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
9451 {
9452 rtx cookie_rtx = operands[3];
9453 long cookie = INTVAL (cookie_rtx);
9454 rtx func = XEXP (operands[1], 0);
9455 rtx mach, r1;
9456
9457 if (flag_pic)
9458 {
9459 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9460 {
9461 rtx reg = gen_reg_rtx (Pmode);
9462
9463 emit_insn (gen_symGOT2reg (reg, func));
9464 func = reg;
9465 }
9466 else
9467 func = legitimize_pic_address (func, Pmode, 0);
9468 }
9469
9470 /* FIXME: if we could tell whether all argument registers are
9471 already taken, we could decide whether to force the use of
9472 MACH_REG or to stick to R0_REG. Unfortunately, there's no
9473 simple way to tell. We could use the CALL_COOKIE, but we
9474 can't currently tell a register used for regular argument
9475 passing from one that is unused. If we leave it up to reload
9476 to decide which register to use, it seems to always choose
9477 R0_REG, which leaves no available registers in SIBCALL_REGS
9478 to hold the address of the trampoline. */
9479 mach = gen_rtx_REG (SImode, MACH_REG);
9480 r1 = gen_rtx_REG (SImode, R1_REG);
9481
9482 /* Since such a call function may use all call-clobbered
9483 registers, we force a mode switch earlier, so that we don't
9484 run out of registers when adjusting fpscr for the call. */
9485 emit_insn (gen_force_mode_for_call ());
9486
9487 operands[1]
9488 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9489 operands[1] = force_reg (SImode, operands[1]);
9490
9491 /* We don't need a return trampoline, since the callee will
9492 return directly to the upper caller. */
9493 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9494 {
9495 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
9496 cookie_rtx = GEN_INT (cookie);
9497 }
9498
9499 emit_move_insn (mach, func);
9500 emit_move_insn (r1, cookie_rtx);
9501
9502 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
9503 operands[2], mach));
9504 DONE;
9505 }
9506 else if (TARGET_SHCOMPACT && flag_pic
9507 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9508 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9509 {
9510 rtx reg = gen_reg_rtx (Pmode);
9511
9512 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
9513 XEXP (operands[1], 0) = reg;
9514 }
9515 if (flag_pic && TARGET_SH2
9516 && MEM_P (operands[1])
9517 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9518 /* The PLT needs the PIC register, but the epilogue would have
9519 to restore it, so we can only use PC-relative PIC calls for
9520 static functions. */
9521 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9522 {
9523 emit_call_insn (gen_sibcall_value_pcrel (operands[0],
9524 XEXP (operands[1], 0),
9525 operands[2]));
9526 DONE;
9527 }
9528 else
9529 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9530
9531 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
9532 DONE;
9533 })
9534
9535 (define_insn "call_value_pop_compact"
9536 [(set (match_operand 0 "" "=rf")
9537 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9538 (match_operand 2 "" "")))
9539 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9540 (match_operand 4 "immediate_operand" "n")))
9541 (match_operand 3 "immediate_operand" "n")
9542 (use (reg:SI R0_REG))
9543 (use (reg:SI R1_REG))
9544 (use (reg:PSI FPSCR_REG))
9545 (clobber (reg:SI PR_REG))]
9546 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9547 "jsr @%1%#"
9548 [(set_attr "type" "call")
9549 (set (attr "fp_mode")
9550 (if_then_else (eq_attr "fpu_single" "yes")
9551 (const_string "single") (const_string "double")))
9552 (set_attr "needs_delay_slot" "yes")])
9553
9554 (define_insn "call_value_pop_compact_rettramp"
9555 [(set (match_operand 0 "" "=rf")
9556 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9557 (match_operand 2 "" "")))
9558 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9559 (match_operand 4 "immediate_operand" "n")))
9560 (match_operand 3 "immediate_operand" "n")
9561 (use (reg:SI R0_REG))
9562 (use (reg:SI R1_REG))
9563 (use (reg:PSI FPSCR_REG))
9564 (clobber (reg:SI R10_REG))
9565 (clobber (reg:SI PR_REG))]
9566 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9567 "jsr @%1%#"
9568 [(set_attr "type" "call")
9569 (set (attr "fp_mode")
9570 (if_then_else (eq_attr "fpu_single" "yes")
9571 (const_string "single") (const_string "double")))
9572 (set_attr "needs_delay_slot" "yes")])
9573
9574 (define_expand "call_value_pop"
9575 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9576 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9577 (match_operand 2 "" "")))
9578 (match_operand 3 "" "")
9579 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9580 (match_operand 4 "" "")))])]
9581 "TARGET_SHCOMPACT"
9582 {
9583 rtx cookie_rtx;
9584 long cookie;
9585 rtx func;
9586 rtx r0, r1;
9587
9588 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
9589 cookie_rtx = operands[3];
9590 cookie = INTVAL (cookie_rtx);
9591 func = XEXP (operands[1], 0);
9592
9593 if (flag_pic)
9594 {
9595 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9596 {
9597 rtx reg = gen_reg_rtx (Pmode);
9598
9599 emit_insn (gen_symGOTPLT2reg (reg, func));
9600 func = reg;
9601 }
9602 else
9603 func = legitimize_pic_address (func, Pmode, 0);
9604 }
9605
9606 r0 = gen_rtx_REG (SImode, R0_REG);
9607 r1 = gen_rtx_REG (SImode, R1_REG);
9608
9609 /* Since such a call function may use all call-clobbered
9610 registers, we force a mode switch earlier, so that we don't
9611 run out of registers when adjusting fpscr for the call. */
9612 emit_insn (gen_force_mode_for_call ());
9613
9614 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9615 SFUNC_GOT);
9616 operands[1] = force_reg (SImode, operands[1]);
9617
9618 emit_move_insn (r0, func);
9619 emit_move_insn (r1, cookie_rtx);
9620
9621 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9622 emit_call_insn (gen_call_value_pop_compact_rettramp
9623 (operands[0], operands[1], operands[2],
9624 operands[3], operands[4]));
9625 else
9626 emit_call_insn (gen_call_value_pop_compact
9627 (operands[0], operands[1], operands[2],
9628 operands[3], operands[4]));
9629
9630 DONE;
9631 })
9632
9633 (define_expand "sibcall_epilogue"
9634 [(return)]
9635 ""
9636 {
9637 sh_expand_epilogue (true);
9638 if (TARGET_SHCOMPACT)
9639 {
9640 rtx insn, set;
9641
9642 /* If epilogue clobbers r0, preserve it in macl. */
9643 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
9644 if ((set = single_set (insn))
9645 && REG_P (SET_DEST (set))
9646 && REGNO (SET_DEST (set)) == R0_REG)
9647 {
9648 rtx r0 = gen_rtx_REG (SImode, R0_REG);
9649 rtx tmp = gen_rtx_REG (SImode, MACL_REG);
9650
9651 /* We can't tell at this point whether the sibcall is a
9652 sibcall_compact and, if it is, whether it uses r0 or
9653 mach as operand 2, so let the instructions that
9654 preserve r0 be optimized away if r0 turns out to be
9655 dead. */
9656 emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
9657 emit_move_insn (r0, tmp);
9658 break;
9659 }
9660 }
9661 DONE;
9662 })
9663
9664 (define_insn "indirect_jump_compact"
9665 [(set (pc)
9666 (match_operand:SI 0 "arith_reg_operand" "r"))]
9667 "TARGET_SH1"
9668 "jmp @%0%#"
9669 [(set_attr "needs_delay_slot" "yes")
9670 (set_attr "type" "jump_ind")])
9671
9672 (define_expand "indirect_jump"
9673 [(set (pc)
9674 (match_operand 0 "register_operand" ""))]
9675 ""
9676 {
9677 if (GET_MODE (operands[0]) != Pmode)
9678 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
9679 })
9680
9681 ;; The use of operand 1 / 2 helps us distinguish case table jumps
9682 ;; which can be present in structured code from indirect jumps which can not
9683 ;; be present in structured code. This allows -fprofile-arcs to work.
9684
9685 ;; For SH1 processors.
9686 (define_insn "casesi_jump_1"
9687 [(set (pc)
9688 (match_operand:SI 0 "register_operand" "r"))
9689 (use (label_ref (match_operand 1 "" "")))]
9690 "TARGET_SH1"
9691 "jmp @%0%#"
9692 [(set_attr "needs_delay_slot" "yes")
9693 (set_attr "type" "jump_ind")])
9694
9695 ;; For all later processors.
9696 (define_insn "casesi_jump_2"
9697 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
9698 (label_ref (match_operand 1 "" ""))))
9699 (use (label_ref (match_operand 2 "" "")))]
9700 "TARGET_SH2
9701 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
9702 "braf %0%#"
9703 [(set_attr "needs_delay_slot" "yes")
9704 (set_attr "type" "jump_ind")])
9705
9706 (define_insn "casesi_jump_media"
9707 [(set (pc) (match_operand 0 "target_reg_operand" "b"))
9708 (use (label_ref (match_operand 1 "" "")))]
9709 "TARGET_SHMEDIA"
9710 "blink %0, r63"
9711 [(set_attr "type" "jump_media")])
9712
9713 ;; Call subroutine returning any type.
9714 ;; ??? This probably doesn't work.
9715
9716 (define_expand "untyped_call"
9717 [(parallel [(call (match_operand 0 "" "")
9718 (const_int 0))
9719 (match_operand 1 "" "")
9720 (match_operand 2 "" "")])]
9721 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
9722 {
9723 int i;
9724
9725 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
9726
9727 for (i = 0; i < XVECLEN (operands[2], 0); i++)
9728 {
9729 rtx set = XVECEXP (operands[2], 0, i);
9730 emit_move_insn (SET_DEST (set), SET_SRC (set));
9731 }
9732
9733 /* The optimizer does not know that the call sets the function value
9734 registers we stored in the result block. We avoid problems by
9735 claiming that all hard registers are used and clobbered at this
9736 point. */
9737 emit_insn (gen_blockage ());
9738
9739 DONE;
9740 })
9741 \f
9742 ;; ------------------------------------------------------------------------
9743 ;; Misc insns
9744 ;; ------------------------------------------------------------------------
9745
9746 (define_insn "dect"
9747 [(set (reg:SI T_REG)
9748 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
9749 (set (match_operand:SI 0 "arith_reg_dest" "=r")
9750 (plus:SI (match_dup 1) (const_int -1)))]
9751 "TARGET_SH2"
9752 "dt %0"
9753 [(set_attr "type" "arith")])
9754
9755 (define_insn "nop"
9756 [(const_int 0)]
9757 ""
9758 "nop")
9759
9760 ;; Load address of a label. This is only generated by the casesi expand,
9761 ;; and by machine_dependent_reorg (fixing up fp moves).
9762 ;; This must use unspec, because this only works for labels that are
9763 ;; within range,
9764
9765 (define_insn "mova"
9766 [(set (reg:SI R0_REG)
9767 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
9768 "TARGET_SH1"
9769 "mova %O0,r0"
9770 [(set_attr "in_delay_slot" "no")
9771 (set_attr "type" "arith")])
9772
9773 ;; machine_dependent_reorg will make this a `mova'.
9774 (define_insn "mova_const"
9775 [(set (reg:SI R0_REG)
9776 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
9777 "TARGET_SH1"
9778 "#"
9779 [(set_attr "in_delay_slot" "no")
9780 (set_attr "type" "arith")])
9781
9782 (define_expand "GOTaddr2picreg"
9783 [(set (reg:SI R0_REG)
9784 (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
9785 UNSPEC_MOVA))
9786 (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
9787 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
9788 ""
9789 {
9790 if (TARGET_VXWORKS_RTP)
9791 {
9792 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
9793 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
9794 emit_insn (gen_vxworks_picreg (gott_base, gott_index));
9795 DONE;
9796 }
9797
9798 operands[0] = gen_rtx_REG (Pmode, PIC_REG);
9799 operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
9800
9801 if (TARGET_SHMEDIA)
9802 {
9803 rtx tr = gen_rtx_REG (Pmode, TR0_REG);
9804 rtx pic = operands[0];
9805 rtx lab = PATTERN (gen_call_site ());
9806 rtx insn, equiv;
9807
9808 equiv = operands[1];
9809 operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
9810 UNSPEC_PCREL_SYMOFF);
9811 operands[1] = gen_rtx_CONST (Pmode, operands[1]);
9812
9813 if (Pmode == SImode)
9814 {
9815 emit_insn (gen_movsi_const (pic, operands[1]));
9816 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
9817 }
9818 else
9819 {
9820 emit_insn (gen_movdi_const (pic, operands[1]));
9821 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
9822 }
9823
9824 insn = emit_move_insn (operands[0], tr);
9825
9826 set_unique_reg_note (insn, REG_EQUAL, equiv);
9827
9828 DONE;
9829 }
9830 })
9831
9832 ;; A helper for GOTaddr2picreg to finish up the initialization of the
9833 ;; PIC register.
9834
9835 (define_expand "vxworks_picreg"
9836 [(set (reg:SI PIC_REG)
9837 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
9838 (set (reg:SI R0_REG)
9839 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
9840 (set (reg:SI PIC_REG)
9841 (mem:SI (reg:SI PIC_REG)))
9842 (set (reg:SI PIC_REG)
9843 (mem:SI (plus:SI (reg:SI PIC_REG)
9844 (reg:SI R0_REG))))]
9845 "TARGET_VXWORKS_RTP")
9846
9847 (define_insn "*ptb"
9848 [(set (match_operand 0 "target_reg_operand" "=b")
9849 (const (unspec [(match_operand 1 "" "Csy")]
9850 UNSPEC_DATALABEL)))]
9851 "TARGET_SHMEDIA && flag_pic
9852 && satisfies_constraint_Csy (operands[1])"
9853 "ptb/u datalabel %1, %0"
9854 [(set_attr "type" "ptabs_media")
9855 (set_attr "length" "*")])
9856
9857 (define_insn "ptrel_si"
9858 [(set (match_operand:SI 0 "target_reg_operand" "=b")
9859 (plus:SI (match_operand:SI 1 "register_operand" "r")
9860 (pc)))
9861 (match_operand:SI 2 "" "")]
9862 "TARGET_SHMEDIA"
9863 "%O2: ptrel/u %1, %0"
9864 [(set_attr "type" "ptabs_media")])
9865
9866 (define_insn "ptrel_di"
9867 [(set (match_operand:DI 0 "target_reg_operand" "=b")
9868 (plus:DI (match_operand:DI 1 "register_operand" "r")
9869 (pc)))
9870 (match_operand:DI 2 "" "")]
9871 "TARGET_SHMEDIA"
9872 "%O2: ptrel/u %1, %0"
9873 [(set_attr "type" "ptabs_media")])
9874
9875 (define_expand "builtin_setjmp_receiver"
9876 [(match_operand 0 "" "")]
9877 "flag_pic"
9878 {
9879 emit_insn (gen_GOTaddr2picreg ());
9880 DONE;
9881 })
9882
9883 (define_expand "call_site"
9884 [(unspec [(match_dup 0)] UNSPEC_CALLER)]
9885 "TARGET_SH1"
9886 {
9887 static HOST_WIDE_INT i = 0;
9888 operands[0] = GEN_INT (i);
9889 i++;
9890 })
9891
9892 ;; op0 = op1 + r12 but hide it before reload completed. See the comment
9893 ;; in symGOT_load expand.
9894
9895 (define_insn_and_split "chk_guard_add"
9896 [(set (match_operand:SI 0 "register_operand" "=&r")
9897 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
9898 (reg:SI PIC_REG)]
9899 UNSPEC_CHKADD))]
9900 "TARGET_SH1"
9901 "#"
9902 "TARGET_SH1 && reload_completed"
9903 [(set (match_dup 0) (reg:SI PIC_REG))
9904 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9905 ""
9906 [(set_attr "type" "arith")])
9907
9908 (define_expand "sym_label2reg"
9909 [(set (match_operand:SI 0 "" "")
9910 (const:SI (unspec:SI [(match_operand:SI 1 "" "")
9911 (const (plus:SI (match_operand:SI 2 "" "")
9912 (const_int 2)))]
9913 UNSPEC_SYMOFF)))]
9914 "TARGET_SH1" "")
9915
9916 (define_expand "symGOT_load"
9917 [(set (match_dup 2) (match_operand 1 "" ""))
9918 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
9919 (set (match_operand 0 "" "") (mem (match_dup 3)))]
9920 ""
9921 {
9922 rtx mem;
9923
9924 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
9925 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
9926
9927 if (TARGET_SHMEDIA)
9928 {
9929 rtx reg = operands[2];
9930
9931 if (Pmode == DImode)
9932 {
9933 if (flag_pic > 1)
9934 emit_insn (gen_movdi_const_32bit (reg, operands[1]));
9935 else
9936 emit_insn (gen_movdi_const_16bit (reg, operands[1]));
9937 }
9938 else
9939 {
9940 if (flag_pic > 1)
9941 emit_insn (gen_movsi_const (reg, operands[1]));
9942 else
9943 emit_insn (gen_movsi_const_16bit (reg, operands[1]));
9944 }
9945 }
9946 else
9947 emit_move_insn (operands[2], operands[1]);
9948
9949 /* When stack protector inserts codes after the result is set to
9950 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec
9951 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
9952 when rX is a GOT address for the guard symbol. Ugly but doesn't
9953 matter because this is a rare situation. */
9954 if (!TARGET_SHMEDIA
9955 && flag_stack_protect
9956 && GET_CODE (operands[1]) == CONST
9957 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
9958 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
9959 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
9960 "__stack_chk_guard") == 0)
9961 emit_insn (gen_chk_guard_add (operands[3], operands[2]));
9962 else
9963 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
9964 gen_rtx_REG (Pmode, PIC_REG)));
9965
9966 /* N.B. This is not constant for a GOTPLT relocation. */
9967 mem = gen_rtx_MEM (Pmode, operands[3]);
9968 MEM_NOTRAP_P (mem) = 1;
9969 /* ??? Should we have a special alias set for the GOT? */
9970 emit_move_insn (operands[0], mem);
9971
9972 DONE;
9973 })
9974
9975 (define_expand "sym2GOT"
9976 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
9977 ""
9978 "")
9979
9980 (define_expand "symGOT2reg"
9981 [(match_operand 0 "" "") (match_operand 1 "" "")]
9982 ""
9983 {
9984 rtx gotsym, insn;
9985
9986 gotsym = gen_sym2GOT (operands[1]);
9987 PUT_MODE (gotsym, Pmode);
9988 insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
9989
9990 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
9991
9992 DONE;
9993 })
9994
9995 (define_expand "symGOTPLT2reg"
9996 [(match_operand 0 "" "") (match_operand 1 "" "")]
9997 ""
9998 {
9999 rtx pltsym = gen_rtx_CONST (Pmode,
10000 gen_rtx_UNSPEC (Pmode,
10001 gen_rtvec (1, operands[1]),
10002 UNSPEC_GOTPLT));
10003 emit_insn (gen_symGOT_load (operands[0], pltsym));
10004 DONE;
10005 })
10006
10007 (define_expand "sym2GOTOFF"
10008 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10009 ""
10010 "")
10011
10012 (define_expand "symGOTOFF2reg"
10013 [(match_operand 0 "" "") (match_operand 1 "" "")]
10014 ""
10015 {
10016 rtx gotoffsym, insn;
10017 rtx t = (!can_create_pseudo_p ()
10018 ? operands[0]
10019 : gen_reg_rtx (GET_MODE (operands[0])));
10020
10021 gotoffsym = gen_sym2GOTOFF (operands[1]);
10022 PUT_MODE (gotoffsym, Pmode);
10023 emit_move_insn (t, gotoffsym);
10024 insn = emit_move_insn (operands[0],
10025 gen_rtx_PLUS (Pmode, t,
10026 gen_rtx_REG (Pmode, PIC_REG)));
10027
10028 set_unique_reg_note (insn, REG_EQUAL, operands[1]);
10029
10030 DONE;
10031 })
10032
10033 (define_expand "symPLT_label2reg"
10034 [(set (match_operand:SI 0 "" "")
10035 (const:SI
10036 (unspec:SI
10037 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10038 (const:SI (plus:SI (match_operand:SI 2 "" "")
10039 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
10040 ;; Even though the PIC register is not really used by the call
10041 ;; sequence in which this is expanded, the PLT code assumes the PIC
10042 ;; register is set, so we must not skip its initialization. Since
10043 ;; we only use this expand as part of calling sequences, and never
10044 ;; to take the address of a function, this is the best point to
10045 ;; insert the (use). Using the PLT to take the address of a
10046 ;; function would be wrong, not only because the PLT entry could
10047 ;; then be called from a function that doesn't initialize the PIC
10048 ;; register to the proper GOT, but also because pointers to the
10049 ;; same function might not compare equal, should they be set by
10050 ;; different shared libraries.
10051 (use (reg:SI PIC_REG))]
10052 "TARGET_SH1"
10053 "")
10054
10055 (define_expand "sym2PIC"
10056 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
10057 ""
10058 "")
10059
10060 ;; TLS code generation.
10061 ;; ??? this should be a define_insn_and_split
10062 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10063 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10064 ;; for details.
10065
10066 (define_insn "tls_global_dynamic"
10067 [(set (match_operand:SI 0 "register_operand" "=&z")
10068 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10069 UNSPEC_TLSGD))
10070 (const_int 0)))
10071 (use (reg:PSI FPSCR_REG))
10072 (use (reg:SI PIC_REG))
10073 (clobber (reg:SI PR_REG))
10074 (clobber (scratch:SI))]
10075 "TARGET_SH1"
10076 {
10077 return "mov.l 1f,r4" "\n"
10078 " mova 2f,r0" "\n"
10079 " mov.l 2f,r1" "\n"
10080 " add r0,r1" "\n"
10081 " jsr @r1" "\n"
10082 " add r12,r4" "\n"
10083 " bra 3f" "\n"
10084 " nop" "\n"
10085 " .align 2" "\n"
10086 "1: .long %a1@TLSGD" "\n"
10087 "2: .long __tls_get_addr@PLT" "\n"
10088 "3:";
10089 }
10090 [(set_attr "type" "tls_load")
10091 (set_attr "length" "26")])
10092
10093 (define_insn "tls_local_dynamic"
10094 [(set (match_operand:SI 0 "register_operand" "=&z")
10095 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10096 UNSPEC_TLSLDM))
10097 (const_int 0)))
10098 (use (reg:PSI FPSCR_REG))
10099 (use (reg:SI PIC_REG))
10100 (clobber (reg:SI PR_REG))
10101 (clobber (scratch:SI))]
10102 "TARGET_SH1"
10103 {
10104 return "mov.l 1f,r4" "\n"
10105 " mova 2f,r0" "\n"
10106 " mov.l 2f,r1" "\n"
10107 " add r0,r1" "\n"
10108 " jsr @r1" "\n"
10109 " add r12,r4" "\n"
10110 " bra 3f" "\n"
10111 " nop" "\n"
10112 " .align 2" "\n"
10113 "1: .long %a1@TLSLDM" "\n"
10114 "2: .long __tls_get_addr@PLT" "\n"
10115 "3:";
10116 }
10117 [(set_attr "type" "tls_load")
10118 (set_attr "length" "26")])
10119
10120 (define_expand "sym2DTPOFF"
10121 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
10122 ""
10123 "")
10124
10125 (define_expand "symDTPOFF2reg"
10126 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
10127 ""
10128 {
10129 rtx dtpoffsym;
10130 rtx t = (!can_create_pseudo_p ()
10131 ? operands[0]
10132 : gen_reg_rtx (GET_MODE (operands[0])));
10133
10134 dtpoffsym = gen_sym2DTPOFF (operands[1]);
10135 PUT_MODE (dtpoffsym, Pmode);
10136 emit_move_insn (t, dtpoffsym);
10137 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
10138 DONE;
10139 })
10140
10141 (define_expand "sym2GOTTPOFF"
10142 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
10143 ""
10144 "")
10145
10146 (define_insn "tls_initial_exec"
10147 [(set (match_operand:SI 0 "register_operand" "=&r")
10148 (unspec:SI [(match_operand:SI 1 "" "")]
10149 UNSPEC_TLSIE))
10150 (use (reg:SI GBR_REG))
10151 (use (reg:SI PIC_REG))
10152 (clobber (reg:SI R0_REG))]
10153 ""
10154 {
10155 return "mov.l 1f,r0" "\n"
10156 " stc gbr,%0" "\n"
10157 " mov.l @(r0,r12),r0" "\n"
10158 " bra 2f" "\n"
10159 " add r0,%0" "\n"
10160 " .align 2" "\n"
10161 "1: .long %a1" "\n"
10162 "2:";
10163 }
10164 [(set_attr "type" "tls_load")
10165 (set_attr "length" "16")])
10166
10167 (define_expand "sym2TPOFF"
10168 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
10169 ""
10170 "")
10171
10172 (define_expand "symTPOFF2reg"
10173 [(match_operand 0 "" "") (match_operand 1 "" "")]
10174 ""
10175 {
10176 rtx tpoffsym;
10177
10178 tpoffsym = gen_sym2TPOFF (operands[1]);
10179 PUT_MODE (tpoffsym, Pmode);
10180 emit_move_insn (operands[0], tpoffsym);
10181 DONE;
10182 })
10183
10184 ;;------------------------------------------------------------------------------
10185 ;; Thread pointer getter and setter.
10186 ;;
10187 ;; On SH the thread pointer is kept in the GBR.
10188 ;; These patterns are usually expanded from the respective built-in functions.
10189 (define_expand "get_thread_pointersi"
10190 [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))]
10191 "TARGET_SH1")
10192
10193 ;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
10194 (define_insn "store_gbr"
10195 [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))]
10196 ""
10197 "stc gbr,%0"
10198 [(set_attr "type" "tls_load")])
10199
10200 (define_expand "set_thread_pointersi"
10201 [(set (reg:SI GBR_REG)
10202 (unspec_volatile:SI [(match_operand:SI 0 "register_operand")]
10203 UNSPECV_GBR))]
10204 "TARGET_SH1")
10205
10206 (define_insn "load_gbr"
10207 [(set (reg:SI GBR_REG)
10208 (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
10209 UNSPECV_GBR))]
10210 "TARGET_SH1"
10211 "ldc %0,gbr"
10212 [(set_attr "type" "move")])
10213
10214 ;;------------------------------------------------------------------------------
10215 ;; Thread pointer relative memory loads and stores.
10216 ;;
10217 ;; On SH there are GBR displacement address modes which can be utilized to
10218 ;; access memory behind the thread pointer.
10219 ;; Since we do not allow using GBR for general purpose memory accesses, these
10220 ;; GBR addressing modes are formed by the combine pass.
10221 ;; This could be done with fewer patterns than below by using a mem predicate
10222 ;; for the GBR mem, but then reload would try to reload addresses with a
10223 ;; zero displacement for some strange reason.
10224
10225 (define_insn "*mov<mode>_gbr_load"
10226 [(set (match_operand:QIHISI 0 "register_operand" "=z")
10227 (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10228 (match_operand:QIHISI 1 "gbr_displacement"))))]
10229 "TARGET_SH1"
10230 "mov.<bwl> @(%O1,gbr),%0"
10231 [(set_attr "type" "load")])
10232
10233 (define_insn "*mov<mode>_gbr_load"
10234 [(set (match_operand:QIHISI 0 "register_operand" "=z")
10235 (mem:QIHISI (reg:SI GBR_REG)))]
10236 "TARGET_SH1"
10237 "mov.<bwl> @(0,gbr),%0"
10238 [(set_attr "type" "load")])
10239
10240 (define_insn "*mov<mode>_gbr_load"
10241 [(set (match_operand:SI 0 "register_operand" "=z")
10242 (sign_extend:SI
10243 (mem:QIHI (plus:SI (reg:SI GBR_REG)
10244 (match_operand:QIHI 1 "gbr_displacement")))))]
10245 "TARGET_SH1"
10246 "mov.<bw> @(%O1,gbr),%0"
10247 [(set_attr "type" "load")])
10248
10249 (define_insn "*mov<mode>_gbr_load"
10250 [(set (match_operand:SI 0 "register_operand" "=z")
10251 (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
10252 "TARGET_SH1"
10253 "mov.<bw> @(0,gbr),%0"
10254 [(set_attr "type" "load")])
10255
10256 (define_insn "*mov<mode>_gbr_store"
10257 [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
10258 (match_operand:QIHISI 0 "gbr_displacement")))
10259 (match_operand:QIHISI 1 "register_operand" "z"))]
10260 "TARGET_SH1"
10261 "mov.<bwl> %1,@(%O0,gbr)"
10262 [(set_attr "type" "store")])
10263
10264 (define_insn "*mov<mode>_gbr_store"
10265 [(set (mem:QIHISI (reg:SI GBR_REG))
10266 (match_operand:QIHISI 0 "register_operand" "z"))]
10267 "TARGET_SH1"
10268 "mov.<bwl> %0,@(0,gbr)"
10269 [(set_attr "type" "store")])
10270
10271 ;; DImode memory accesses have to be split in two SImode accesses.
10272 ;; Split them before reload, so that it gets a better chance to figure out
10273 ;; how to deal with the R0 restriction for the individual SImode accesses.
10274 ;; Do not match this insn during or after reload because it can't be split
10275 ;; afterwards.
10276 (define_insn_and_split "*movdi_gbr_load"
10277 [(set (match_operand:DI 0 "register_operand")
10278 (match_operand:DI 1 "gbr_address_mem"))]
10279 "TARGET_SH1 && can_create_pseudo_p ()"
10280 "#"
10281 "&& 1"
10282 [(set (match_dup 3) (match_dup 5))
10283 (set (match_dup 4) (match_dup 6))]
10284 {
10285 /* Swap low/high part load order on little endian, so that the result reg
10286 of the second load can be used better. */
10287 int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
10288 operands[3 + off] = gen_lowpart (SImode, operands[0]);
10289 operands[5 + off] = gen_lowpart (SImode, operands[1]);
10290 operands[4 - off] = gen_highpart (SImode, operands[0]);
10291 operands[6 - off] = gen_highpart (SImode, operands[1]);
10292 })
10293
10294 (define_insn_and_split "*movdi_gbr_store"
10295 [(set (match_operand:DI 0 "gbr_address_mem")
10296 (match_operand:DI 1 "register_operand"))]
10297 "TARGET_SH1 && can_create_pseudo_p ()"
10298 "#"
10299 "&& 1"
10300 [(set (match_dup 3) (match_dup 5))
10301 (set (match_dup 4) (match_dup 6))]
10302 {
10303 /* Swap low/high part store order on big endian, so that stores of function
10304 call results can save a reg copy. */
10305 int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
10306 operands[3 + off] = gen_lowpart (SImode, operands[0]);
10307 operands[5 + off] = gen_lowpart (SImode, operands[1]);
10308 operands[4 - off] = gen_highpart (SImode, operands[0]);
10309 operands[6 - off] = gen_highpart (SImode, operands[1]);
10310 })
10311
10312 ;; Sometimes memory accesses do not get combined with the store_gbr insn,
10313 ;; in particular when the displacements are in the range of the regular move
10314 ;; insns. Thus, in the first split pass after the combine pass we search
10315 ;; for missed opportunities and try to fix them up ourselves.
10316 ;; If an equivalent GBR address can be determined the load / store is split
10317 ;; into one of the GBR load / store patterns.
10318 ;; All of that must happen before reload (GBR address modes use R0 as the
10319 ;; other operand) and there's no point of doing it if the GBR is not
10320 ;; referenced in a function at all.
10321 (define_split
10322 [(set (match_operand:QIHISIDI 0 "register_operand")
10323 (match_operand:QIHISIDI 1 "memory_operand"))]
10324 "TARGET_SH1 && !reload_in_progress && !reload_completed
10325 && df_regs_ever_live_p (GBR_REG)"
10326 [(set (match_dup 0) (match_dup 1))]
10327 {
10328 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10329 if (gbr_mem != NULL_RTX)
10330 operands[1] = replace_equiv_address (operands[1], gbr_mem);
10331 else
10332 FAIL;
10333 })
10334
10335 (define_split
10336 [(set (match_operand:SI 0 "register_operand")
10337 (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10338 "TARGET_SH1 && !reload_in_progress && !reload_completed
10339 && df_regs_ever_live_p (GBR_REG)"
10340 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
10341 {
10342 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10343 if (gbr_mem != NULL_RTX)
10344 operands[1] = replace_equiv_address (operands[1], gbr_mem);
10345 else
10346 FAIL;
10347 })
10348
10349 ;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
10350 ;; Split those so that a GBR load can be used.
10351 (define_split
10352 [(set (match_operand:SI 0 "register_operand")
10353 (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
10354 "TARGET_SH2A && !reload_in_progress && !reload_completed
10355 && df_regs_ever_live_p (GBR_REG)"
10356 [(set (match_dup 2) (match_dup 1))
10357 (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
10358 {
10359 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
10360 if (gbr_mem != NULL_RTX)
10361 {
10362 operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
10363 operands[1] = replace_equiv_address (operands[1], gbr_mem);
10364 }
10365 else
10366 FAIL;
10367 })
10368
10369 (define_split
10370 [(set (match_operand:QIHISIDI 0 "memory_operand")
10371 (match_operand:QIHISIDI 1 "register_operand"))]
10372 "TARGET_SH1 && !reload_in_progress && !reload_completed
10373 && df_regs_ever_live_p (GBR_REG)"
10374 [(set (match_dup 0) (match_dup 1))]
10375 {
10376 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
10377 if (gbr_mem != NULL_RTX)
10378 operands[0] = replace_equiv_address (operands[0], gbr_mem);
10379 else
10380 FAIL;
10381 })
10382
10383 ;;------------------------------------------------------------------------------
10384 ;; case instruction for switch statements.
10385
10386 ;; Operand 0 is index
10387 ;; operand 1 is the minimum bound
10388 ;; operand 2 is the maximum bound - minimum bound + 1
10389 ;; operand 3 is CODE_LABEL for the table;
10390 ;; operand 4 is the CODE_LABEL to go to if index out of range.
10391
10392 (define_expand "casesi"
10393 [(match_operand:SI 0 "arith_reg_operand" "")
10394 (match_operand:SI 1 "arith_reg_operand" "")
10395 (match_operand:SI 2 "arith_reg_operand" "")
10396 (match_operand 3 "" "") (match_operand 4 "" "")]
10397 ""
10398 {
10399 rtx reg = gen_reg_rtx (SImode);
10400 rtx reg2 = gen_reg_rtx (SImode);
10401 if (TARGET_SHMEDIA)
10402 {
10403 rtx reg = gen_reg_rtx (DImode);
10404 rtx reg2 = gen_reg_rtx (DImode);
10405 rtx reg3 = gen_reg_rtx (Pmode);
10406 rtx reg4 = gen_reg_rtx (Pmode);
10407 rtx reg5 = gen_reg_rtx (Pmode);
10408 rtx load, test;
10409
10410 operands[0] = convert_modes (DImode, SImode, operands[0], 0);
10411 operands[1] = convert_modes (DImode, SImode, operands[1], 0);
10412 operands[2] = convert_modes (DImode, SImode, operands[2], 1);
10413
10414 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
10415 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4]));
10416 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
10417 test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
10418 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
10419 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
10420 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
10421 (Pmode, operands[3])));
10422 /* Messy: can we subreg to clean this up? */
10423 if (Pmode == DImode)
10424 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
10425 else
10426 load = gen_casesi_load_media (reg4,
10427 gen_rtx_SUBREG (DImode, reg3, 0),
10428 reg2, operands[3]);
10429 PUT_MODE (SET_SRC (load), Pmode);
10430 emit_insn (load);
10431 /* ??? The following add could be eliminated if we used ptrel. */
10432 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
10433 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
10434 emit_barrier ();
10435 DONE;
10436 }
10437 operands[1] = copy_to_mode_reg (SImode, operands[1]);
10438 operands[2] = copy_to_mode_reg (SImode, operands[2]);
10439 /* If optimizing, casesi_worker depends on the mode of the instruction
10440 before label it 'uses' - operands[3]. */
10441 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
10442 reg));
10443 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
10444 if (TARGET_SH2)
10445 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
10446 else
10447 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
10448 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
10449 operands[3], but to lab. We will fix this up in
10450 machine_dependent_reorg. */
10451 emit_barrier ();
10452 DONE;
10453 })
10454
10455 (define_expand "casesi_0"
10456 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
10457 (set (match_dup 4) (minus:SI (match_dup 4)
10458 (match_operand:SI 1 "arith_operand" "")))
10459 (set (reg:SI T_REG)
10460 (gtu:SI (match_dup 4)
10461 (match_operand:SI 2 "arith_reg_operand" "")))
10462 (set (pc)
10463 (if_then_else (ne (reg:SI T_REG)
10464 (const_int 0))
10465 (label_ref (match_operand 3 "" ""))
10466 (pc)))]
10467 "TARGET_SH1"
10468 "")
10469
10470 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
10471 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
10472 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
10473
10474 (define_insn "casesi_worker_0"
10475 [(set (match_operand:SI 0 "register_operand" "=r,r")
10476 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
10477 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10478 (clobber (match_scratch:SI 3 "=X,1"))
10479 (clobber (match_scratch:SI 4 "=&z,z"))]
10480 "TARGET_SH1"
10481 "#")
10482
10483 (define_split
10484 [(set (match_operand:SI 0 "register_operand" "")
10485 (unspec:SI [(match_operand:SI 1 "register_operand" "")
10486 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10487 (clobber (match_scratch:SI 3 ""))
10488 (clobber (match_scratch:SI 4 ""))]
10489 "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
10490 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10491 (parallel [(set (match_dup 0)
10492 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10493 (label_ref (match_dup 2))] UNSPEC_CASESI))
10494 (clobber (match_dup 3))])
10495 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
10496 {
10497 if (GET_CODE (operands[2]) == CODE_LABEL)
10498 LABEL_NUSES (operands[2])++;
10499 })
10500
10501 (define_split
10502 [(set (match_operand:SI 0 "register_operand" "")
10503 (unspec:SI [(match_operand:SI 1 "register_operand" "")
10504 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10505 (clobber (match_scratch:SI 3 ""))
10506 (clobber (match_scratch:SI 4 ""))]
10507 "TARGET_SH2 && reload_completed"
10508 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
10509 (parallel [(set (match_dup 0)
10510 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
10511 (label_ref (match_dup 2))] UNSPEC_CASESI))
10512 (clobber (match_dup 3))])]
10513 {
10514 if (GET_CODE (operands[2]) == CODE_LABEL)
10515 LABEL_NUSES (operands[2])++;
10516 })
10517
10518 (define_insn "casesi_worker_1"
10519 [(set (match_operand:SI 0 "register_operand" "=r,r")
10520 (unspec:SI [(reg:SI R0_REG)
10521 (match_operand:SI 1 "register_operand" "0,r")
10522 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
10523 (clobber (match_scratch:SI 3 "=X,1"))]
10524 "TARGET_SH1"
10525 {
10526 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10527
10528 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10529
10530 switch (GET_MODE (diff_vec))
10531 {
10532 case SImode:
10533 return "shll2 %1" "\n"
10534 " mov.l @(r0,%1),%0";
10535 case HImode:
10536 return "add %1,%1" "\n"
10537 " mov.w @(r0,%1),%0";
10538 case QImode:
10539 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10540 return "mov.b @(r0,%1),%0" "\n"
10541 " extu.b %0,%0";
10542 else
10543 return "mov.b @(r0,%1),%0";
10544
10545 default:
10546 gcc_unreachable ();
10547 }
10548 }
10549 [(set_attr "length" "4")])
10550
10551 (define_insn "casesi_worker_2"
10552 [(set (match_operand:SI 0 "register_operand" "=r,r")
10553 (unspec:SI [(reg:SI R0_REG)
10554 (match_operand:SI 1 "register_operand" "0,r")
10555 (label_ref (match_operand 2 "" ""))
10556 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
10557 (clobber (match_operand:SI 4 "" "=X,1"))]
10558 "TARGET_SH2 && reload_completed && flag_pic"
10559 {
10560 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10561 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10562
10563 switch (GET_MODE (diff_vec))
10564 {
10565 case SImode:
10566 return "shll2 %1" "\n"
10567 " add r0,%1" "\n"
10568 " mova %O3,r0" "\n"
10569 " mov.l @(r0,%1),%0";
10570 case HImode:
10571 return "add %1,%1" "\n"
10572 " add r0,%1" "\n"
10573 " mova %O3,r0" "\n"
10574 " mov.w @(r0,%1),%0";
10575 case QImode:
10576 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10577 return "add r0,%1" "\n"
10578 " mova %O3,r0" "\n"
10579 " mov.b @(r0,%1),%0" "\n"
10580 " extu.b %0,%0";
10581 else
10582 return "add r0,%1" "\n"
10583 " mova %O3,r0" "\n"
10584 " mov.b @(r0,%1),%0";
10585 default:
10586 gcc_unreachable ();
10587 }
10588 }
10589 [(set_attr "length" "8")])
10590
10591 (define_insn "casesi_shift_media"
10592 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
10593 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
10594 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
10595 UNSPEC_CASESI)))]
10596 "TARGET_SHMEDIA"
10597 {
10598 rtx diff_vec = PATTERN (next_real_insn (operands[2]));
10599
10600 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10601
10602 switch (GET_MODE (diff_vec))
10603 {
10604 case SImode:
10605 return "shlli %1, 2, %0";
10606 case HImode:
10607 return "shlli %1, 1, %0";
10608 case QImode:
10609 if (rtx_equal_p (operands[0], operands[1]))
10610 return "";
10611 return "add %1, r63, %0";
10612 default:
10613 gcc_unreachable ();
10614 }
10615 }
10616 [(set_attr "type" "arith_media")])
10617
10618 (define_insn "casesi_load_media"
10619 [(set (match_operand 0 "any_arith_reg_dest" "=r")
10620 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
10621 (match_operand:DI 2 "arith_reg_operand" "r")
10622 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
10623 "TARGET_SHMEDIA"
10624 {
10625 rtx diff_vec = PATTERN (next_real_insn (operands[3]));
10626
10627 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
10628
10629 switch (GET_MODE (diff_vec))
10630 {
10631 case SImode:
10632 return "ldx.l %1, %2, %0";
10633 case HImode:
10634 #if 0
10635 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10636 return "ldx.uw %1, %2, %0";
10637 #endif
10638 return "ldx.w %1, %2, %0";
10639 case QImode:
10640 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
10641 return "ldx.ub %1, %2, %0";
10642 return "ldx.b %1, %2, %0";
10643 default:
10644 gcc_unreachable ();
10645 }
10646 }
10647 [(set_attr "type" "load_media")])
10648
10649 (define_expand "simple_return"
10650 [(simple_return)]
10651 "sh_can_use_simple_return_p ()")
10652
10653 (define_expand "return"
10654 [(return)]
10655 "reload_completed && epilogue_completed"
10656 {
10657 if (TARGET_SHMEDIA)
10658 {
10659 emit_jump_insn (gen_return_media ());
10660 DONE;
10661 }
10662
10663 if (TARGET_SHCOMPACT
10664 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
10665 {
10666 emit_jump_insn (gen_shcompact_return_tramp ());
10667 DONE;
10668 }
10669 })
10670
10671 (define_insn "*<code>_i"
10672 [(any_return)]
10673 "TARGET_SH1 && ! (TARGET_SHCOMPACT
10674 && (crtl->args.info.call_cookie
10675 & CALL_COOKIE_RET_TRAMP (1)))
10676 && reload_completed
10677 && ! sh_cfun_trap_exit_p ()"
10678 {
10679 if (TARGET_SH2A && (dbr_sequence_length () == 0)
10680 && !current_function_interrupt)
10681 return "rts/n";
10682 else
10683 return "%@ %#";
10684 }
10685 [(set_attr "type" "return")
10686 (set_attr "needs_delay_slot" "yes")])
10687
10688 ;; trapa has no delay slot.
10689 (define_insn "*return_trapa"
10690 [(return)]
10691 "TARGET_SH1 && !TARGET_SHCOMPACT
10692 && reload_completed"
10693 "%@"
10694 [(set_attr "type" "return")])
10695
10696 (define_expand "shcompact_return_tramp"
10697 [(return)]
10698 "TARGET_SHCOMPACT
10699 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10700 {
10701 rtx reg = gen_rtx_REG (Pmode, R0_REG);
10702
10703 function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
10704 emit_jump_insn (gen_shcompact_return_tramp_i ());
10705 DONE;
10706 })
10707
10708 (define_insn "shcompact_return_tramp_i"
10709 [(parallel [(return) (use (reg:SI R0_REG))])]
10710 "TARGET_SHCOMPACT
10711 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
10712 "jmp @r0%#"
10713 [(set_attr "type" "jump_ind")
10714 (set_attr "needs_delay_slot" "yes")])
10715
10716 (define_insn "return_media_i"
10717 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
10718 "TARGET_SHMEDIA && reload_completed"
10719 "blink %0, r63"
10720 [(set_attr "type" "jump_media")])
10721
10722 (define_insn "return_media_rte"
10723 [(return)]
10724 "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
10725 "rte"
10726 [(set_attr "type" "jump_media")])
10727
10728 (define_expand "return_media"
10729 [(return)]
10730 "TARGET_SHMEDIA && reload_completed"
10731 {
10732 int tr_regno = sh_media_register_for_return ();
10733 rtx tr;
10734
10735 if (current_function_interrupt)
10736 {
10737 emit_jump_insn (gen_return_media_rte ());
10738 DONE;
10739 }
10740 if (tr_regno < 0)
10741 {
10742 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
10743
10744 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
10745 tr_regno = TR0_REG;
10746 tr = gen_rtx_REG (Pmode, tr_regno);
10747 emit_move_insn (tr, r18);
10748 }
10749 else
10750 tr = gen_rtx_REG (Pmode, tr_regno);
10751
10752 emit_jump_insn (gen_return_media_i (tr));
10753 DONE;
10754 })
10755
10756 (define_insn "shcompact_preserve_incoming_args"
10757 [(set (match_operand:SI 0 "register_operand" "+r")
10758 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
10759 "TARGET_SHCOMPACT"
10760 ""
10761 [(set_attr "length" "0")])
10762
10763 (define_insn "shcompact_incoming_args"
10764 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
10765 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
10766 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
10767 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
10768 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
10769 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
10770 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
10771 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
10772 (set (mem:BLK (reg:SI MACL_REG))
10773 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
10774 (use (reg:SI R0_REG))
10775 (clobber (reg:SI R0_REG))
10776 (clobber (reg:SI MACL_REG))
10777 (clobber (reg:SI MACH_REG))
10778 (clobber (reg:SI PR_REG))]
10779 "TARGET_SHCOMPACT"
10780 "jsr @r0%#"
10781 [(set_attr "needs_delay_slot" "yes")])
10782
10783 (define_insn "shmedia_save_restore_regs_compact"
10784 [(set (reg:SI SP_REG)
10785 (plus:SI (reg:SI SP_REG)
10786 (match_operand:SI 0 "immediate_operand" "i")))
10787 (use (reg:SI R0_REG))
10788 (clobber (reg:SI PR_REG))]
10789 "TARGET_SHCOMPACT
10790 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
10791 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
10792 "jsr @r0%#"
10793 [(set_attr "needs_delay_slot" "yes")])
10794
10795 (define_expand "prologue"
10796 [(const_int 0)]
10797 ""
10798 {
10799 sh_expand_prologue ();
10800 DONE;
10801 })
10802
10803 (define_expand "epilogue"
10804 [(return)]
10805 ""
10806 {
10807 sh_expand_epilogue (false);
10808 if (TARGET_SHMEDIA
10809 || (TARGET_SHCOMPACT
10810 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
10811 {
10812 emit_jump_insn (gen_return ());
10813 DONE;
10814 }
10815 })
10816
10817 (define_expand "eh_return"
10818 [(use (match_operand 0 "register_operand" ""))]
10819 ""
10820 {
10821 rtx ra = operands[0];
10822
10823 if (TARGET_SHMEDIA64)
10824 emit_insn (gen_eh_set_ra_di (ra));
10825 else
10826 emit_insn (gen_eh_set_ra_si (ra));
10827
10828 DONE;
10829 })
10830
10831 ;; Clobber the return address on the stack. We can't expand this
10832 ;; until we know where it will be put in the stack frame.
10833
10834 (define_insn "eh_set_ra_si"
10835 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
10836 UNSPECV_EH_RETURN)
10837 (clobber (match_scratch:SI 1 "=&r"))]
10838 "! TARGET_SHMEDIA64"
10839 "#")
10840
10841 (define_insn "eh_set_ra_di"
10842 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
10843 UNSPECV_EH_RETURN)
10844 (clobber (match_scratch:DI 1 "=&r"))]
10845 "TARGET_SHMEDIA64"
10846 "#")
10847
10848 (define_split
10849 [(unspec_volatile [(match_operand 0 "register_operand" "")]
10850 UNSPECV_EH_RETURN)
10851 (clobber (match_scratch 1 ""))]
10852 "reload_completed"
10853 [(const_int 0)]
10854 {
10855 sh_set_return_address (operands[0], operands[1]);
10856 DONE;
10857 })
10858
10859 (define_insn "blockage"
10860 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
10861 ""
10862 ""
10863 [(set_attr "length" "0")])
10864 \f
10865 ;; Define movml instructions for SH2A target. Currently they are
10866 ;; used to push and pop all banked registers only.
10867
10868 (define_insn "movml_push_banked"
10869 [(set (match_operand:SI 0 "register_operand" "=r")
10870 (plus (match_dup 0) (const_int -32)))
10871 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
10872 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
10873 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
10874 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
10875 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
10876 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
10877 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
10878 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
10879 "TARGET_SH2A && REGNO (operands[0]) == 15"
10880 "movml.l r7,@-r15"
10881 [(set_attr "in_delay_slot" "no")])
10882
10883 (define_insn "movml_pop_banked"
10884 [(set (match_operand:SI 0 "register_operand" "=r")
10885 (plus (match_dup 0) (const_int 32)))
10886 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
10887 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
10888 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
10889 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
10890 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
10891 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
10892 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
10893 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
10894 "TARGET_SH2A && REGNO (operands[0]) == 15"
10895 "movml.l @r15+,r7"
10896 [(set_attr "in_delay_slot" "no")])
10897 \f
10898 ;; ------------------------------------------------------------------------
10899 ;; Scc instructions
10900 ;; ------------------------------------------------------------------------
10901
10902 (define_insn "movt"
10903 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
10904 (match_operand:SI 1 "t_reg_operand"))]
10905 "TARGET_SH1"
10906 "movt %0"
10907 [(set_attr "type" "arith")])
10908
10909 (define_insn "movrt"
10910 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
10911 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
10912 "TARGET_SH2A"
10913 "movrt %0"
10914 [(set_attr "type" "arith")])
10915
10916 (define_expand "cstore4_media"
10917 [(set (match_operand:SI 0 "register_operand" "=r")
10918 (match_operator:SI 1 "sh_float_comparison_operator"
10919 [(match_operand 2 "logical_operand" "")
10920 (match_operand 3 "cmp_operand" "")]))]
10921 "TARGET_SHMEDIA"
10922 {
10923 enum machine_mode mode = GET_MODE (operands[2]);
10924 enum rtx_code code = GET_CODE (operands[1]);
10925 bool invert, swap;
10926 if (mode == VOIDmode)
10927 mode = GET_MODE (operands[3]);
10928 if (operands[2] == const0_rtx)
10929 {
10930 if (code == EQ || code == NE)
10931 operands[2] = operands[3], operands[3] = const0_rtx;
10932 }
10933 else
10934 operands[2] = force_reg (mode, operands[2]);
10935 if (operands[3] != const0_rtx)
10936 operands[3] = force_reg (mode, operands[3]);
10937
10938 switch (code)
10939 {
10940 case GEU:
10941 case GE:
10942 swap = invert = !FLOAT_MODE_P (mode);
10943 break;
10944
10945 case LEU:
10946 case LE:
10947 swap = FLOAT_MODE_P (mode), invert = !swap;
10948 break;
10949
10950 case LTU:
10951 case LT:
10952 swap = true, invert = false;
10953 break;
10954
10955 case GTU:
10956 case GT:
10957 case EQ:
10958 case UNORDERED:
10959 swap = invert = false;
10960 break;
10961
10962 case NE:
10963 swap = invert = true;
10964 break;
10965
10966 default:
10967 gcc_unreachable ();
10968 }
10969
10970 if (swap)
10971 {
10972 rtx tem = operands[2];
10973 operands[2] = operands[3];
10974 operands[3] = tem;
10975 code = swap_condition (code);
10976 }
10977
10978 if (invert)
10979 {
10980 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
10981 code = reverse_condition (code);
10982 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
10983 emit_insn (gen_cstore4_media (tem, operands[1],
10984 operands[2], operands[3]));
10985 code = EQ;
10986 operands[2] = tem;
10987 operands[3] = const0_rtx;
10988 }
10989
10990 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
10991 })
10992
10993 (define_expand "cstoresi4"
10994 [(set (match_operand:SI 0 "register_operand" "=r")
10995 (match_operator:SI 1 "comparison_operator"
10996 [(match_operand:SI 2 "cmpsi_operand" "")
10997 (match_operand:SI 3 "arith_operand" "")]))]
10998 "TARGET_SH1 || TARGET_SHMEDIA"
10999 {
11000 if (TARGET_SHMEDIA)
11001 {
11002 emit_insn (gen_cstore4_media (operands[0], operands[1],
11003 operands[2], operands[3]));
11004 DONE;
11005 }
11006
11007 if (sh_expand_t_scc (operands))
11008 DONE;
11009
11010 if (! currently_expanding_to_rtl)
11011 FAIL;
11012
11013 sh_emit_compare_and_set (operands, SImode);
11014 DONE;
11015 })
11016
11017 (define_expand "cstoredi4"
11018 [(set (match_operand:SI 0 "register_operand" "=r")
11019 (match_operator:SI 1 "comparison_operator"
11020 [(match_operand:DI 2 "arith_operand" "")
11021 (match_operand:DI 3 "arith_operand" "")]))]
11022 "TARGET_SH2 || TARGET_SHMEDIA"
11023 {
11024 if (TARGET_SHMEDIA)
11025 {
11026 emit_insn (gen_cstore4_media (operands[0], operands[1],
11027 operands[2], operands[3]));
11028 DONE;
11029 }
11030
11031 if (sh_expand_t_scc (operands))
11032 DONE;
11033
11034 if (! currently_expanding_to_rtl)
11035 FAIL;
11036
11037 sh_emit_compare_and_set (operands, DImode);
11038 DONE;
11039 })
11040
11041 ;; Move the complement of the T reg to a reg.
11042 ;; On SH2A the movrt insn can be used.
11043 ;; On anything else than SH2A this has to be done with multiple instructions.
11044 ;; One obvious way would be:
11045 ;; cmp/eq ...
11046 ;; movt r0
11047 ;; xor #1,r0
11048 ;;
11049 ;; However, this puts pressure on r0 in most cases and thus the following is
11050 ;; more appealing:
11051 ;; cmp/eq ...
11052 ;; mov #-1,temp
11053 ;; negc temp,dest
11054 ;;
11055 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11056 ;; becomes a one instruction operation. Moreover, care must be taken that
11057 ;; the insn can still be combined with inverted compare and branch code
11058 ;; around it. On the other hand, if a function returns the complement of
11059 ;; a previous comparison result in the T bit, the xor #1,r0 approach might
11060 ;; lead to better code.
11061
11062 (define_expand "movnegt"
11063 [(set (match_operand:SI 0 "arith_reg_dest" "")
11064 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11065 "TARGET_SH1"
11066 {
11067 if (TARGET_SH2A)
11068 emit_insn (gen_movrt (operands[0], operands[1]));
11069 else
11070 {
11071 rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
11072 emit_insn (gen_movrt_negc (operands[0], operands[1], val));
11073 }
11074 DONE;
11075 })
11076
11077 (define_insn "movrt_negc"
11078 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11079 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11080 (set (reg:SI T_REG) (const_int 1))
11081 (use (match_operand:SI 2 "arith_reg_operand" "r"))]
11082 "TARGET_SH1"
11083 "negc %2,%0"
11084 [(set_attr "type" "arith")])
11085
11086 ;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
11087 ;; pattern can be used by the combine pass. Using a scratch reg for the
11088 ;; -1 constant results in slightly better register allocations compared to
11089 ;; generating a pseudo reg before reload.
11090 (define_insn_and_split "*movrt_negc"
11091 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11092 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
11093 (clobber (match_scratch:SI 2 "=r"))
11094 (clobber (reg:SI T_REG))]
11095 "TARGET_SH1 && ! TARGET_SH2A"
11096 "#"
11097 "&& reload_completed"
11098 [(set (match_dup 2) (const_int -1))
11099 (parallel
11100 [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
11101 (set (reg:SI T_REG) (const_int 1))
11102 (use (match_dup 2))])])
11103
11104 ;; Store the negated T bit in a reg using r0 and xor. This one doesn't
11105 ;; clobber the T bit, which is useful when storing the T bit and the
11106 ;; negated T bit in parallel. On SH2A the movrt insn can be used for that.
11107 ;; Usually we don't want this insn to be matched, except for cases where the
11108 ;; T bit clobber is really not appreciated. Hence the extra use on T_REG.
11109 (define_insn_and_split "movrt_xor"
11110 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11111 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11112 (use (reg:SI T_REG))]
11113 "TARGET_SH1 && !TARGET_SH2A"
11114 "#"
11115 "&& reload_completed"
11116 [(set (match_dup 0) (reg:SI T_REG))
11117 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
11118
11119 ;; Store the T bit and the negated T bit in two regs in parallel. There is
11120 ;; no real insn to do that, but specifying this pattern will give combine
11121 ;; some opportunities.
11122 (define_insn_and_split "*movt_movrt"
11123 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11124 (match_operand:SI 1 "negt_reg_operand"))
11125 (set (match_operand:SI 2 "arith_reg_dest")
11126 (match_operand:SI 3 "t_reg_operand"))])]
11127 "TARGET_SH1"
11128 "#"
11129 "&& 1"
11130 [(const_int 0)]
11131 {
11132 rtx i = TARGET_SH2A
11133 ? gen_movrt (operands[0], get_t_reg_rtx ())
11134 : gen_movrt_xor (operands[0], get_t_reg_rtx ());
11135
11136 emit_insn (i);
11137 emit_insn (gen_movt (operands[2], get_t_reg_rtx ()));
11138 DONE;
11139 })
11140
11141 (define_insn_and_split "*movt_movrt"
11142 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
11143 (match_operand:SI 1 "t_reg_operand"))
11144 (set (match_operand:SI 2 "arith_reg_dest")
11145 (match_operand:SI 3 "negt_reg_operand"))])]
11146 "TARGET_SH1"
11147 "#"
11148 "&& 1"
11149 [(parallel [(set (match_dup 2) (match_dup 3))
11150 (set (match_dup 0) (match_dup 1))])])
11151
11152 ;; Use negc to store the T bit in a MSB of a reg in the following way:
11153 ;; T = 1: 0x80000000 -> reg
11154 ;; T = 0: 0x7FFFFFFF -> reg
11155 ;; This works because 0 - 0x80000000 = 0x80000000.
11156 (define_insn_and_split "*mov_t_msb_neg"
11157 [(set (match_operand:SI 0 "arith_reg_dest")
11158 (minus:SI (const_int -2147483648) ;; 0x80000000
11159 (match_operand 1 "t_reg_operand")))
11160 (clobber (reg:SI T_REG))]
11161 "TARGET_SH1"
11162 "#"
11163 "&& can_create_pseudo_p ()"
11164 [(set (match_dup 2) (const_int -2147483648))
11165 (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
11166 (reg:SI T_REG)))
11167 (clobber (reg:SI T_REG))])]
11168 {
11169 operands[2] = gen_reg_rtx (SImode);
11170 })
11171
11172 ;; These are essentially the same as above, but with the inverted T bit.
11173 ;; Combine recognizes the split patterns, but does not take them sometimes
11174 ;; if the T_REG clobber is specified. Instead it tries to split out the
11175 ;; T bit negation. Since these splits are supposed to be taken only by
11176 ;; combine, it will see the T_REG clobber of the *mov_t_msb_neg insn, so this
11177 ;; should be fine.
11178 (define_split
11179 [(set (match_operand:SI 0 "arith_reg_dest")
11180 (plus:SI (match_operand 1 "negt_reg_operand")
11181 (const_int 2147483647)))] ;; 0x7fffffff
11182 "TARGET_SH1 && can_create_pseudo_p ()"
11183 [(parallel [(set (match_dup 0)
11184 (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11185 (clobber (reg:SI T_REG))])])
11186
11187 (define_split
11188 [(set (match_operand:SI 0 "arith_reg_dest")
11189 (if_then_else:SI (match_operand 1 "t_reg_operand")
11190 (const_int 2147483647) ;; 0x7fffffff
11191 (const_int -2147483648)))] ;; 0x80000000
11192 "TARGET_SH1 && can_create_pseudo_p ()"
11193 [(parallel [(set (match_dup 0)
11194 (minus:SI (const_int -2147483648) (reg:SI T_REG)))
11195 (clobber (reg:SI T_REG))])])
11196
11197 ;; The *negnegt pattern helps the combine pass to figure out how to fold
11198 ;; an explicit double T bit negation.
11199 (define_insn_and_split "*negnegt"
11200 [(set (reg:SI T_REG)
11201 (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
11202 "TARGET_SH1"
11203 "#"
11204 ""
11205 [(const_int 0)])
11206
11207 ;; Store T bit as all zeros or ones in a reg.
11208 (define_insn "mov_neg_si_t"
11209 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11210 (neg:SI (match_operand 1 "t_reg_operand" "")))]
11211 "TARGET_SH1"
11212 "subc %0,%0"
11213 [(set_attr "type" "arith")])
11214
11215 ;; Store negated T bit as all zeros or ones in a reg.
11216 ;; Use the following sequence:
11217 ;; subc Rn,Rn ! Rn = Rn - Rn - T; T = T
11218 ;; not Rn,Rn ! Rn = 0 - Rn
11219 (define_split
11220 [(set (match_operand:SI 0 "arith_reg_dest" "")
11221 (neg:SI (match_operand 1 "negt_reg_operand" "")))]
11222 "TARGET_SH1"
11223 [(set (match_dup 0) (neg:SI (reg:SI T_REG)))
11224 (set (match_dup 0) (not:SI (match_dup 0)))])
11225
11226 ;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
11227 (define_insn_and_split "*movtt"
11228 [(set (reg:SI T_REG)
11229 (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
11230 "TARGET_SH1"
11231 "#"
11232 ""
11233 [(const_int 0)])
11234
11235 (define_insn_and_split "nott"
11236 [(set (reg:SI T_REG)
11237 (xor:SI (match_operand:SI 0 "t_reg_operand" "") (const_int 1)))]
11238 "TARGET_SH1"
11239 {
11240 gcc_assert (TARGET_SH2A);
11241 return "nott";
11242 }
11243 "! TARGET_SH2A && can_create_pseudo_p ()"
11244 [(set (match_dup 0) (reg:SI T_REG))
11245 (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
11246 {
11247 operands[0] = gen_reg_rtx (SImode);
11248 })
11249
11250 ;; Store T bit as MSB in a reg.
11251 ;; T = 0: 0x00000000 -> reg
11252 ;; T = 1: 0x80000000 -> reg
11253 (define_insn_and_split "*movt_msb"
11254 [(set (match_operand:SI 0 "arith_reg_dest")
11255 (mult:SI (match_operand:SI 1 "t_reg_operand")
11256 (const_int -2147483648))) ;; 0xffffffff80000000
11257 (clobber (reg:SI T_REG))]
11258 "TARGET_SH1"
11259 "#"
11260 "&& 1"
11261 [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
11262
11263 ;; Store inverted T bit as MSB in a reg.
11264 ;; T = 0: 0x80000000 -> reg
11265 ;; T = 1: 0x00000000 -> reg
11266 ;; On SH2A we can get away without clobbering the T_REG.
11267 (define_insn_and_split "*negt_msb"
11268 [(set (match_operand:SI 0 "arith_reg_dest")
11269 (match_operand:SI 1 "negt_reg_shl31_operand"))]
11270 "TARGET_SH2A"
11271 "#"
11272 "&& can_create_pseudo_p ()"
11273 [(const_int 0)]
11274 {
11275 rtx tmp = gen_reg_rtx (SImode);
11276 emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
11277 emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
11278 DONE;
11279 })
11280
11281 (define_insn_and_split "*negt_msb"
11282 [(set (match_operand:SI 0 "arith_reg_dest")
11283 (match_operand:SI 1 "negt_reg_shl31_operand"))
11284 (clobber (reg:SI T_REG))]
11285 "TARGET_SH1 && !TARGET_SH2A"
11286 "#"
11287 "&& can_create_pseudo_p ()"
11288 [(const_int 0)]
11289 {
11290 rtx tmp = gen_reg_rtx (SImode);
11291 emit_move_insn (tmp, get_t_reg_rtx ());
11292 emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
11293 emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
11294 DONE;
11295 })
11296
11297 ;; The *cset_zero patterns convert optimizations such as
11298 ;; "if (test) x = 0;" to "x &= -(test == 0);"
11299 ;; back to conditional branch sequences if zero-displacement branches
11300 ;; are enabled.
11301 ;; FIXME: These patterns can be removed when conditional execution patterns
11302 ;; are implemented, since ifcvt will not perform these optimizations if
11303 ;; conditional execution is supported.
11304 (define_insn "*cset_zero"
11305 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11306 (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
11307 (const_int -1))
11308 (match_operand:SI 2 "arith_reg_operand" "0")))]
11309 "TARGET_SH1 && TARGET_ZDCBRANCH"
11310 {
11311 return "bf 0f" "\n"
11312 " mov #0,%0" "\n"
11313 "0:";
11314 }
11315 [(set_attr "type" "arith") ;; poor approximation
11316 (set_attr "length" "4")])
11317
11318 (define_insn "*cset_zero"
11319 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11320 (if_then_else:SI (match_operand:SI 1 "t_reg_operand")
11321 (match_operand:SI 2 "arith_reg_operand" "0")
11322 (const_int 0)))]
11323 "TARGET_SH1 && TARGET_ZDCBRANCH"
11324 {
11325 return "bt 0f" "\n"
11326 " mov #0,%0" "\n"
11327 "0:";
11328 }
11329 [(set_attr "type" "arith") ;; poor approximation
11330 (set_attr "length" "4")])
11331
11332 (define_expand "cstoresf4"
11333 [(set (match_operand:SI 0 "register_operand" "=r")
11334 (match_operator:SI 1 "sh_float_comparison_operator"
11335 [(match_operand:SF 2 "arith_operand" "")
11336 (match_operand:SF 3 "arith_operand" "")]))]
11337 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11338 {
11339 if (TARGET_SHMEDIA)
11340 {
11341 emit_insn (gen_cstore4_media (operands[0], operands[1],
11342 operands[2], operands[3]));
11343 DONE;
11344 }
11345
11346 if (! currently_expanding_to_rtl)
11347 FAIL;
11348
11349 sh_emit_compare_and_set (operands, SFmode);
11350 DONE;
11351 })
11352
11353 (define_expand "cstoredf4"
11354 [(set (match_operand:SI 0 "register_operand" "=r")
11355 (match_operator:SI 1 "sh_float_comparison_operator"
11356 [(match_operand:DF 2 "arith_operand" "")
11357 (match_operand:DF 3 "arith_operand" "")]))]
11358 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
11359 {
11360 if (TARGET_SHMEDIA)
11361 {
11362 emit_insn (gen_cstore4_media (operands[0], operands[1],
11363 operands[2], operands[3]));
11364 DONE;
11365 }
11366
11367 if (! currently_expanding_to_rtl)
11368 FAIL;
11369
11370 sh_emit_compare_and_set (operands, DFmode);
11371 DONE;
11372 })
11373
11374 ;; -------------------------------------------------------------------------
11375 ;; Instructions to cope with inline literal tables
11376 ;; -------------------------------------------------------------------------
11377
11378 ; 2 byte integer in line
11379
11380 (define_insn "consttable_2"
11381 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11382 (match_operand 1 "" "")]
11383 UNSPECV_CONST2)]
11384 ""
11385 {
11386 if (operands[1] != const0_rtx)
11387 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
11388 return "";
11389 }
11390 [(set_attr "length" "2")
11391 (set_attr "in_delay_slot" "no")])
11392
11393 ; 4 byte integer in line
11394
11395 (define_insn "consttable_4"
11396 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11397 (match_operand 1 "" "")]
11398 UNSPECV_CONST4)]
11399 ""
11400 {
11401 if (operands[1] != const0_rtx)
11402 {
11403 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
11404 mark_symbol_refs_as_used (operands[0]);
11405 }
11406 return "";
11407 }
11408 [(set_attr "length" "4")
11409 (set_attr "in_delay_slot" "no")])
11410
11411 ; 8 byte integer in line
11412
11413 (define_insn "consttable_8"
11414 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
11415 (match_operand 1 "" "")]
11416 UNSPECV_CONST8)]
11417 ""
11418 {
11419 if (operands[1] != const0_rtx)
11420 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
11421 return "";
11422 }
11423 [(set_attr "length" "8")
11424 (set_attr "in_delay_slot" "no")])
11425
11426 ; 4 byte floating point
11427
11428 (define_insn "consttable_sf"
11429 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
11430 (match_operand 1 "" "")]
11431 UNSPECV_CONST4)]
11432 ""
11433 {
11434 if (operands[1] != const0_rtx)
11435 {
11436 REAL_VALUE_TYPE d;
11437 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11438 assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode));
11439 }
11440 return "";
11441 }
11442 [(set_attr "length" "4")
11443 (set_attr "in_delay_slot" "no")])
11444
11445 ; 8 byte floating point
11446
11447 (define_insn "consttable_df"
11448 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
11449 (match_operand 1 "" "")]
11450 UNSPECV_CONST8)]
11451 ""
11452 {
11453 if (operands[1] != const0_rtx)
11454 {
11455 REAL_VALUE_TYPE d;
11456 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
11457 assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode));
11458 }
11459 return "";
11460 }
11461 [(set_attr "length" "8")
11462 (set_attr "in_delay_slot" "no")])
11463
11464 ;; Alignment is needed for some constant tables; it may also be added for
11465 ;; Instructions at the start of loops, or after unconditional branches.
11466 ;; ??? We would get more accurate lengths if we did instruction
11467 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
11468 ;; here is too conservative.
11469
11470 ; align to a two byte boundary
11471
11472 (define_expand "align_2"
11473 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
11474 ""
11475 "")
11476
11477 ; align to a four byte boundary
11478 ;; align_4 and align_log are instructions for the starts of loops, or
11479 ;; after unconditional branches, which may take up extra room.
11480
11481 (define_expand "align_4"
11482 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
11483 ""
11484 "")
11485
11486 ; align to a cache line boundary
11487
11488 (define_insn "align_log"
11489 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
11490 ""
11491 ""
11492 [(set_attr "length" "0")
11493 (set_attr "in_delay_slot" "no")])
11494
11495 ; emitted at the end of the literal table, used to emit the
11496 ; 32bit branch labels if needed.
11497
11498 (define_insn "consttable_end"
11499 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
11500 ""
11501 {
11502 return output_jump_label_table ();
11503 }
11504 [(set_attr "in_delay_slot" "no")])
11505
11506 ; emitted at the end of the window in the literal table.
11507
11508 (define_insn "consttable_window_end"
11509 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
11510 ""
11511 ""
11512 [(set_attr "length" "0")
11513 (set_attr "in_delay_slot" "no")])
11514
11515 ;; -------------------------------------------------------------------------
11516 ;; Misc
11517 ;; -------------------------------------------------------------------------
11518
11519 ;; String/block move insn.
11520
11521 (define_expand "movmemsi"
11522 [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
11523 (mem:BLK (match_operand:BLK 1 "" "")))
11524 (use (match_operand:SI 2 "nonmemory_operand" ""))
11525 (use (match_operand:SI 3 "immediate_operand" ""))
11526 (clobber (reg:SI PR_REG))
11527 (clobber (reg:SI R4_REG))
11528 (clobber (reg:SI R5_REG))
11529 (clobber (reg:SI R0_REG))])]
11530 "TARGET_SH1 && ! TARGET_SH5"
11531 {
11532 if(expand_block_move (operands))
11533 DONE;
11534 else FAIL;
11535 })
11536
11537 (define_insn "block_move_real"
11538 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11539 (mem:BLK (reg:SI R5_REG)))
11540 (use (match_operand:SI 0 "arith_reg_operand" "r"))
11541 (clobber (reg:SI PR_REG))
11542 (clobber (reg:SI R0_REG))])]
11543 "TARGET_SH1 && ! TARGET_HARD_SH4"
11544 "jsr @%0%#"
11545 [(set_attr "type" "sfunc")
11546 (set_attr "needs_delay_slot" "yes")])
11547
11548 (define_insn "block_lump_real"
11549 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11550 (mem:BLK (reg:SI R5_REG)))
11551 (use (match_operand:SI 0 "arith_reg_operand" "r"))
11552 (use (reg:SI R6_REG))
11553 (clobber (reg:SI PR_REG))
11554 (clobber (reg:SI T_REG))
11555 (clobber (reg:SI R4_REG))
11556 (clobber (reg:SI R5_REG))
11557 (clobber (reg:SI R6_REG))
11558 (clobber (reg:SI R0_REG))])]
11559 "TARGET_SH1 && ! TARGET_HARD_SH4"
11560 "jsr @%0%#"
11561 [(set_attr "type" "sfunc")
11562 (set_attr "needs_delay_slot" "yes")])
11563
11564 (define_insn "block_move_real_i4"
11565 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11566 (mem:BLK (reg:SI R5_REG)))
11567 (use (match_operand:SI 0 "arith_reg_operand" "r"))
11568 (clobber (reg:SI PR_REG))
11569 (clobber (reg:SI R0_REG))
11570 (clobber (reg:SI R1_REG))
11571 (clobber (reg:SI R2_REG))])]
11572 "TARGET_HARD_SH4"
11573 "jsr @%0%#"
11574 [(set_attr "type" "sfunc")
11575 (set_attr "needs_delay_slot" "yes")])
11576
11577 (define_insn "block_lump_real_i4"
11578 [(parallel [(set (mem:BLK (reg:SI R4_REG))
11579 (mem:BLK (reg:SI R5_REG)))
11580 (use (match_operand:SI 0 "arith_reg_operand" "r"))
11581 (use (reg:SI R6_REG))
11582 (clobber (reg:SI PR_REG))
11583 (clobber (reg:SI T_REG))
11584 (clobber (reg:SI R4_REG))
11585 (clobber (reg:SI R5_REG))
11586 (clobber (reg:SI R6_REG))
11587 (clobber (reg:SI R0_REG))
11588 (clobber (reg:SI R1_REG))
11589 (clobber (reg:SI R2_REG))
11590 (clobber (reg:SI R3_REG))])]
11591 "TARGET_HARD_SH4"
11592 "jsr @%0%#"
11593 [(set_attr "type" "sfunc")
11594 (set_attr "needs_delay_slot" "yes")])
11595 \f
11596 ;; -------------------------------------------------------------------------
11597 ;; Floating point instructions.
11598 ;; -------------------------------------------------------------------------
11599
11600 ;; ??? All patterns should have a type attribute.
11601
11602 (define_expand "movpsi"
11603 [(set (match_operand:PSI 0 "register_operand" "")
11604 (match_operand:PSI 1 "general_movsrc_operand" ""))]
11605 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11606 "")
11607
11608 ;; The c / m alternative is a fake to guide reload to load directly into
11609 ;; fpscr, since reload doesn't know how to use post-increment.
11610 ;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
11611 ;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
11612 ;; predicate after reload.
11613 ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
11614 ;; like a mac -> gpr move.
11615 (define_insn "fpu_switch"
11616 [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
11617 (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
11618 "TARGET_SH2E
11619 && (! reload_completed
11620 || true_regnum (operands[0]) != FPSCR_REG
11621 || !MEM_P (operands[1])
11622 || GET_CODE (XEXP (operands[1], 0)) != PLUS)"
11623 "@
11624 ! precision stays the same
11625 lds.l %1,fpscr
11626 mov.l %1,%0
11627 #
11628 lds %1,fpscr
11629 mov %1,%0
11630 mov.l %1,%0
11631 sts fpscr,%0
11632 sts.l fpscr,%0"
11633 [(set_attr "length" "0,2,2,4,2,2,2,2,2")
11634 (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
11635
11636 (define_peephole2
11637 [(set (reg:PSI FPSCR_REG)
11638 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
11639 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
11640 [(const_int 0)]
11641 {
11642 rtx fpscr, mem, new_insn;
11643
11644 fpscr = SET_DEST (PATTERN (curr_insn));
11645 mem = SET_SRC (PATTERN (curr_insn));
11646 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
11647
11648 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
11649 add_reg_note (new_insn, REG_INC, operands[0]);
11650 DONE;
11651 })
11652
11653 (define_split
11654 [(set (reg:PSI FPSCR_REG)
11655 (mem:PSI (match_operand:SI 0 "register_operand" "")))]
11656 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
11657 && (flag_peephole2 ? epilogue_completed : reload_completed)"
11658 [(const_int 0)]
11659 {
11660 rtx fpscr, mem, new_insn;
11661
11662 fpscr = SET_DEST (PATTERN (curr_insn));
11663 mem = SET_SRC (PATTERN (curr_insn));
11664 mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
11665
11666 new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
11667 add_reg_note (new_insn, REG_INC, operands[0]);
11668
11669 if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
11670 emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
11671 DONE;
11672 })
11673
11674 ;; ??? This uses the fp unit, but has no type indicating that.
11675 ;; If we did that, this would either give a bogus latency or introduce
11676 ;; a bogus FIFO constraint.
11677 ;; Since this insn is currently only used for prologues/epilogues,
11678 ;; it is probably best to claim no function unit, which matches the
11679 ;; current setting.
11680 (define_insn "toggle_sz"
11681 [(set (reg:PSI FPSCR_REG)
11682 (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
11683 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
11684 "fschg"
11685 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
11686
11687 ;; There's no way we can use it today, since optimize mode switching
11688 ;; doesn't enable us to know from which mode we're switching to the
11689 ;; mode it requests, to tell whether we can use a relative mode switch
11690 ;; (like toggle_pr) or an absolute switch (like loading fpscr from
11691 ;; memory).
11692 (define_insn "toggle_pr"
11693 [(set (reg:PSI FPSCR_REG)
11694 (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
11695 "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
11696 "fpchg"
11697 [(set_attr "type" "fpscr_toggle")])
11698
11699 (define_expand "addsf3"
11700 [(set (match_operand:SF 0 "arith_reg_operand" "")
11701 (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
11702 (match_operand:SF 2 "arith_reg_operand" "")))]
11703 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11704 {
11705 if (TARGET_SH2E)
11706 {
11707 expand_sf_binop (&gen_addsf3_i, operands);
11708 DONE;
11709 }
11710 })
11711
11712 (define_insn "*addsf3_media"
11713 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11714 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
11715 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
11716 "TARGET_SHMEDIA_FPU"
11717 "fadd.s %1, %2, %0"
11718 [(set_attr "type" "fparith_media")])
11719
11720 (define_insn_and_split "unary_sf_op"
11721 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11722 (vec_select:V2SF
11723 (vec_concat:V2SF
11724 (vec_select:SF
11725 (match_dup 0)
11726 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
11727 (match_operator:SF 2 "unary_float_operator"
11728 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11729 (parallel [(match_operand 4
11730 "const_int_operand" "n")]))]))
11731 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
11732 "TARGET_SHMEDIA_FPU"
11733 "#"
11734 "TARGET_SHMEDIA_FPU && reload_completed"
11735 [(set (match_dup 5) (match_dup 6))]
11736 {
11737 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11738 rtx op1 = gen_rtx_REG (SFmode,
11739 (true_regnum (operands[1])
11740 + (INTVAL (operands[4]) ^ endian)));
11741
11742 operands[7] = gen_rtx_REG (SFmode,
11743 (true_regnum (operands[0])
11744 + (INTVAL (operands[3]) ^ endian)));
11745 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
11746 }
11747 [(set_attr "type" "fparith_media")])
11748
11749 (define_insn_and_split "binary_sf_op0"
11750 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11751 (vec_concat:V2SF
11752 (match_operator:SF 3 "binary_float_operator"
11753 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11754 (parallel [(const_int 0)]))
11755 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
11756 (parallel [(const_int 0)]))])
11757 (vec_select:SF
11758 (match_dup 0)
11759 (parallel [(const_int 1)]))))]
11760 "TARGET_SHMEDIA_FPU"
11761 "#"
11762 "&& reload_completed"
11763 [(set (match_dup 4) (match_dup 5))]
11764 {
11765 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11766 rtx op1 = gen_rtx_REG (SFmode,
11767 true_regnum (operands[1]) + endian);
11768 rtx op2 = gen_rtx_REG (SFmode,
11769 true_regnum (operands[2]) + endian);
11770
11771 operands[4] = gen_rtx_REG (SFmode,
11772 true_regnum (operands[0]) + endian);
11773 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
11774 }
11775 [(set_attr "type" "fparith_media")])
11776
11777 (define_insn_and_split "binary_sf_op1"
11778 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
11779 (vec_concat:V2SF
11780 (vec_select:SF
11781 (match_dup 0)
11782 (parallel [(const_int 0)]))
11783 (match_operator:SF 3 "binary_float_operator"
11784 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
11785 (parallel [(const_int 1)]))
11786 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
11787 (parallel [(const_int 1)]))])))]
11788 "TARGET_SHMEDIA_FPU"
11789 "#"
11790 "&& reload_completed"
11791 [(set (match_dup 4) (match_dup 5))]
11792 {
11793 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
11794 rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
11795 rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
11796
11797 operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
11798 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
11799 }
11800 [(set_attr "type" "fparith_media")])
11801
11802 (define_insn "addsf3_i"
11803 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11804 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
11805 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
11806 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
11807 "TARGET_SH2E"
11808 "fadd %2,%0"
11809 [(set_attr "type" "fp")
11810 (set_attr "fp_mode" "single")])
11811
11812 (define_expand "subsf3"
11813 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
11814 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
11815 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
11816 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11817 {
11818 if (TARGET_SH2E)
11819 {
11820 expand_sf_binop (&gen_subsf3_i, operands);
11821 DONE;
11822 }
11823 })
11824
11825 (define_insn "*subsf3_media"
11826 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11827 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
11828 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
11829 "TARGET_SHMEDIA_FPU"
11830 "fsub.s %1, %2, %0"
11831 [(set_attr "type" "fparith_media")])
11832
11833 (define_insn "subsf3_i"
11834 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11835 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
11836 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
11837 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
11838 "TARGET_SH2E"
11839 "fsub %2,%0"
11840 [(set_attr "type" "fp")
11841 (set_attr "fp_mode" "single")])
11842
11843 (define_expand "mulsf3"
11844 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
11845 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
11846 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
11847 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11848 {
11849 if (TARGET_SH2E)
11850 {
11851 emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2],
11852 get_fpscr_rtx ()));
11853 DONE;
11854 }
11855 })
11856
11857 (define_insn "*mulsf3_media"
11858 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11859 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
11860 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
11861 "TARGET_SHMEDIA_FPU"
11862 "fmul.s %1, %2, %0"
11863 [(set_attr "type" "fparith_media")])
11864
11865 (define_insn "mulsf3_i"
11866 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11867 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
11868 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
11869 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
11870 "TARGET_SH2E"
11871 "fmul %2,%0"
11872 [(set_attr "type" "fp")
11873 (set_attr "fp_mode" "single")])
11874
11875 ;; FMA (fused multiply-add) patterns
11876 (define_expand "fmasf4"
11877 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
11878 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
11879 (match_operand:SF 2 "fp_arith_reg_operand" "")
11880 (match_operand:SF 3 "fp_arith_reg_operand" "")))]
11881 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11882 {
11883 if (TARGET_SH2E)
11884 {
11885 emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
11886 operands[3], get_fpscr_rtx ()));
11887 DONE;
11888 }
11889 })
11890
11891 (define_insn "fmasf4_i"
11892 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11893 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
11894 (match_operand:SF 2 "fp_arith_reg_operand" "f")
11895 (match_operand:SF 3 "fp_arith_reg_operand" "0")))
11896 (use (match_operand:PSI 4 "fpscr_operand" "c"))]
11897 "TARGET_SH2E"
11898 "fmac %1,%2,%0"
11899 [(set_attr "type" "fp")
11900 (set_attr "fp_mode" "single")])
11901
11902 (define_insn "fmasf4_media"
11903 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11904 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
11905 (match_operand:SF 2 "fp_arith_reg_operand" "f")
11906 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
11907 "TARGET_SHMEDIA_FPU"
11908 "fmac.s %1, %2, %0"
11909 [(set_attr "type" "fparith_media")])
11910
11911 (define_expand "divsf3"
11912 [(set (match_operand:SF 0 "arith_reg_operand" "")
11913 (div:SF (match_operand:SF 1 "arith_reg_operand" "")
11914 (match_operand:SF 2 "arith_reg_operand" "")))]
11915 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11916 {
11917 if (TARGET_SH2E)
11918 {
11919 expand_sf_binop (&gen_divsf3_i, operands);
11920 DONE;
11921 }
11922 })
11923
11924 (define_insn "*divsf3_media"
11925 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11926 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
11927 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
11928 "TARGET_SHMEDIA_FPU"
11929 "fdiv.s %1, %2, %0"
11930 [(set_attr "type" "fdiv_media")])
11931
11932 (define_insn "divsf3_i"
11933 [(set (match_operand:SF 0 "arith_reg_dest" "=f")
11934 (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
11935 (match_operand:SF 2 "arith_reg_operand" "f")))
11936 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
11937 "TARGET_SH2E"
11938 "fdiv %2,%0"
11939 [(set_attr "type" "fdiv")
11940 (set_attr "fp_mode" "single")])
11941
11942 (define_insn "floatdisf2"
11943 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11944 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
11945 "TARGET_SHMEDIA_FPU"
11946 "float.qs %1, %0"
11947 [(set_attr "type" "fpconv_media")])
11948
11949 (define_expand "floatsisf2"
11950 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
11951 (float:SF (match_operand:SI 1 "fpul_operand" "")))]
11952 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11953 {
11954 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
11955 {
11956 emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
11957 DONE;
11958 }
11959 })
11960
11961 (define_insn "*floatsisf2_media"
11962 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11963 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
11964 "TARGET_SHMEDIA_FPU"
11965 "float.ls %1, %0"
11966 [(set_attr "type" "fpconv_media")])
11967
11968 (define_insn "floatsisf2_i4"
11969 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11970 (float:SF (match_operand:SI 1 "fpul_operand" "y")))
11971 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
11972 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
11973 "float %1,%0"
11974 [(set_attr "type" "fp")
11975 (set_attr "fp_mode" "single")])
11976
11977 (define_insn "*floatsisf2_ie"
11978 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
11979 (float:SF (match_operand:SI 1 "fpul_operand" "y")))]
11980 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
11981 "float %1,%0"
11982 [(set_attr "type" "fp")])
11983
11984 (define_insn "fix_truncsfdi2"
11985 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
11986 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11987 "TARGET_SHMEDIA_FPU"
11988 "ftrc.sq %1, %0"
11989 [(set_attr "type" "fpconv_media")])
11990
11991 (define_expand "fix_truncsfsi2"
11992 [(set (match_operand:SI 0 "fpul_operand" "=y")
11993 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
11994 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
11995 {
11996 if (TARGET_SH4 || TARGET_SH2A_SINGLE)
11997 {
11998 emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
11999 DONE;
12000 }
12001 })
12002
12003 (define_insn "*fix_truncsfsi2_media"
12004 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12005 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12006 "TARGET_SHMEDIA_FPU"
12007 "ftrc.sl %1, %0"
12008 [(set_attr "type" "fpconv_media")])
12009
12010 (define_insn "fix_truncsfsi2_i4"
12011 [(set (match_operand:SI 0 "fpul_operand" "=y")
12012 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12013 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12014 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12015 "ftrc %1,%0"
12016 [(set_attr "type" "ftrc_s")
12017 (set_attr "fp_mode" "single")])
12018
12019 ;; ??? This pattern is used nowhere. fix_truncsfsi2 always expands to
12020 ;; fix_truncsfsi2_i4.
12021 ;; (define_insn "fix_truncsfsi2_i4_2"
12022 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12023 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12024 ;; (use (reg:PSI FPSCR_REG))
12025 ;; (clobber (reg:SI FPUL_REG))]
12026 ;; "TARGET_SH4"
12027 ;; "#"
12028 ;; [(set_attr "length" "4")
12029 ;; (set_attr "fp_mode" "single")])
12030
12031 ;;(define_split
12032 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12033 ;; (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
12034 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
12035 ;; (clobber (reg:SI FPUL_REG))]
12036 ;; "TARGET_SH4"
12037 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
12038 ;; (use (match_dup 2))])
12039 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
12040
12041 (define_insn "*fixsfsi"
12042 [(set (match_operand:SI 0 "fpul_operand" "=y")
12043 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12044 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12045 "ftrc %1,%0"
12046 [(set_attr "type" "fp")])
12047
12048 (define_insn "cmpgtsf_t"
12049 [(set (reg:SI T_REG)
12050 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12051 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12052 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12053 "fcmp/gt %1,%0"
12054 [(set_attr "type" "fp_cmp")
12055 (set_attr "fp_mode" "single")])
12056
12057 (define_insn "cmpeqsf_t"
12058 [(set (reg:SI T_REG)
12059 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12060 (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12061 "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12062 "fcmp/eq %1,%0"
12063 [(set_attr "type" "fp_cmp")
12064 (set_attr "fp_mode" "single")])
12065
12066 (define_insn "ieee_ccmpeqsf_t"
12067 [(set (reg:SI T_REG)
12068 (ior:SI (reg:SI T_REG)
12069 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12070 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
12071 "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12072 {
12073 return output_ieee_ccmpeq (insn, operands);
12074 }
12075 [(set_attr "length" "4")])
12076
12077
12078 (define_insn "cmpgtsf_t_i4"
12079 [(set (reg:SI T_REG)
12080 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12081 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12082 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12083 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12084 "fcmp/gt %1,%0"
12085 [(set_attr "type" "fp_cmp")
12086 (set_attr "fp_mode" "single")])
12087
12088 (define_insn "cmpeqsf_t_i4"
12089 [(set (reg:SI T_REG)
12090 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12091 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
12092 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12093 "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
12094 "fcmp/eq %1,%0"
12095 [(set_attr "type" "fp_cmp")
12096 (set_attr "fp_mode" "single")])
12097
12098 (define_insn "*ieee_ccmpeqsf_t_4"
12099 [(set (reg:SI T_REG)
12100 (ior:SI (reg:SI T_REG)
12101 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
12102 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
12103 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12104 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
12105 {
12106 return output_ieee_ccmpeq (insn, operands);
12107 }
12108 [(set_attr "length" "4")
12109 (set_attr "fp_mode" "single")])
12110
12111 (define_insn "cmpeqsf_media"
12112 [(set (match_operand:SI 0 "register_operand" "=r")
12113 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12114 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12115 "TARGET_SHMEDIA_FPU"
12116 "fcmpeq.s %1, %2, %0"
12117 [(set_attr "type" "fcmp_media")])
12118
12119 (define_insn "cmpgtsf_media"
12120 [(set (match_operand:SI 0 "register_operand" "=r")
12121 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12122 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12123 "TARGET_SHMEDIA_FPU"
12124 "fcmpgt.s %1, %2, %0"
12125 [(set_attr "type" "fcmp_media")])
12126
12127 (define_insn "cmpgesf_media"
12128 [(set (match_operand:SI 0 "register_operand" "=r")
12129 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12130 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12131 "TARGET_SHMEDIA_FPU"
12132 "fcmpge.s %1, %2, %0"
12133 [(set_attr "type" "fcmp_media")])
12134
12135 (define_insn "cmpunsf_media"
12136 [(set (match_operand:SI 0 "register_operand" "=r")
12137 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
12138 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12139 "TARGET_SHMEDIA_FPU"
12140 "fcmpun.s %1, %2, %0"
12141 [(set_attr "type" "fcmp_media")])
12142
12143 (define_expand "cbranchsf4"
12144 [(set (pc)
12145 (if_then_else (match_operator 0 "sh_float_comparison_operator"
12146 [(match_operand:SF 1 "arith_operand" "")
12147 (match_operand:SF 2 "arith_operand" "")])
12148 (match_operand 3 "" "")
12149 (pc)))]
12150 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12151 {
12152 if (TARGET_SHMEDIA)
12153 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12154 operands[3]));
12155 else
12156 sh_emit_compare_and_branch (operands, SFmode);
12157 DONE;
12158 })
12159
12160 (define_expand "negsf2"
12161 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12162 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12163 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12164 {
12165 if (TARGET_SH2E)
12166 {
12167 expand_sf_unop (&gen_negsf2_i, operands);
12168 DONE;
12169 }
12170 })
12171
12172 (define_insn "*negsf2_media"
12173 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12174 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12175 "TARGET_SHMEDIA_FPU"
12176 "fneg.s %1, %0"
12177 [(set_attr "type" "fmove_media")])
12178
12179 (define_insn "negsf2_i"
12180 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12181 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12182 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12183 "TARGET_SH2E"
12184 "fneg %0"
12185 [(set_attr "type" "fmove")
12186 (set_attr "fp_mode" "single")])
12187
12188 (define_expand "sqrtsf2"
12189 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12190 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12191 "TARGET_SH3E || TARGET_SHMEDIA_FPU"
12192 {
12193 if (TARGET_SH3E)
12194 {
12195 expand_sf_unop (&gen_sqrtsf2_i, operands);
12196 DONE;
12197 }
12198 })
12199
12200 (define_insn "*sqrtsf2_media"
12201 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12202 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12203 "TARGET_SHMEDIA_FPU"
12204 "fsqrt.s %1, %0"
12205 [(set_attr "type" "fdiv_media")])
12206
12207 (define_insn "sqrtsf2_i"
12208 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12209 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12210 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12211 "TARGET_SH3E"
12212 "fsqrt %0"
12213 [(set_attr "type" "fdiv")
12214 (set_attr "fp_mode" "single")])
12215
12216 (define_insn "rsqrtsf2"
12217 [(set (match_operand:SF 0 "register_operand" "=f")
12218 (div:SF (match_operand:SF 1 "immediate_operand" "i")
12219 (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
12220 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12221 "TARGET_FPU_ANY && TARGET_FSRRA
12222 && operands[1] == CONST1_RTX (SFmode)"
12223 "fsrra %0"
12224 [(set_attr "type" "fsrra")
12225 (set_attr "fp_mode" "single")])
12226
12227 ;; When the sincos pattern is defined, the builtin functions sin and cos
12228 ;; will be expanded to the sincos pattern and one of the output values will
12229 ;; remain unused.
12230 (define_expand "sincossf3"
12231 [(set (match_operand:SF 0 "nonimmediate_operand" "")
12232 (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand" "")]
12233 UNSPEC_FSINA))
12234 (set (match_operand:SF 1 "nonimmediate_operand" "")
12235 (unspec:SF [(match_dup 2)] UNSPEC_FCOSA))]
12236 "TARGET_FPU_ANY && TARGET_FSCA"
12237 {
12238 rtx scaled = gen_reg_rtx (SFmode);
12239 rtx truncated = gen_reg_rtx (SImode);
12240 rtx fsca = gen_reg_rtx (V2SFmode);
12241 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
12242
12243 emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
12244 emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
12245 emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
12246 get_fpscr_rtx ()));
12247
12248 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 0));
12249 emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 4));
12250 DONE;
12251 })
12252
12253 (define_insn_and_split "fsca"
12254 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12255 (vec_concat:V2SF
12256 (unspec:SF [(mult:SF
12257 (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
12258 (match_operand:SF 2 "fsca_scale_factor" "i"))
12259 ] UNSPEC_FSINA)
12260 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
12261 ] UNSPEC_FCOSA)))
12262 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12263 "TARGET_FPU_ANY && TARGET_FSCA"
12264 "fsca fpul,%d0"
12265 "&& !fpul_operand (operands[1], SImode)"
12266 [(const_int 0)]
12267 {
12268 /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
12269 to a simple reg, otherwise reload will have trouble reloading the
12270 pseudo into fpul. */
12271 rtx x = XEXP (operands[1], 0);
12272 while (x != NULL_RTX && !fpul_operand (x, SImode))
12273 {
12274 gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
12275 x = XEXP (x, 0);
12276 }
12277
12278 gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
12279 emit_insn (gen_fsca (operands[0], x, operands[2], operands[3]));
12280 DONE;
12281 }
12282 [(set_attr "type" "fsca")
12283 (set_attr "fp_mode" "single")])
12284
12285 (define_expand "abssf2"
12286 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
12287 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
12288 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12289 {
12290 if (TARGET_SH2E)
12291 {
12292 expand_sf_unop (&gen_abssf2_i, operands);
12293 DONE;
12294 }
12295 })
12296
12297 (define_insn "*abssf2_media"
12298 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12299 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12300 "TARGET_SHMEDIA_FPU"
12301 "fabs.s %1, %0"
12302 [(set_attr "type" "fmove_media")])
12303
12304 (define_insn "abssf2_i"
12305 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12306 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
12307 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12308 "TARGET_SH2E"
12309 "fabs %0"
12310 [(set_attr "type" "fmove")
12311 (set_attr "fp_mode" "single")])
12312
12313 (define_expand "adddf3"
12314 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12315 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12316 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12317 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12318 {
12319 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12320 {
12321 expand_df_binop (&gen_adddf3_i, operands);
12322 DONE;
12323 }
12324 })
12325
12326 (define_insn "*adddf3_media"
12327 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12328 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12329 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12330 "TARGET_SHMEDIA_FPU"
12331 "fadd.d %1, %2, %0"
12332 [(set_attr "type" "dfparith_media")])
12333
12334 (define_insn "adddf3_i"
12335 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12336 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12337 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12338 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12339 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12340 "fadd %2,%0"
12341 [(set_attr "type" "dfp_arith")
12342 (set_attr "fp_mode" "double")])
12343
12344 (define_expand "subdf3"
12345 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12346 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12347 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12348 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12349 {
12350 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12351 {
12352 expand_df_binop (&gen_subdf3_i, operands);
12353 DONE;
12354 }
12355 })
12356
12357 (define_insn "*subdf3_media"
12358 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12359 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12360 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12361 "TARGET_SHMEDIA_FPU"
12362 "fsub.d %1, %2, %0"
12363 [(set_attr "type" "dfparith_media")])
12364
12365 (define_insn "subdf3_i"
12366 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12367 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12368 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12369 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12370 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12371 "fsub %2,%0"
12372 [(set_attr "type" "dfp_arith")
12373 (set_attr "fp_mode" "double")])
12374
12375 (define_expand "muldf3"
12376 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12377 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12378 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12379 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12380 {
12381 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12382 {
12383 expand_df_binop (&gen_muldf3_i, operands);
12384 DONE;
12385 }
12386 })
12387
12388 (define_insn "*muldf3_media"
12389 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12390 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
12391 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12392 "TARGET_SHMEDIA_FPU"
12393 "fmul.d %1, %2, %0"
12394 [(set_attr "type" "dfmul_media")])
12395
12396 (define_insn "muldf3_i"
12397 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12398 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
12399 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12400 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12401 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12402 "fmul %2,%0"
12403 [(set_attr "type" "dfp_mul")
12404 (set_attr "fp_mode" "double")])
12405
12406 (define_expand "divdf3"
12407 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12408 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
12409 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
12410 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12411 {
12412 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12413 {
12414 expand_df_binop (&gen_divdf3_i, operands);
12415 DONE;
12416 }
12417 })
12418
12419 (define_insn "*divdf3_media"
12420 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12421 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
12422 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12423 "TARGET_SHMEDIA_FPU"
12424 "fdiv.d %1, %2, %0"
12425 [(set_attr "type" "dfdiv_media")])
12426
12427 (define_insn "divdf3_i"
12428 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12429 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
12430 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
12431 (use (match_operand:PSI 3 "fpscr_operand" "c"))]
12432 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12433 "fdiv %2,%0"
12434 [(set_attr "type" "dfdiv")
12435 (set_attr "fp_mode" "double")])
12436
12437 (define_insn "floatdidf2"
12438 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12439 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
12440 "TARGET_SHMEDIA_FPU"
12441 "float.qd %1, %0"
12442 [(set_attr "type" "dfpconv_media")])
12443
12444 (define_expand "floatsidf2"
12445 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12446 (float:DF (match_operand:SI 1 "fpul_operand" "")))]
12447 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12448 {
12449 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12450 {
12451 emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
12452 get_fpscr_rtx ()));
12453 DONE;
12454 }
12455 })
12456
12457 (define_insn "*floatsidf2_media"
12458 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12459 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
12460 "TARGET_SHMEDIA_FPU"
12461 "float.ld %1, %0"
12462 [(set_attr "type" "dfpconv_media")])
12463
12464 (define_insn "floatsidf2_i"
12465 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12466 (float:DF (match_operand:SI 1 "fpul_operand" "y")))
12467 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12468 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12469 "float %1,%0"
12470 [(set_attr "type" "dfp_conv")
12471 (set_attr "fp_mode" "double")])
12472
12473 (define_insn "fix_truncdfdi2"
12474 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
12475 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12476 "TARGET_SHMEDIA_FPU"
12477 "ftrc.dq %1, %0"
12478 [(set_attr "type" "dfpconv_media")])
12479
12480 (define_expand "fix_truncdfsi2"
12481 [(set (match_operand:SI 0 "fpul_operand" "")
12482 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
12483 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12484 {
12485 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12486 {
12487 emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
12488 get_fpscr_rtx ()));
12489 DONE;
12490 }
12491 })
12492
12493 (define_insn "*fix_truncdfsi2_media"
12494 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
12495 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12496 "TARGET_SHMEDIA_FPU"
12497 "ftrc.dl %1, %0"
12498 [(set_attr "type" "dfpconv_media")])
12499
12500 (define_insn "fix_truncdfsi2_i"
12501 [(set (match_operand:SI 0 "fpul_operand" "=y")
12502 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
12503 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12504 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12505 "ftrc %1,%0"
12506 [(set_attr "type" "dfp_conv")
12507 (set_attr "dfp_comp" "no")
12508 (set_attr "fp_mode" "double")])
12509
12510 ;; ??? This pattern is used nowhere. fix_truncdfsi2 always expands to
12511 ;; fix_truncdfsi2_i.
12512 ;; (define_insn "fix_truncdfsi2_i4"
12513 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12514 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
12515 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
12516 ;; (clobber (reg:SI FPUL_REG))]
12517 ;; "TARGET_SH4"
12518 ;; "#"
12519 ;; [(set_attr "length" "4")
12520 ;; (set_attr "fp_mode" "double")])
12521 ;;
12522 ;; (define_split
12523 ;; [(set (match_operand:SI 0 "arith_reg_operand" "=r")
12524 ;; (fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
12525 ;; (use (match_operand:PSI 2 "fpscr_operand" "c"))
12526 ;; (clobber (reg:SI FPUL_REG))]
12527 ;; "TARGET_SH4"
12528 ;; [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
12529 ;; (use (match_dup 2))])
12530 ;; (set (match_dup 0) (reg:SI FPUL_REG))])
12531
12532 (define_insn "cmpgtdf_t"
12533 [(set (reg:SI T_REG)
12534 (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
12535 (match_operand:DF 1 "arith_reg_operand" "f")))
12536 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12537 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12538 "fcmp/gt %1,%0"
12539 [(set_attr "type" "dfp_cmp")
12540 (set_attr "fp_mode" "double")])
12541
12542 (define_insn "cmpeqdf_t"
12543 [(set (reg:SI T_REG)
12544 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
12545 (match_operand:DF 1 "arith_reg_operand" "f")))
12546 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12547 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12548 "fcmp/eq %1,%0"
12549 [(set_attr "type" "dfp_cmp")
12550 (set_attr "fp_mode" "double")])
12551
12552 (define_insn "*ieee_ccmpeqdf_t"
12553 [(set (reg:SI T_REG)
12554 (ior:SI (reg:SI T_REG)
12555 (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
12556 (match_operand:DF 1 "arith_reg_operand" "f"))))
12557 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12558 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12559 {
12560 return output_ieee_ccmpeq (insn, operands);
12561 }
12562 [(set_attr "length" "4")
12563 (set_attr "fp_mode" "double")])
12564
12565 (define_insn "cmpeqdf_media"
12566 [(set (match_operand:SI 0 "register_operand" "=r")
12567 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12568 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12569 "TARGET_SHMEDIA_FPU"
12570 "fcmpeq.d %1,%2,%0"
12571 [(set_attr "type" "fcmp_media")])
12572
12573 (define_insn "cmpgtdf_media"
12574 [(set (match_operand:SI 0 "register_operand" "=r")
12575 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12576 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12577 "TARGET_SHMEDIA_FPU"
12578 "fcmpgt.d %1,%2,%0"
12579 [(set_attr "type" "fcmp_media")])
12580
12581 (define_insn "cmpgedf_media"
12582 [(set (match_operand:SI 0 "register_operand" "=r")
12583 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12584 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12585 "TARGET_SHMEDIA_FPU"
12586 "fcmpge.d %1,%2,%0"
12587 [(set_attr "type" "fcmp_media")])
12588
12589 (define_insn "cmpundf_media"
12590 [(set (match_operand:SI 0 "register_operand" "=r")
12591 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
12592 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
12593 "TARGET_SHMEDIA_FPU"
12594 "fcmpun.d %1,%2,%0"
12595 [(set_attr "type" "fcmp_media")])
12596
12597 (define_expand "cbranchdf4"
12598 [(set (pc)
12599 (if_then_else (match_operator 0 "sh_float_comparison_operator"
12600 [(match_operand:DF 1 "arith_operand" "")
12601 (match_operand:DF 2 "arith_operand" "")])
12602 (match_operand 3 "" "")
12603 (pc)))]
12604 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12605 {
12606 if (TARGET_SHMEDIA)
12607 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
12608 operands[3]));
12609 else
12610 sh_emit_compare_and_branch (operands, DFmode);
12611 DONE;
12612 })
12613
12614
12615 (define_expand "negdf2"
12616 [(set (match_operand:DF 0 "arith_reg_operand" "")
12617 (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
12618 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12619 {
12620 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12621 {
12622 expand_df_unop (&gen_negdf2_i, operands);
12623 DONE;
12624 }
12625 })
12626
12627 (define_insn "*negdf2_media"
12628 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12629 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12630 "TARGET_SHMEDIA_FPU"
12631 "fneg.d %1, %0"
12632 [(set_attr "type" "fmove_media")])
12633
12634 (define_insn "negdf2_i"
12635 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12636 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
12637 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12638 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12639 "fneg %0"
12640 [(set_attr "type" "fmove")
12641 (set_attr "fp_mode" "double")])
12642
12643 (define_expand "sqrtdf2"
12644 [(set (match_operand:DF 0 "arith_reg_operand" "")
12645 (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
12646 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12647 {
12648 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12649 {
12650 expand_df_unop (&gen_sqrtdf2_i, operands);
12651 DONE;
12652 }
12653 })
12654
12655 (define_insn "*sqrtdf2_media"
12656 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12657 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12658 "TARGET_SHMEDIA_FPU"
12659 "fsqrt.d %1, %0"
12660 [(set_attr "type" "dfdiv_media")])
12661
12662 (define_insn "sqrtdf2_i"
12663 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12664 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
12665 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12666 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12667 "fsqrt %0"
12668 [(set_attr "type" "dfdiv")
12669 (set_attr "fp_mode" "double")])
12670
12671 (define_expand "absdf2"
12672 [(set (match_operand:DF 0 "arith_reg_operand" "")
12673 (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
12674 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12675 {
12676 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12677 {
12678 expand_df_unop (&gen_absdf2_i, operands);
12679 DONE;
12680 }
12681 })
12682
12683 (define_insn "*absdf2_media"
12684 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12685 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12686 "TARGET_SHMEDIA_FPU"
12687 "fabs.d %1, %0"
12688 [(set_attr "type" "fmove_media")])
12689
12690 (define_insn "absdf2_i"
12691 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12692 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
12693 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12694 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12695 "fabs %0"
12696 [(set_attr "type" "fmove")
12697 (set_attr "fp_mode" "double")])
12698
12699 (define_expand "extendsfdf2"
12700 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
12701 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
12702 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12703 {
12704 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12705 {
12706 emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
12707 get_fpscr_rtx ()));
12708 DONE;
12709 }
12710 })
12711
12712 (define_insn "*extendsfdf2_media"
12713 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12714 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
12715 "TARGET_SHMEDIA_FPU"
12716 "fcnv.sd %1, %0"
12717 [(set_attr "type" "dfpconv_media")])
12718
12719 (define_insn "extendsfdf2_i4"
12720 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
12721 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
12722 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12723 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12724 "fcnvsd %1,%0"
12725 [(set_attr "type" "fp")
12726 (set_attr "fp_mode" "double")])
12727
12728 (define_expand "truncdfsf2"
12729 [(set (match_operand:SF 0 "fpul_operand" "")
12730 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
12731 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12732 {
12733 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
12734 {
12735 emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
12736 get_fpscr_rtx ()));
12737 DONE;
12738 }
12739 })
12740
12741 (define_insn "*truncdfsf2_media"
12742 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12743 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
12744 "TARGET_SHMEDIA_FPU"
12745 "fcnv.ds %1, %0"
12746 [(set_attr "type" "dfpconv_media")])
12747
12748 (define_insn "truncdfsf2_i4"
12749 [(set (match_operand:SF 0 "fpul_operand" "=y")
12750 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
12751 (use (match_operand:PSI 2 "fpscr_operand" "c"))]
12752 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12753 "fcnvds %1,%0"
12754 [(set_attr "type" "fp")
12755 (set_attr "fp_mode" "double")])
12756 \f
12757 ;; Bit field extract patterns. These give better code for packed bitfields,
12758 ;; because they allow auto-increment addresses to be generated.
12759
12760 (define_expand "insv"
12761 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
12762 (match_operand:SI 1 "immediate_operand" "")
12763 (match_operand:SI 2 "immediate_operand" ""))
12764 (match_operand:SI 3 "general_operand" ""))]
12765 "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
12766 {
12767 rtx addr_target, orig_address, shift_reg, qi_val;
12768 HOST_WIDE_INT bitsize, size, v = 0;
12769 rtx x = operands[3];
12770
12771 if (TARGET_SH2A && TARGET_BITOPS
12772 && (satisfies_constraint_Sbw (operands[0])
12773 || satisfies_constraint_Sbv (operands[0]))
12774 && satisfies_constraint_M (operands[1])
12775 && satisfies_constraint_K03 (operands[2]))
12776 {
12777 if (satisfies_constraint_N (operands[3]))
12778 {
12779 emit_insn (gen_bclr_m2a (operands[0], operands[2]));
12780 DONE;
12781 }
12782 else if (satisfies_constraint_M (operands[3]))
12783 {
12784 emit_insn (gen_bset_m2a (operands[0], operands[2]));
12785 DONE;
12786 }
12787 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
12788 && satisfies_constraint_M (operands[1]))
12789 {
12790 emit_insn (gen_bst_m2a (operands[0], operands[2]));
12791 DONE;
12792 }
12793 else if (REG_P (operands[3])
12794 && satisfies_constraint_M (operands[1]))
12795 {
12796 emit_insn (gen_bld_reg (operands[3], const0_rtx));
12797 emit_insn (gen_bst_m2a (operands[0], operands[2]));
12798 DONE;
12799 }
12800 }
12801 /* ??? expmed doesn't care for non-register predicates. */
12802 if (! memory_operand (operands[0], VOIDmode)
12803 || ! immediate_operand (operands[1], VOIDmode)
12804 || ! immediate_operand (operands[2], VOIDmode)
12805 || ! general_operand (x, VOIDmode))
12806 FAIL;
12807 /* If this isn't a 16 / 24 / 32 bit field, or if
12808 it doesn't start on a byte boundary, then fail. */
12809 bitsize = INTVAL (operands[1]);
12810 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
12811 || (INTVAL (operands[2]) % 8) != 0)
12812 FAIL;
12813
12814 size = bitsize / 8;
12815 orig_address = XEXP (operands[0], 0);
12816 shift_reg = gen_reg_rtx (SImode);
12817 if (CONST_INT_P (x))
12818 {
12819 v = INTVAL (x);
12820 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
12821 }
12822 else
12823 {
12824 emit_insn (gen_movsi (shift_reg, operands[3]));
12825 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
12826 }
12827 addr_target = copy_addr_to_reg (plus_constant (Pmode,
12828 orig_address, size - 1));
12829
12830 operands[0] = replace_equiv_address (operands[0], addr_target);
12831 emit_insn (gen_movqi (operands[0], qi_val));
12832
12833 while (size -= 1)
12834 {
12835 if (CONST_INT_P (x))
12836 qi_val
12837 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
12838 else
12839 {
12840 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
12841 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
12842 }
12843 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
12844 emit_insn (gen_movqi (operands[0], qi_val));
12845 }
12846
12847 DONE;
12848 })
12849
12850 (define_insn "movua"
12851 [(set (match_operand:SI 0 "register_operand" "=z")
12852 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
12853 UNSPEC_MOVUA))]
12854 "TARGET_SH4A_ARCH"
12855 "movua.l %1,%0"
12856 [(set_attr "type" "movua")])
12857
12858 ;; We shouldn't need this, but cse replaces increments with references
12859 ;; to other regs before flow has a chance to create post_inc
12860 ;; addressing modes, and only postreload's cse_move2add brings the
12861 ;; increments back to a usable form.
12862 (define_peephole2
12863 [(set (match_operand:SI 0 "register_operand" "")
12864 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
12865 (const_int 32) (const_int 0)))
12866 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
12867 "TARGET_SH4A_ARCH && REGNO (operands[0]) != REGNO (operands[1])"
12868 [(set (match_operand:SI 0 "register_operand" "")
12869 (sign_extract:SI (mem:SI (post_inc:SI
12870 (match_operand:SI 1 "register_operand" "")))
12871 (const_int 32) (const_int 0)))]
12872 "")
12873
12874 (define_expand "extv"
12875 [(set (match_operand:SI 0 "register_operand" "")
12876 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
12877 (match_operand 2 "const_int_operand" "")
12878 (match_operand 3 "const_int_operand" "")))]
12879 "TARGET_SH4A_ARCH || TARGET_SH2A"
12880 {
12881 if (TARGET_SH2A && TARGET_BITOPS
12882 && (satisfies_constraint_Sbw (operands[1])
12883 || satisfies_constraint_Sbv (operands[1]))
12884 && satisfies_constraint_M (operands[2])
12885 && satisfies_constraint_K03 (operands[3]))
12886 {
12887 emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
12888 if (REGNO (operands[0]) != T_REG)
12889 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
12890 DONE;
12891 }
12892 if (TARGET_SH4A_ARCH
12893 && INTVAL (operands[2]) == 32
12894 && INTVAL (operands[3]) == 0
12895 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
12896 {
12897 rtx src = adjust_address (operands[1], BLKmode, 0);
12898 set_mem_size (src, 4);
12899 emit_insn (gen_movua (operands[0], src));
12900 DONE;
12901 }
12902
12903 FAIL;
12904 })
12905
12906 (define_expand "extzv"
12907 [(set (match_operand:SI 0 "register_operand" "")
12908 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
12909 (match_operand 2 "const_int_operand" "")
12910 (match_operand 3 "const_int_operand" "")))]
12911 "TARGET_SH4A_ARCH || TARGET_SH2A"
12912 {
12913 if (TARGET_SH2A && TARGET_BITOPS
12914 && (satisfies_constraint_Sbw (operands[1])
12915 || satisfies_constraint_Sbv (operands[1]))
12916 && satisfies_constraint_M (operands[2])
12917 && satisfies_constraint_K03 (operands[3]))
12918 {
12919 emit_insn (gen_bld_m2a (operands[1], operands[3]));
12920 if (REGNO (operands[0]) != T_REG)
12921 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
12922 DONE;
12923 }
12924 if (TARGET_SH4A_ARCH
12925 && INTVAL (operands[2]) == 32
12926 && INTVAL (operands[3]) == 0
12927 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
12928 {
12929 rtx src = adjust_address (operands[1], BLKmode, 0);
12930 set_mem_size (src, 4);
12931 emit_insn (gen_movua (operands[0], src));
12932 DONE;
12933 }
12934
12935 FAIL;
12936 })
12937
12938 ;; SH2A instructions for bitwise operations.
12939
12940 ;; Clear a bit in a memory location.
12941 (define_insn "bclr_m2a"
12942 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
12943 (and:QI
12944 (not:QI (ashift:QI (const_int 1)
12945 (match_operand:QI 1 "const_int_operand" "K03,K03")))
12946 (match_dup 0)))]
12947 "TARGET_SH2A && TARGET_BITOPS"
12948 "@
12949 bclr.b %1,%0
12950 bclr.b %1,@(0,%t0)"
12951 [(set_attr "length" "4,4")])
12952
12953 (define_insn "bclrmem_m2a"
12954 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
12955 (and:QI (match_dup 0)
12956 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
12957 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
12958 "@
12959 bclr.b %W1,%0
12960 bclr.b %W1,@(0,%t0)"
12961 [(set_attr "length" "4,4")])
12962
12963 ;; Set a bit in a memory location.
12964 (define_insn "bset_m2a"
12965 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
12966 (ior:QI
12967 (ashift:QI (const_int 1)
12968 (match_operand:QI 1 "const_int_operand" "K03,K03"))
12969 (match_dup 0)))]
12970 "TARGET_SH2A && TARGET_BITOPS"
12971 "@
12972 bset.b %1,%0
12973 bset.b %1,@(0,%t0)"
12974 [(set_attr "length" "4,4")])
12975
12976 (define_insn "bsetmem_m2a"
12977 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
12978 (ior:QI (match_dup 0)
12979 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
12980 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
12981 "@
12982 bset.b %V1,%0
12983 bset.b %V1,@(0,%t0)"
12984 [(set_attr "length" "4,4")])
12985
12986 ;;; Transfer the contents of the T bit to a specified bit of memory.
12987 (define_insn "bst_m2a"
12988 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
12989 (if_then_else (eq (reg:SI T_REG) (const_int 0))
12990 (and:QI
12991 (not:QI (ashift:QI (const_int 1)
12992 (match_operand:QI 1 "const_int_operand" "K03,K03")))
12993 (match_dup 0))
12994 (ior:QI
12995 (ashift:QI (const_int 1) (match_dup 1))
12996 (match_dup 0))))]
12997 "TARGET_SH2A && TARGET_BITOPS"
12998 "@
12999 bst.b %1,%0
13000 bst.b %1,@(0,%t0)"
13001 [(set_attr "length" "4")])
13002
13003 ;; Store a specified bit of memory in the T bit.
13004 (define_insn "bld_m2a"
13005 [(set (reg:SI T_REG)
13006 (zero_extract:SI
13007 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
13008 (const_int 1)
13009 (match_operand 1 "const_int_operand" "K03,K03")))]
13010 "TARGET_SH2A && TARGET_BITOPS"
13011 "@
13012 bld.b %1,%0
13013 bld.b %1,@(0,%t0)"
13014 [(set_attr "length" "4,4")])
13015
13016 ;; Store a specified bit of memory in the T bit.
13017 (define_insn "bldsign_m2a"
13018 [(set (reg:SI T_REG)
13019 (sign_extract:SI
13020 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13021 (const_int 1)
13022 (match_operand 1 "const_int_operand" "K03,K03")))]
13023 "TARGET_SH2A && TARGET_BITOPS"
13024 "@
13025 bld.b %1,%0
13026 bld.b %1,@(0,%t0)"
13027 [(set_attr "length" "4,4")])
13028
13029 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
13030 (define_insn "bld_reg"
13031 [(set (reg:SI T_REG)
13032 (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
13033 (const_int 1)
13034 (match_operand 1 "const_int_operand" "K03")))]
13035 "TARGET_SH2A"
13036 "bld %1,%0")
13037
13038 (define_insn "*bld_regqi"
13039 [(set (reg:SI T_REG)
13040 (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
13041 (const_int 1)
13042 (match_operand 1 "const_int_operand" "K03")))]
13043 "TARGET_SH2A"
13044 "bld %1,%0")
13045
13046 ;; Take logical and of a specified bit of memory with the T bit and
13047 ;; store its result in the T bit.
13048 (define_insn "band_m2a"
13049 [(set (reg:SI T_REG)
13050 (and:SI (reg:SI T_REG)
13051 (zero_extract:SI
13052 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13053 (const_int 1)
13054 (match_operand 1 "const_int_operand" "K03,K03"))))]
13055 "TARGET_SH2A && TARGET_BITOPS"
13056 "@
13057 band.b %1,%0
13058 band.b %1,@(0,%t0)"
13059 [(set_attr "length" "4,4")])
13060
13061 (define_insn "bandreg_m2a"
13062 [(set (match_operand:SI 0 "register_operand" "=r,r")
13063 (and:SI (zero_extract:SI
13064 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13065 (const_int 1)
13066 (match_operand 2 "const_int_operand" "K03,K03"))
13067 (match_operand:SI 3 "register_operand" "r,r")))]
13068 "TARGET_SH2A && TARGET_BITOPS"
13069 {
13070 static const char* alt[] =
13071 {
13072 "band.b %2,%1" "\n"
13073 " movt %0",
13074
13075 "band.b %2,@(0,%t1)" "\n"
13076 " movt %0"
13077 };
13078 return alt[which_alternative];
13079 }
13080 [(set_attr "length" "6,6")])
13081
13082 ;; Take logical or of a specified bit of memory with the T bit and
13083 ;; store its result in the T bit.
13084 (define_insn "bor_m2a"
13085 [(set (reg:SI T_REG)
13086 (ior:SI (reg:SI T_REG)
13087 (zero_extract:SI
13088 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13089 (const_int 1)
13090 (match_operand 1 "const_int_operand" "K03,K03"))))]
13091 "TARGET_SH2A && TARGET_BITOPS"
13092 "@
13093 bor.b %1,%0
13094 bor.b %1,@(0,%t0)"
13095 [(set_attr "length" "4,4")])
13096
13097 (define_insn "borreg_m2a"
13098 [(set (match_operand:SI 0 "register_operand" "=r,r")
13099 (ior:SI (zero_extract:SI
13100 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13101 (const_int 1)
13102 (match_operand 2 "const_int_operand" "K03,K03"))
13103 (match_operand:SI 3 "register_operand" "=r,r")))]
13104 "TARGET_SH2A && TARGET_BITOPS"
13105 {
13106 static const char* alt[] =
13107 {
13108 "bor.b %2,%1" "\n"
13109 " movt %0",
13110
13111 "bor.b %2,@(0,%t1)" "\n"
13112 " movt %0"
13113 };
13114 return alt[which_alternative];
13115 }
13116 [(set_attr "length" "6,6")])
13117
13118 ;; Take exclusive or of a specified bit of memory with the T bit and
13119 ;; store its result in the T bit.
13120 (define_insn "bxor_m2a"
13121 [(set (reg:SI T_REG)
13122 (xor:SI (reg:SI T_REG)
13123 (zero_extract:SI
13124 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
13125 (const_int 1)
13126 (match_operand 1 "const_int_operand" "K03,K03"))))]
13127 "TARGET_SH2A && TARGET_BITOPS"
13128 "@
13129 bxor.b %1,%0
13130 bxor.b %1,@(0,%t0)"
13131 [(set_attr "length" "4,4")])
13132
13133 (define_insn "bxorreg_m2a"
13134 [(set (match_operand:SI 0 "register_operand" "=r,r")
13135 (xor:SI (zero_extract:SI
13136 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
13137 (const_int 1)
13138 (match_operand 2 "const_int_operand" "K03,K03"))
13139 (match_operand:SI 3 "register_operand" "=r,r")))]
13140 "TARGET_SH2A && TARGET_BITOPS"
13141 {
13142 static const char* alt[] =
13143 {
13144 "bxor.b %2,%1" "\n"
13145 " movt %0",
13146
13147 "bxor.b %2,@(0,%t1)" "\n"
13148 " movt %0"
13149 };
13150 return alt[which_alternative];
13151 }
13152 [(set_attr "length" "6,6")])
13153
13154 \f
13155 ;; -------------------------------------------------------------------------
13156 ;; Peepholes
13157 ;; -------------------------------------------------------------------------
13158 ;; This matches cases where the bit in a memory location is set.
13159 (define_peephole2
13160 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13161 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13162 (set (match_dup 0)
13163 (ior:SI (match_dup 0)
13164 (match_operand:SI 2 "const_int_operand" "Pso,Pso")))
13165 (set (match_dup 1)
13166 (match_operand 3 "arith_reg_operand" "r,r"))]
13167 "TARGET_SH2A && TARGET_BITOPS
13168 && satisfies_constraint_Pso (operands[2])
13169 && REGNO (operands[0]) == REGNO (operands[3])"
13170 [(set (match_dup 1)
13171 (ior:QI (match_dup 1)
13172 (match_dup 2)))]
13173 "")
13174
13175 ;; This matches cases where the bit in a memory location is cleared.
13176 (define_peephole2
13177 [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
13178 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
13179 (set (match_dup 0)
13180 (and:SI (match_dup 0)
13181 (match_operand:SI 2 "const_int_operand" "Psz,Psz")))
13182 (set (match_dup 1)
13183 (match_operand 3 "arith_reg_operand" "r,r"))]
13184 "TARGET_SH2A && TARGET_BITOPS
13185 && satisfies_constraint_Psz (operands[2])
13186 && REGNO (operands[0]) == REGNO (operands[3])"
13187 [(set (match_dup 1)
13188 (and:QI (match_dup 1)
13189 (match_dup 2)))]
13190 "")
13191
13192 ;; This matches cases where a stack pointer increment at the start of the
13193 ;; epilogue combines with a stack slot read loading the return value.
13194
13195 (define_peephole
13196 [(set (match_operand:SI 0 "arith_reg_operand" "")
13197 (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
13198 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
13199 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
13200 "mov.l @%1+,%0")
13201
13202 ;; See the comment on the dt combiner pattern above.
13203
13204 (define_peephole
13205 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
13206 (plus:SI (match_dup 0)
13207 (const_int -1)))
13208 (set (reg:SI T_REG)
13209 (eq:SI (match_dup 0)
13210 (const_int 0)))]
13211 "TARGET_SH2"
13212 "dt %0")
13213
13214 ;; The following peepholes fold load sequences for which reload was not
13215 ;; able to generate a displacement addressing move insn.
13216 ;; This can happen when reload has to transform a move insn
13217 ;; without displacement into one with displacement. Or when reload can't
13218 ;; fit a displacement into the insn's constraints. In the latter case, the
13219 ;; load destination reg remains at r0, which reload compensates by inserting
13220 ;; another mov insn.
13221
13222 ;; Fold sequence:
13223 ;; mov #54,r0
13224 ;; mov.{b,w} @(r0,r15),r0
13225 ;; mov r0,r3
13226 ;; into:
13227 ;; mov.{b,w} @(54,r15),r3
13228 ;;
13229 (define_peephole2
13230 [(set (match_operand:SI 0 "arith_reg_dest" "")
13231 (match_operand:SI 1 "const_int_operand" ""))
13232 (set (match_operand:SI 2 "arith_reg_dest" "")
13233 (sign_extend:SI
13234 (mem:QI (plus:SI (match_dup 0)
13235 (match_operand:SI 3 "arith_reg_operand" "")))))
13236 (set (match_operand:QI 4 "arith_reg_dest" "")
13237 (match_operand:QI 5 "arith_reg_operand" ""))]
13238 "TARGET_SH2A
13239 && sh_legitimate_index_p (QImode, operands[1], true, true)
13240 && REGNO (operands[2]) == REGNO (operands[5])
13241 && peep2_reg_dead_p (3, operands[5])"
13242 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
13243 "")
13244
13245 (define_peephole2
13246 [(set (match_operand:SI 0 "arith_reg_dest" "")
13247 (match_operand:SI 1 "const_int_operand" ""))
13248 (set (match_operand:SI 2 "arith_reg_dest" "")
13249 (sign_extend:SI
13250 (mem:HI (plus:SI (match_dup 0)
13251 (match_operand:SI 3 "arith_reg_operand" "")))))
13252 (set (match_operand:HI 4 "arith_reg_dest" "")
13253 (match_operand:HI 5 "arith_reg_operand" ""))]
13254 "TARGET_SH2A
13255 && sh_legitimate_index_p (HImode, operands[1], true, true)
13256 && REGNO (operands[2]) == REGNO (operands[5])
13257 && peep2_reg_dead_p (3, operands[5])"
13258 [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
13259 "")
13260
13261 ;; Fold sequence:
13262 ;; mov #54,r0
13263 ;; mov.{b,w} @(r0,r15),r1
13264 ;; into:
13265 ;; mov.{b,w} @(54,r15),r1
13266 ;;
13267 (define_peephole2
13268 [(set (match_operand:SI 0 "arith_reg_dest" "")
13269 (match_operand:SI 1 "const_int_operand" ""))
13270 (set (match_operand:SI 2 "arith_reg_dest" "")
13271 (sign_extend:SI
13272 (mem:QI (plus:SI (match_dup 0)
13273 (match_operand:SI 3 "arith_reg_operand" "")))))]
13274 "TARGET_SH2A
13275 && sh_legitimate_index_p (QImode, operands[1], true, true)
13276 && (peep2_reg_dead_p (2, operands[0])
13277 || REGNO (operands[0]) == REGNO (operands[2]))"
13278 [(set (match_dup 2)
13279 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
13280 "")
13281
13282 (define_peephole2
13283 [(set (match_operand:SI 0 "arith_reg_dest" "")
13284 (match_operand:SI 1 "const_int_operand" ""))
13285 (set (match_operand:SI 2 "arith_reg_dest" "")
13286 (sign_extend:SI
13287 (mem:HI (plus:SI (match_dup 0)
13288 (match_operand:SI 3 "arith_reg_operand" "")))))]
13289 "TARGET_SH2A
13290 && sh_legitimate_index_p (HImode, operands[1], true, true)
13291 && (peep2_reg_dead_p (2, operands[0])
13292 || REGNO (operands[0]) == REGNO (operands[2]))"
13293 [(set (match_dup 2)
13294 (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
13295 "")
13296
13297 ;; Fold sequence:
13298 ;; mov.{b,w} @(r0,r15),r0
13299 ;; mov r0,r3
13300 ;; into:
13301 ;; mov.{b,w} @(r0,r15),r3
13302 ;;
13303 ;; This can happen when initially a displacement address is picked, where
13304 ;; the destination reg is fixed to r0, and then the address is transformed
13305 ;; into 'r0 + reg'.
13306 (define_peephole2
13307 [(set (match_operand:SI 0 "arith_reg_dest" "")
13308 (sign_extend:SI
13309 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13310 (match_operand:SI 2 "arith_reg_operand" "")))))
13311 (set (match_operand:QI 3 "arith_reg_dest" "")
13312 (match_operand:QI 4 "arith_reg_operand" ""))]
13313 "TARGET_SH1
13314 && REGNO (operands[0]) == REGNO (operands[4])
13315 && peep2_reg_dead_p (2, operands[0])"
13316 [(set (match_dup 3)
13317 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
13318 "")
13319
13320 (define_peephole2
13321 [(set (match_operand:SI 0 "arith_reg_dest" "")
13322 (sign_extend:SI
13323 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
13324 (match_operand:SI 2 "arith_reg_operand" "")))))
13325 (set (match_operand:HI 3 "arith_reg_dest" "")
13326 (match_operand:HI 4 "arith_reg_operand" ""))]
13327 "TARGET_SH1
13328 && REGNO (operands[0]) == REGNO (operands[4])
13329 && peep2_reg_dead_p (2, operands[0])"
13330 [(set (match_dup 3)
13331 (mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
13332 "")
13333
13334 (define_peephole
13335 [(set (match_operand:SI 0 "register_operand" "=r")
13336 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13337 (set (mem:SF (match_dup 0))
13338 (match_operand:SF 2 "general_movsrc_operand" ""))]
13339 "TARGET_SH1 && REGNO (operands[0]) == 0
13340 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13341 || (GET_CODE (operands[2]) == SUBREG
13342 && REGNO (SUBREG_REG (operands[2])) < 16))
13343 && reg_unused_after (operands[0], insn)"
13344 "mov.l %2,@(%0,%1)")
13345
13346 (define_peephole
13347 [(set (match_operand:SI 0 "register_operand" "=r")
13348 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13349 (set (match_operand:SF 2 "general_movdst_operand" "")
13350
13351 (mem:SF (match_dup 0)))]
13352 "TARGET_SH1 && REGNO (operands[0]) == 0
13353 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
13354 || (GET_CODE (operands[2]) == SUBREG
13355 && REGNO (SUBREG_REG (operands[2])) < 16))
13356 && reg_unused_after (operands[0], insn)"
13357 "mov.l @(%0,%1),%2")
13358
13359 (define_peephole
13360 [(set (match_operand:SI 0 "register_operand" "=r")
13361 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13362 (set (mem:SF (match_dup 0))
13363 (match_operand:SF 2 "general_movsrc_operand" ""))]
13364 "TARGET_SH2E && REGNO (operands[0]) == 0
13365 && ((REG_P (operands[2])
13366 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13367 || (GET_CODE (operands[2]) == SUBREG
13368 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13369 && reg_unused_after (operands[0], insn)"
13370 "fmov{.s|} %2,@(%0,%1)")
13371
13372 (define_peephole
13373 [(set (match_operand:SI 0 "register_operand" "=r")
13374 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
13375 (set (match_operand:SF 2 "general_movdst_operand" "")
13376
13377 (mem:SF (match_dup 0)))]
13378 "TARGET_SH2E && REGNO (operands[0]) == 0
13379 && ((REG_P (operands[2])
13380 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
13381 || (GET_CODE (operands[2]) == SUBREG
13382 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
13383 && reg_unused_after (operands[0], insn)"
13384 "fmov{.s|} @(%0,%1),%2")
13385
13386 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
13387 (define_insn "sp_switch_1"
13388 [(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
13389 "TARGET_SH1"
13390 {
13391 return "mov.l r0,@-r15" "\n"
13392 " mov.l %0,r0" "\n"
13393 " mov.l @r0,r0" "\n"
13394 " mov.l r15,@-r0" "\n"
13395 " mov r0,r15";
13396 }
13397 [(set_attr "length" "10")])
13398
13399 ;; Switch back to the original stack for interrupt functions with the
13400 ;; sp_switch attribute.
13401 (define_insn "sp_switch_2"
13402 [(const_int 2)]
13403 "TARGET_SH1"
13404 {
13405 return "mov.l @r15+,r15" "\n"
13406 " mov.l @r15+,r0";
13407 }
13408 [(set_attr "length" "4")])
13409
13410 ;; Integer vector moves
13411
13412 (define_expand "movv8qi"
13413 [(set (match_operand:V8QI 0 "general_movdst_operand" "")
13414 (match_operand:V8QI 1 "general_movsrc_operand" ""))]
13415 "TARGET_SHMEDIA"
13416 {
13417 prepare_move_operands (operands, V8QImode);
13418 })
13419
13420 (define_insn "movv8qi_i"
13421 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
13422 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13423 "TARGET_SHMEDIA
13424 && (register_operand (operands[0], V8QImode)
13425 || sh_register_operand (operands[1], V8QImode))"
13426 "@
13427 add %1, r63, %0
13428 movi %1, %0
13429 #
13430 ld%M1.q %m1, %0
13431 st%M0.q %m0, %N1"
13432 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
13433 (set_attr "length" "4,4,16,4,4")])
13434
13435 (define_split
13436 [(set (match_operand:V8QI 0 "arith_reg_dest" "")
13437 (subreg:V8QI (const_int 0) 0))]
13438 "TARGET_SHMEDIA"
13439 [(set (match_dup 0)
13440 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
13441 (const_int 0) (const_int 0) (const_int 0)
13442 (const_int 0) (const_int 0)]))])
13443
13444 (define_split
13445 [(set (match_operand 0 "arith_reg_dest" "")
13446 (match_operand 1 "sh_rep_vec" ""))]
13447 "TARGET_SHMEDIA && reload_completed
13448 && GET_MODE (operands[0]) == GET_MODE (operands[1])
13449 && sh_vector_mode_supported_p (GET_MODE (operands[0]))
13450 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
13451 && (XVECEXP (operands[1], 0, 0) != const0_rtx
13452 || XVECEXP (operands[1], 0, 1) != const0_rtx)
13453 && (XVECEXP (operands[1], 0, 0) != constm1_rtx
13454 || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
13455 [(set (match_dup 0) (match_dup 1))
13456 (match_dup 2)]
13457 {
13458 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
13459 rtx elt1 = XVECEXP (operands[1], 0, 1);
13460
13461 if (unit_size > 2)
13462 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
13463 else
13464 {
13465 if (unit_size < 2)
13466 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
13467 operands[2] = gen_mperm_w0 (operands[0], operands[0]);
13468 }
13469 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
13470 operands[1] = XVECEXP (operands[1], 0, 0);
13471 if (unit_size < 2)
13472 {
13473 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
13474 operands[1]
13475 = GEN_INT (TARGET_LITTLE_ENDIAN
13476 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
13477 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
13478 else
13479 {
13480 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
13481 operands[1]
13482 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
13483 }
13484 }
13485 })
13486
13487 (define_split
13488 [(set (match_operand 0 "arith_reg_dest" "")
13489 (match_operand 1 "sh_const_vec" ""))]
13490 "TARGET_SHMEDIA && reload_completed
13491 && GET_MODE (operands[0]) == GET_MODE (operands[1])
13492 && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
13493 [(set (match_dup 0) (match_dup 1))]
13494 {
13495 rtx v = operands[1];
13496 enum machine_mode new_mode
13497 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
13498
13499 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
13500 operands[1]
13501 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
13502 })
13503
13504 (define_expand "movv2hi"
13505 [(set (match_operand:V2HI 0 "general_movdst_operand" "")
13506 (match_operand:V2HI 1 "general_movsrc_operand" ""))]
13507 "TARGET_SHMEDIA"
13508 {
13509 prepare_move_operands (operands, V2HImode);
13510 })
13511
13512 (define_insn "movv2hi_i"
13513 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
13514 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13515 "TARGET_SHMEDIA
13516 && (register_operand (operands[0], V2HImode)
13517 || sh_register_operand (operands[1], V2HImode))"
13518 "@
13519 add.l %1, r63, %0
13520 movi %1, %0
13521 #
13522 ld%M1.l %m1, %0
13523 st%M0.l %m0, %N1"
13524 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
13525 (set_attr "length" "4,4,16,4,4")
13526 (set (attr "highpart")
13527 (cond [(match_test "sh_contains_memref_p (insn)")
13528 (const_string "user")]
13529 (const_string "ignore")))])
13530
13531 (define_expand "movv4hi"
13532 [(set (match_operand:V4HI 0 "general_movdst_operand" "")
13533 (match_operand:V4HI 1 "general_movsrc_operand" ""))]
13534 "TARGET_SHMEDIA"
13535 {
13536 prepare_move_operands (operands, V4HImode);
13537 })
13538
13539 (define_insn "movv4hi_i"
13540 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
13541 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13542 "TARGET_SHMEDIA
13543 && (register_operand (operands[0], V4HImode)
13544 || sh_register_operand (operands[1], V4HImode))"
13545 "@
13546 add %1, r63, %0
13547 movi %1, %0
13548 #
13549 ld%M1.q %m1, %0
13550 st%M0.q %m0, %N1"
13551 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
13552 (set_attr "length" "4,4,16,4,4")
13553 (set_attr "highpart" "depend")])
13554
13555 (define_expand "movv2si"
13556 [(set (match_operand:V2SI 0 "general_movdst_operand" "")
13557 (match_operand:V2SI 1 "general_movsrc_operand" ""))]
13558 "TARGET_SHMEDIA"
13559 {
13560 prepare_move_operands (operands, V2SImode);
13561 })
13562
13563 (define_insn "movv2si_i"
13564 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
13565 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
13566 "TARGET_SHMEDIA
13567 && (register_operand (operands[0], V2SImode)
13568 || sh_register_operand (operands[1], V2SImode))"
13569 "@
13570 add %1, r63, %0
13571 #
13572 #
13573 ld%M1.q %m1, %0
13574 st%M0.q %m0, %N1"
13575 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
13576 (set_attr "length" "4,4,16,4,4")
13577 (set_attr "highpart" "depend")])
13578
13579 ;; Multimedia Intrinsics
13580
13581 (define_insn "absv2si2"
13582 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13583 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
13584 "TARGET_SHMEDIA"
13585 "mabs.l %1, %0"
13586 [(set_attr "type" "mcmp_media")
13587 (set_attr "highpart" "depend")])
13588
13589 (define_insn "absv4hi2"
13590 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13591 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
13592 "TARGET_SHMEDIA"
13593 "mabs.w %1, %0"
13594 [(set_attr "type" "mcmp_media")
13595 (set_attr "highpart" "depend")])
13596
13597 (define_insn "addv2si3"
13598 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13599 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
13600 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13601 "TARGET_SHMEDIA"
13602 "madd.l %1, %2, %0"
13603 [(set_attr "type" "arith_media")
13604 (set_attr "highpart" "depend")])
13605
13606 (define_insn "addv4hi3"
13607 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13608 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
13609 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13610 "TARGET_SHMEDIA"
13611 "madd.w %1, %2, %0"
13612 [(set_attr "type" "arith_media")
13613 (set_attr "highpart" "depend")])
13614
13615 (define_insn_and_split "addv2hi3"
13616 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
13617 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
13618 (match_operand:V2HI 2 "extend_reg_operand" "r")))]
13619 "TARGET_SHMEDIA"
13620 "#"
13621 "TARGET_SHMEDIA"
13622 [(const_int 0)]
13623 {
13624 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
13625 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
13626 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
13627 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
13628 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
13629
13630 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
13631 emit_insn (gen_truncdisi2 (si_dst, di_dst));
13632 DONE;
13633 }
13634 [(set_attr "highpart" "must_split")])
13635
13636 (define_insn "ssaddv2si3"
13637 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13638 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
13639 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13640 "TARGET_SHMEDIA"
13641 "madds.l %1, %2, %0"
13642 [(set_attr "type" "mcmp_media")
13643 (set_attr "highpart" "depend")])
13644
13645 (define_insn "usaddv8qi3"
13646 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13647 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
13648 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
13649 "TARGET_SHMEDIA"
13650 "madds.ub %1, %2, %0"
13651 [(set_attr "type" "mcmp_media")
13652 (set_attr "highpart" "depend")])
13653
13654 (define_insn "ssaddv4hi3"
13655 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13656 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
13657 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13658 "TARGET_SHMEDIA"
13659 "madds.w %1, %2, %0"
13660 [(set_attr "type" "mcmp_media")
13661 (set_attr "highpart" "depend")])
13662
13663 (define_insn "negcmpeqv8qi"
13664 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13665 (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
13666 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
13667 "TARGET_SHMEDIA"
13668 "mcmpeq.b %N1, %N2, %0"
13669 [(set_attr "type" "mcmp_media")
13670 (set_attr "highpart" "depend")])
13671
13672 (define_insn "negcmpeqv2si"
13673 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13674 (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
13675 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
13676 "TARGET_SHMEDIA"
13677 "mcmpeq.l %N1, %N2, %0"
13678 [(set_attr "type" "mcmp_media")
13679 (set_attr "highpart" "depend")])
13680
13681 (define_insn "negcmpeqv4hi"
13682 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13683 (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
13684 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13685 "TARGET_SHMEDIA"
13686 "mcmpeq.w %N1, %N2, %0"
13687 [(set_attr "type" "mcmp_media")
13688 (set_attr "highpart" "depend")])
13689
13690 (define_insn "negcmpgtuv8qi"
13691 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13692 (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
13693 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
13694 "TARGET_SHMEDIA"
13695 "mcmpgt.ub %N1, %N2, %0"
13696 [(set_attr "type" "mcmp_media")
13697 (set_attr "highpart" "depend")])
13698
13699 (define_insn "negcmpgtv2si"
13700 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13701 (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
13702 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
13703 "TARGET_SHMEDIA"
13704 "mcmpgt.l %N1, %N2, %0"
13705 [(set_attr "type" "mcmp_media")
13706 (set_attr "highpart" "depend")])
13707
13708 (define_insn "negcmpgtv4hi"
13709 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13710 (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
13711 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13712 "TARGET_SHMEDIA"
13713 "mcmpgt.w %N1, %N2, %0"
13714 [(set_attr "type" "mcmp_media")
13715 (set_attr "highpart" "depend")])
13716
13717 (define_insn "mcmv"
13718 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13719 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13720 (match_operand:DI 2 "arith_reg_operand" "r"))
13721 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
13722 (not:DI (match_dup 2)))))]
13723 "TARGET_SHMEDIA"
13724 "mcmv %N1, %2, %0"
13725 [(set_attr "type" "arith_media")
13726 (set_attr "highpart" "depend")])
13727
13728 (define_insn "mcnvs_lw"
13729 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13730 (vec_concat:V4HI
13731 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
13732 (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
13733 "TARGET_SHMEDIA"
13734 "mcnvs.lw %N1, %N2, %0"
13735 [(set_attr "type" "mcmp_media")])
13736
13737 (define_insn "mcnvs_wb"
13738 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13739 (vec_concat:V8QI
13740 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
13741 (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13742 "TARGET_SHMEDIA"
13743 "mcnvs.wb %N1, %N2, %0"
13744 [(set_attr "type" "mcmp_media")])
13745
13746 (define_insn "mcnvs_wub"
13747 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
13748 (vec_concat:V8QI
13749 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
13750 (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
13751 "TARGET_SHMEDIA"
13752 "mcnvs.wub %N1, %N2, %0"
13753 [(set_attr "type" "mcmp_media")])
13754
13755 (define_insn "mextr_rl"
13756 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13757 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13758 (match_operand:HI 3 "mextr_bit_offset" "i"))
13759 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13760 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
13761 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
13762 {
13763 static char templ[21];
13764 sprintf (templ, "mextr%d %%N1, %%N2, %%0",
13765 (int) INTVAL (operands[3]) >> 3);
13766 return templ;
13767 }
13768 [(set_attr "type" "arith_media")])
13769
13770 (define_insn "*mextr_lr"
13771 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
13772 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13773 (match_operand:HI 3 "mextr_bit_offset" "i"))
13774 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
13775 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
13776 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
13777 {
13778 static char templ[21];
13779 sprintf (templ, "mextr%d %%N2, %%N1, %%0",
13780 (int) INTVAL (operands[4]) >> 3);
13781 return templ;
13782 }
13783 [(set_attr "type" "arith_media")])
13784
13785 ; mextrN can be modelled with vec_select / vec_concat, but the selection
13786 ; vector then varies depending on endianness.
13787 (define_expand "mextr1"
13788 [(match_operand:DI 0 "arith_reg_dest" "")
13789 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13790 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
13791 "TARGET_SHMEDIA"
13792 {
13793 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
13794 GEN_INT (1 * 8), GEN_INT (7 * 8)));
13795 DONE;
13796 })
13797
13798 (define_expand "mextr2"
13799 [(match_operand:DI 0 "arith_reg_dest" "")
13800 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13801 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
13802 "TARGET_SHMEDIA"
13803 {
13804 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
13805 GEN_INT (2 * 8), GEN_INT (6 * 8)));
13806 DONE;
13807 })
13808
13809 (define_expand "mextr3"
13810 [(match_operand:DI 0 "arith_reg_dest" "")
13811 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13812 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
13813 "TARGET_SHMEDIA"
13814 {
13815 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
13816 GEN_INT (3 * 8), GEN_INT (5 * 8)));
13817 DONE;
13818 })
13819
13820 (define_expand "mextr4"
13821 [(match_operand:DI 0 "arith_reg_dest" "")
13822 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13823 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
13824 "TARGET_SHMEDIA"
13825 {
13826 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
13827 GEN_INT (4 * 8), GEN_INT (4 * 8)));
13828 DONE;
13829 })
13830
13831 (define_expand "mextr5"
13832 [(match_operand:DI 0 "arith_reg_dest" "")
13833 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13834 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
13835 "TARGET_SHMEDIA"
13836 {
13837 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
13838 GEN_INT (5 * 8), GEN_INT (3 * 8)));
13839 DONE;
13840 })
13841
13842 (define_expand "mextr6"
13843 [(match_operand:DI 0 "arith_reg_dest" "")
13844 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13845 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
13846 "TARGET_SHMEDIA"
13847 {
13848 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
13849 GEN_INT (6 * 8), GEN_INT (2 * 8)));
13850 DONE;
13851 })
13852
13853 (define_expand "mextr7"
13854 [(match_operand:DI 0 "arith_reg_dest" "")
13855 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
13856 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
13857 "TARGET_SHMEDIA"
13858 {
13859 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
13860 GEN_INT (7 * 8), GEN_INT (1 * 8)));
13861 DONE;
13862 })
13863
13864 (define_expand "mmacfx_wl"
13865 [(match_operand:V2SI 0 "arith_reg_dest" "")
13866 (match_operand:V2HI 1 "extend_reg_operand" "")
13867 (match_operand:V2HI 2 "extend_reg_operand" "")
13868 (match_operand:V2SI 3 "arith_reg_operand" "")]
13869 "TARGET_SHMEDIA"
13870 {
13871 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
13872 operands[1], operands[2]));
13873 DONE;
13874 })
13875
13876 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
13877 ;; is depend
13878 (define_insn "mmacfx_wl_i"
13879 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13880 (ss_plus:V2SI
13881 (match_operand:V2SI 1 "arith_reg_operand" "0")
13882 (ss_truncate:V2SI
13883 (ashift:V2DI
13884 (sign_extend:V2DI
13885 (mult:V2SI
13886 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
13887 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
13888 (const_int 1)))))]
13889 "TARGET_SHMEDIA"
13890 "mmacfx.wl %2, %3, %0"
13891 [(set_attr "type" "mac_media")
13892 (set_attr "highpart" "depend")])
13893
13894 (define_expand "mmacnfx_wl"
13895 [(match_operand:V2SI 0 "arith_reg_dest" "")
13896 (match_operand:V2HI 1 "extend_reg_operand" "")
13897 (match_operand:V2HI 2 "extend_reg_operand" "")
13898 (match_operand:V2SI 3 "arith_reg_operand" "")]
13899 "TARGET_SHMEDIA"
13900 {
13901 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
13902 operands[1], operands[2]));
13903 DONE;
13904 })
13905
13906 (define_insn "mmacnfx_wl_i"
13907 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13908 (ss_minus:V2SI
13909 (match_operand:V2SI 1 "arith_reg_operand" "0")
13910 (ss_truncate:V2SI
13911 (ashift:V2DI
13912 (sign_extend:V2DI
13913 (mult:V2SI
13914 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
13915 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
13916 (const_int 1)))))]
13917 "TARGET_SHMEDIA"
13918 "mmacnfx.wl %2, %3, %0"
13919 [(set_attr "type" "mac_media")
13920 (set_attr "highpart" "depend")])
13921
13922 (define_insn "mulv2si3"
13923 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13924 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
13925 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
13926 "TARGET_SHMEDIA"
13927 "mmul.l %1, %2, %0"
13928 [(set_attr "type" "d2mpy_media")
13929 (set_attr "highpart" "depend")])
13930
13931 (define_insn "mulv4hi3"
13932 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13933 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
13934 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
13935 "TARGET_SHMEDIA"
13936 "mmul.w %1, %2, %0"
13937 [(set_attr "type" "dmpy_media")
13938 (set_attr "highpart" "depend")])
13939
13940 (define_insn "mmulfx_l"
13941 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
13942 (ss_truncate:V2SI
13943 (ashiftrt:V2DI
13944 (mult:V2DI
13945 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
13946 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
13947 (const_int 31))))]
13948 "TARGET_SHMEDIA"
13949 "mmulfx.l %1, %2, %0"
13950 [(set_attr "type" "d2mpy_media")
13951 (set_attr "highpart" "depend")])
13952
13953 (define_insn "mmulfx_w"
13954 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13955 (ss_truncate:V4HI
13956 (ashiftrt:V4SI
13957 (mult:V4SI
13958 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
13959 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
13960 (const_int 15))))]
13961 "TARGET_SHMEDIA"
13962 "mmulfx.w %1, %2, %0"
13963 [(set_attr "type" "dmpy_media")
13964 (set_attr "highpart" "depend")])
13965
13966 (define_insn "mmulfxrp_w"
13967 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
13968 (ss_truncate:V4HI
13969 (ashiftrt:V4SI
13970 (plus:V4SI
13971 (mult:V4SI
13972 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
13973 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
13974 (const_int 16384))
13975 (const_int 15))))]
13976 "TARGET_SHMEDIA"
13977 "mmulfxrp.w %1, %2, %0"
13978 [(set_attr "type" "dmpy_media")
13979 (set_attr "highpart" "depend")])
13980
13981
13982 (define_expand "mmulhi_wl"
13983 [(match_operand:V2SI 0 "arith_reg_dest" "")
13984 (match_operand:V4HI 1 "arith_reg_operand" "")
13985 (match_operand:V4HI 2 "arith_reg_operand" "")]
13986 "TARGET_SHMEDIA"
13987 {
13988 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
13989 (operands[0], operands[1], operands[2]));
13990 DONE;
13991 })
13992
13993 (define_expand "mmullo_wl"
13994 [(match_operand:V2SI 0 "arith_reg_dest" "")
13995 (match_operand:V4HI 1 "arith_reg_operand" "")
13996 (match_operand:V4HI 2 "arith_reg_operand" "")]
13997 "TARGET_SHMEDIA"
13998 {
13999 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
14000 (operands[0], operands[1], operands[2]));
14001 DONE;
14002 })
14003
14004 (define_insn "mmul23_wl"
14005 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14006 (vec_select:V2SI
14007 (mult:V4SI
14008 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14009 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14010 (parallel [(const_int 2) (const_int 3)])))]
14011 "TARGET_SHMEDIA"
14012 {
14013 return (TARGET_LITTLE_ENDIAN
14014 ? "mmulhi.wl %1, %2, %0"
14015 : "mmullo.wl %1, %2, %0");
14016 }
14017 [(set_attr "type" "dmpy_media")
14018 (set (attr "highpart")
14019 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14020 (const_string "user")))])
14021
14022 (define_insn "mmul01_wl"
14023 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14024 (vec_select:V2SI
14025 (mult:V4SI
14026 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14027 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
14028 (parallel [(const_int 0) (const_int 1)])))]
14029 "TARGET_SHMEDIA"
14030 {
14031 return (TARGET_LITTLE_ENDIAN
14032 ? "mmullo.wl %1, %2, %0"
14033 : "mmulhi.wl %1, %2, %0");
14034 }
14035 [(set_attr "type" "dmpy_media")
14036 (set (attr "highpart")
14037 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14038 (const_string "user")))])
14039
14040
14041 (define_expand "mmulsum_wq"
14042 [(match_operand:DI 0 "arith_reg_dest" "")
14043 (match_operand:V4HI 1 "arith_reg_operand" "")
14044 (match_operand:V4HI 2 "arith_reg_operand" "")
14045 (match_operand:DI 3 "arith_reg_operand" "")]
14046 "TARGET_SHMEDIA"
14047 {
14048 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
14049 operands[1], operands[2]));
14050 DONE;
14051 })
14052
14053 (define_insn "mmulsum_wq_i"
14054 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14055 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
14056 (plus:DI
14057 (plus:DI
14058 (vec_select:DI
14059 (mult:V4DI
14060 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
14061 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
14062 (parallel [(const_int 0)]))
14063 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14064 (sign_extend:V4DI (match_dup 3)))
14065 (parallel [(const_int 1)])))
14066 (plus:DI
14067 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14068 (sign_extend:V4DI (match_dup 3)))
14069 (parallel [(const_int 2)]))
14070 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
14071 (sign_extend:V4DI (match_dup 3)))
14072 (parallel [(const_int 3)]))))))]
14073 "TARGET_SHMEDIA"
14074 "mmulsum.wq %2, %3, %0"
14075 [(set_attr "type" "mac_media")])
14076
14077 (define_expand "mperm_w"
14078 [(match_operand:V4HI 0 "arith_reg_dest" "=r")
14079 (match_operand:V4HI 1 "arith_reg_operand" "r")
14080 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
14081 "TARGET_SHMEDIA"
14082 {
14083 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
14084 (operands[0], operands[1], operands[2]));
14085 DONE;
14086 })
14087
14088 ; This use of vec_select isn't exactly correct according to rtl.texi
14089 ; (because not constant), but it seems a straightforward extension.
14090 (define_insn "mperm_w_little"
14091 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14092 (vec_select:V4HI
14093 (match_operand:V4HI 1 "arith_reg_operand" "r")
14094 (parallel
14095 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
14096 (const_int 2) (const_int 0))
14097 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
14098 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
14099 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
14100 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
14101 "mperm.w %1, %N2, %0"
14102 [(set_attr "type" "arith_media")])
14103
14104 (define_insn "mperm_w_big"
14105 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14106 (vec_select:V4HI
14107 (match_operand:V4HI 1 "arith_reg_operand" "r")
14108 (parallel
14109 [(zero_extract:QI (not:QI (match_operand:QI 2
14110 "extend_reg_or_0_operand" "rZ"))
14111 (const_int 2) (const_int 0))
14112 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
14113 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
14114 (zero_extract:QI (not:QI (match_dup 2))
14115 (const_int 2) (const_int 6))])))]
14116 "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
14117 "mperm.w %1, %N2, %0"
14118 [(set_attr "type" "arith_media")])
14119
14120 (define_insn "mperm_w0"
14121 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14122 (vec_duplicate:V4HI (truncate:HI (match_operand 1
14123 "trunc_hi_operand" "r"))))]
14124 "TARGET_SHMEDIA"
14125 "mperm.w %1, r63, %0"
14126 [(set_attr "type" "arith_media")
14127 (set_attr "highpart" "ignore")])
14128
14129 (define_expand "msad_ubq"
14130 [(match_operand:DI 0 "arith_reg_dest" "")
14131 (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
14132 (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
14133 (match_operand:DI 3 "arith_reg_operand" "")]
14134 "TARGET_SHMEDIA"
14135 {
14136 emit_insn (gen_msad_ubq_i (operands[0], operands[3],
14137 operands[1], operands[2]));
14138 DONE;
14139 })
14140
14141 (define_insn "msad_ubq_i"
14142 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14143 (plus:DI
14144 (plus:DI
14145 (plus:DI
14146 (plus:DI
14147 (match_operand:DI 1 "arith_reg_operand" "0")
14148 (abs:DI (vec_select:DI
14149 (minus:V8DI
14150 (zero_extend:V8DI
14151 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14152 (zero_extend:V8DI
14153 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
14154 (parallel [(const_int 0)]))))
14155 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14156 (zero_extend:V8DI (match_dup 3)))
14157 (parallel [(const_int 1)]))))
14158 (plus:DI
14159 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14160 (zero_extend:V8DI (match_dup 3)))
14161 (parallel [(const_int 2)])))
14162 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14163 (zero_extend:V8DI (match_dup 3)))
14164 (parallel [(const_int 3)])))))
14165 (plus:DI
14166 (plus:DI
14167 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14168 (zero_extend:V8DI (match_dup 3)))
14169 (parallel [(const_int 4)])))
14170 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14171 (zero_extend:V8DI (match_dup 3)))
14172 (parallel [(const_int 5)]))))
14173 (plus:DI
14174 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14175 (zero_extend:V8DI (match_dup 3)))
14176 (parallel [(const_int 6)])))
14177 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
14178 (zero_extend:V8DI (match_dup 3)))
14179 (parallel [(const_int 7)])))))))]
14180 "TARGET_SHMEDIA"
14181 "msad.ubq %N2, %N3, %0"
14182 [(set_attr "type" "mac_media")])
14183
14184 (define_insn "mshalds_l"
14185 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14186 (ss_truncate:V2SI
14187 (ashift:V2DI
14188 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
14189 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14190 (const_int 31)))))]
14191 "TARGET_SHMEDIA"
14192 "mshalds.l %1, %2, %0"
14193 [(set_attr "type" "mcmp_media")
14194 (set_attr "highpart" "depend")])
14195
14196 (define_insn "mshalds_w"
14197 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14198 (ss_truncate:V4HI
14199 (ashift:V4SI
14200 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
14201 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
14202 (const_int 15)))))]
14203 "TARGET_SHMEDIA"
14204 "mshalds.w %1, %2, %0"
14205 [(set_attr "type" "mcmp_media")
14206 (set_attr "highpart" "depend")])
14207
14208 (define_insn "ashrv2si3"
14209 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14210 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14211 (match_operand:DI 2 "arith_reg_operand" "r")))]
14212 "TARGET_SHMEDIA"
14213 "mshard.l %1, %2, %0"
14214 [(set_attr "type" "arith_media")
14215 (set_attr "highpart" "depend")])
14216
14217 (define_insn "ashrv4hi3"
14218 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14219 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14220 (match_operand:DI 2 "arith_reg_operand" "r")))]
14221 "TARGET_SHMEDIA"
14222 "mshard.w %1, %2, %0"
14223 [(set_attr "type" "arith_media")
14224 (set_attr "highpart" "depend")])
14225
14226 (define_insn "mshards_q"
14227 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
14228 (ss_truncate:HI
14229 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
14230 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
14231 "TARGET_SHMEDIA"
14232 "mshards.q %1, %N2, %0"
14233 [(set_attr "type" "mcmp_media")])
14234
14235 (define_expand "mshfhi_b"
14236 [(match_operand:V8QI 0 "arith_reg_dest" "")
14237 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14238 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14239 "TARGET_SHMEDIA"
14240 {
14241 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
14242 (operands[0], operands[1], operands[2]));
14243 DONE;
14244 })
14245
14246 (define_expand "mshflo_b"
14247 [(match_operand:V8QI 0 "arith_reg_dest" "")
14248 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14249 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
14250 "TARGET_SHMEDIA"
14251 {
14252 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
14253 (operands[0], operands[1], operands[2]));
14254 DONE;
14255 })
14256
14257 (define_insn "mshf4_b"
14258 [(set
14259 (match_operand:V8QI 0 "arith_reg_dest" "=r")
14260 (vec_select:V8QI
14261 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14262 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14263 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
14264 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
14265 "TARGET_SHMEDIA"
14266 {
14267 return (TARGET_LITTLE_ENDIAN
14268 ? "mshfhi.b %N1, %N2, %0"
14269 : "mshflo.b %N1, %N2, %0");
14270 }
14271 [(set_attr "type" "arith_media")
14272 (set (attr "highpart")
14273 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14274 (const_string "user")))])
14275
14276 (define_insn "mshf0_b"
14277 [(set
14278 (match_operand:V8QI 0 "arith_reg_dest" "=r")
14279 (vec_select:V8QI
14280 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14281 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
14282 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
14283 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
14284 "TARGET_SHMEDIA"
14285 {
14286 return (TARGET_LITTLE_ENDIAN
14287 ? "mshflo.b %N1, %N2, %0"
14288 : "mshfhi.b %N1, %N2, %0");
14289 }
14290 [(set_attr "type" "arith_media")
14291 (set (attr "highpart")
14292 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14293 (const_string "user")))])
14294
14295 (define_expand "mshfhi_l"
14296 [(match_operand:V2SI 0 "arith_reg_dest" "")
14297 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14298 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14299 "TARGET_SHMEDIA"
14300 {
14301 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
14302 (operands[0], operands[1], operands[2]));
14303 DONE;
14304 })
14305
14306 (define_expand "mshflo_l"
14307 [(match_operand:V2SI 0 "arith_reg_dest" "")
14308 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14309 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
14310 "TARGET_SHMEDIA"
14311 {
14312 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
14313 (operands[0], operands[1], operands[2]));
14314 DONE;
14315 })
14316
14317 (define_insn "mshf4_l"
14318 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14319 (vec_select:V2SI
14320 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14321 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14322 (parallel [(const_int 1) (const_int 3)])))]
14323 "TARGET_SHMEDIA"
14324 {
14325 return (TARGET_LITTLE_ENDIAN
14326 ? "mshfhi.l %N1, %N2, %0"
14327 : "mshflo.l %N1, %N2, %0");
14328 }
14329 [(set_attr "type" "arith_media")
14330 (set (attr "highpart")
14331 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14332 (const_string "user")))])
14333
14334 (define_insn "mshf0_l"
14335 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14336 (vec_select:V2SI
14337 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14338 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
14339 (parallel [(const_int 0) (const_int 2)])))]
14340 "TARGET_SHMEDIA"
14341 {
14342 return (TARGET_LITTLE_ENDIAN
14343 ? "mshflo.l %N1, %N2, %0"
14344 : "mshfhi.l %N1, %N2, %0");
14345 }
14346 [(set_attr "type" "arith_media")
14347 (set (attr "highpart")
14348 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14349 (const_string "user")))])
14350
14351 (define_expand "mshfhi_w"
14352 [(match_operand:V4HI 0 "arith_reg_dest" "")
14353 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14354 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14355 "TARGET_SHMEDIA"
14356 {
14357 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
14358 (operands[0], operands[1], operands[2]));
14359 DONE;
14360 })
14361
14362 (define_expand "mshflo_w"
14363 [(match_operand:V4HI 0 "arith_reg_dest" "")
14364 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14365 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
14366 "TARGET_SHMEDIA"
14367 {
14368 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
14369 (operands[0], operands[1], operands[2]));
14370 DONE;
14371 })
14372
14373 (define_insn "mshf4_w"
14374 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14375 (vec_select:V4HI
14376 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14377 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14378 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
14379 "TARGET_SHMEDIA"
14380 {
14381 return (TARGET_LITTLE_ENDIAN
14382 ? "mshfhi.w %N1, %N2, %0"
14383 : "mshflo.w %N1, %N2, %0");
14384 }
14385 [(set_attr "type" "arith_media")
14386 (set (attr "highpart")
14387 (cond [(eq_attr "endian" "big") (const_string "ignore")]
14388 (const_string "user")))])
14389
14390 (define_insn "mshf0_w"
14391 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14392 (vec_select:V4HI
14393 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14394 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
14395 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
14396 "TARGET_SHMEDIA"
14397 {
14398 return (TARGET_LITTLE_ENDIAN
14399 ? "mshflo.w %N1, %N2, %0"
14400 : "mshfhi.w %N1, %N2, %0");
14401 }
14402 [(set_attr "type" "arith_media")
14403 (set (attr "highpart")
14404 (cond [(eq_attr "endian" "little") (const_string "ignore")]
14405 (const_string "user")))])
14406
14407 (define_insn "mshflo_w_x"
14408 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14409 (vec_select:V4HI
14410 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
14411 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
14412 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
14413 "TARGET_SHMEDIA"
14414 "mshflo.w %N1, %N2, %0"
14415 [(set_attr "type" "arith_media")
14416 (set_attr "highpart" "ignore")])
14417
14418 ;; These are useful to expand ANDs and as combiner patterns.
14419 (define_insn_and_split "mshfhi_l_di"
14420 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
14421 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
14422 (const_int 32))
14423 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
14424 (const_int -4294967296))))]
14425 "TARGET_SHMEDIA"
14426 "@
14427 mshfhi.l %N1, %N2, %0
14428 #"
14429 "TARGET_SHMEDIA && reload_completed
14430 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14431 [(set (match_dup 3) (match_dup 4))
14432 (set (match_dup 5) (match_dup 6))]
14433 {
14434 operands[3] = gen_lowpart (SImode, operands[0]);
14435 operands[4] = gen_highpart (SImode, operands[1]);
14436 operands[5] = gen_highpart (SImode, operands[0]);
14437 operands[6] = gen_highpart (SImode, operands[2]);
14438 }
14439 [(set_attr "type" "arith_media")])
14440
14441 (define_insn "*mshfhi_l_di_rev"
14442 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14443 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14444 (const_int -4294967296))
14445 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14446 (const_int 32))))]
14447 "TARGET_SHMEDIA"
14448 "mshfhi.l %N2, %N1, %0"
14449 [(set_attr "type" "arith_media")])
14450
14451 (define_split
14452 [(set (match_operand:DI 0 "arith_reg_dest" "")
14453 (ior:DI (zero_extend:DI (match_operand:SI 1
14454 "extend_reg_or_0_operand" ""))
14455 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
14456 (const_int -4294967296))))
14457 (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
14458 "TARGET_SHMEDIA"
14459 [(const_int 0)]
14460 {
14461 emit_insn (gen_ashldi3_media (operands[3],
14462 simplify_gen_subreg (DImode, operands[1],
14463 SImode, 0),
14464 GEN_INT (32)));
14465 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
14466 DONE;
14467 })
14468
14469 (define_insn "mshflo_l_di"
14470 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14471 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14472 (const_int 4294967295))
14473 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14474 (const_int 32))))]
14475
14476 "TARGET_SHMEDIA"
14477 "mshflo.l %N1, %N2, %0"
14478 [(set_attr "type" "arith_media")
14479 (set_attr "highpart" "ignore")])
14480
14481 (define_insn "*mshflo_l_di_rev"
14482 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14483 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14484 (const_int 32))
14485 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14486 (const_int 4294967295))))]
14487
14488 "TARGET_SHMEDIA"
14489 "mshflo.l %N2, %N1, %0"
14490 [(set_attr "type" "arith_media")
14491 (set_attr "highpart" "ignore")])
14492
14493 ;; Combiner pattern for trampoline initialization.
14494 (define_insn_and_split "*double_shori"
14495 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14496 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
14497 (const_int 32))
14498 (match_operand:DI 2 "const_int_operand" "n")))]
14499 "TARGET_SHMEDIA
14500 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
14501 "#"
14502 "rtx_equal_p (operands[0], operands[1])"
14503 [(const_int 0)]
14504 {
14505 HOST_WIDE_INT v = INTVAL (operands[2]);
14506
14507 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
14508 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
14509 DONE;
14510 }
14511 [(set_attr "highpart" "ignore")])
14512
14513
14514 (define_insn "*mshflo_l_di_x"
14515 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14516 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
14517 "rZ"))
14518 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
14519 (const_int 32))))]
14520
14521 "TARGET_SHMEDIA"
14522 "mshflo.l %N1, %N2, %0"
14523 [(set_attr "type" "arith_media")
14524 (set_attr "highpart" "ignore")])
14525
14526 (define_insn_and_split "concat_v2sf"
14527 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
14528 ;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
14529 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
14530 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
14531
14532 "TARGET_SHMEDIA"
14533 "@
14534 mshflo.l %N1, %N2, %0
14535 #
14536 #"
14537 "TARGET_SHMEDIA && reload_completed
14538 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
14539 [(set (match_dup 3) (match_dup 1))
14540 (set (match_dup 4) (match_dup 2))]
14541 {
14542 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
14543 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
14544 }
14545 [(set_attr "type" "arith_media")
14546 (set_attr "highpart" "ignore")])
14547
14548 (define_insn "*mshflo_l_di_x_rev"
14549 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14550 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
14551 (const_int 32))
14552 (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
14553
14554 "TARGET_SHMEDIA"
14555 "mshflo.l %N2, %N1, %0"
14556 [(set_attr "type" "arith_media")
14557 (set_attr "highpart" "ignore")])
14558
14559 (define_insn "ashlv2si3"
14560 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14561 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14562 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14563 "TARGET_SHMEDIA"
14564 "mshlld.l %1, %2, %0"
14565 [(set_attr "type" "arith_media")
14566 (set_attr "highpart" "depend")])
14567
14568 (define_split
14569 [(set (match_operand 0 "any_register_operand" "")
14570 (match_operator 3 "shift_operator"
14571 [(match_operand 1 "any_register_operand" "")
14572 (match_operand 2 "shift_count_reg_operand" "")]))]
14573 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
14574 [(set (match_dup 0) (match_dup 3))]
14575 {
14576 rtx count = operands[2];
14577 enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
14578
14579 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
14580 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
14581 || GET_CODE (count) == TRUNCATE)
14582 count = XEXP (count, 0);
14583 inner_mode = GET_MODE (count);
14584 count = simplify_gen_subreg (outer_mode, count, inner_mode,
14585 subreg_lowpart_offset (outer_mode, inner_mode));
14586 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
14587 operands[1], count);
14588 })
14589
14590 (define_insn "ashlv4hi3"
14591 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14592 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14593 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14594 "TARGET_SHMEDIA"
14595 "mshlld.w %1, %2, %0"
14596 [(set_attr "type" "arith_media")
14597 (set_attr "highpart" "depend")])
14598
14599 (define_insn "lshrv2si3"
14600 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14601 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
14602 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14603 "TARGET_SHMEDIA"
14604 "mshlrd.l %1, %2, %0"
14605 [(set_attr "type" "arith_media")
14606 (set_attr "highpart" "depend")])
14607
14608 (define_insn "lshrv4hi3"
14609 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14610 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
14611 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
14612 "TARGET_SHMEDIA"
14613 "mshlrd.w %1, %2, %0"
14614 [(set_attr "type" "arith_media")
14615 (set_attr "highpart" "depend")])
14616
14617 (define_insn "subv2si3"
14618 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14619 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14620 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14621 "TARGET_SHMEDIA"
14622 "msub.l %N1, %2, %0"
14623 [(set_attr "type" "arith_media")
14624 (set_attr "highpart" "depend")])
14625
14626 (define_insn "subv4hi3"
14627 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14628 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14629 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14630 "TARGET_SHMEDIA"
14631 "msub.w %N1, %2, %0"
14632 [(set_attr "type" "arith_media")
14633 (set_attr "highpart" "depend")])
14634
14635 (define_insn_and_split "subv2hi3"
14636 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
14637 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
14638 (match_operand:V2HI 2 "arith_reg_operand" "r")))]
14639 "TARGET_SHMEDIA"
14640 "#"
14641 "TARGET_SHMEDIA"
14642 [(const_int 0)]
14643 {
14644 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
14645 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
14646 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
14647 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
14648 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
14649
14650 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
14651 emit_insn (gen_truncdisi2 (si_dst, di_dst));
14652 DONE;
14653 }
14654 [(set_attr "highpart" "must_split")])
14655
14656 (define_insn "sssubv2si3"
14657 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
14658 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
14659 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
14660 "TARGET_SHMEDIA"
14661 "msubs.l %N1, %2, %0"
14662 [(set_attr "type" "mcmp_media")
14663 (set_attr "highpart" "depend")])
14664
14665 (define_insn "ussubv8qi3"
14666 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
14667 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
14668 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
14669 "TARGET_SHMEDIA"
14670 "msubs.ub %N1, %2, %0"
14671 [(set_attr "type" "mcmp_media")
14672 (set_attr "highpart" "depend")])
14673
14674 (define_insn "sssubv4hi3"
14675 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
14676 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
14677 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
14678 "TARGET_SHMEDIA"
14679 "msubs.w %N1, %2, %0"
14680 [(set_attr "type" "mcmp_media")
14681 (set_attr "highpart" "depend")])
14682
14683 ;; Floating Point Intrinsics
14684
14685 (define_insn "fcosa_s"
14686 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14687 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
14688 UNSPEC_FCOSA))]
14689 "TARGET_SHMEDIA"
14690 "fcosa.s %1, %0"
14691 [(set_attr "type" "atrans_media")])
14692
14693 (define_insn "fsina_s"
14694 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14695 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
14696 UNSPEC_FSINA))]
14697 "TARGET_SHMEDIA"
14698 "fsina.s %1, %0"
14699 [(set_attr "type" "atrans_media")])
14700
14701 (define_insn "fipr"
14702 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14703 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
14704 "fp_arith_reg_operand" "f")
14705 (match_operand:V4SF 2
14706 "fp_arith_reg_operand" "f"))
14707 (parallel [(const_int 0)]))
14708 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
14709 (parallel [(const_int 1)])))
14710 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
14711 (parallel [(const_int 2)]))
14712 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
14713 (parallel [(const_int 3)])))))]
14714 "TARGET_SHMEDIA"
14715 "fipr.s %1, %2, %0"
14716 [(set_attr "type" "fparith_media")])
14717
14718 (define_insn "fsrra_s"
14719 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
14720 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
14721 UNSPEC_FSRRA))]
14722 "TARGET_SHMEDIA"
14723 "fsrra.s %1, %0"
14724 [(set_attr "type" "atrans_media")])
14725
14726 (define_insn "ftrv"
14727 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
14728 (plus:V4SF
14729 (plus:V4SF
14730 (mult:V4SF
14731 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
14732 (parallel [(const_int 0) (const_int 5)
14733 (const_int 10) (const_int 15)]))
14734 (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
14735 (mult:V4SF
14736 (vec_select:V4SF (match_dup 1)
14737 (parallel [(const_int 4) (const_int 9)
14738 (const_int 14) (const_int 3)]))
14739 (vec_select:V4SF (match_dup 2)
14740 (parallel [(const_int 1) (const_int 2)
14741 (const_int 3) (const_int 0)]))))
14742 (plus:V4SF
14743 (mult:V4SF
14744 (vec_select:V4SF (match_dup 1)
14745 (parallel [(const_int 8) (const_int 13)
14746 (const_int 2) (const_int 7)]))
14747 (vec_select:V4SF (match_dup 2)
14748 (parallel [(const_int 2) (const_int 3)
14749 (const_int 0) (const_int 1)])))
14750 (mult:V4SF
14751 (vec_select:V4SF (match_dup 1)
14752 (parallel [(const_int 12) (const_int 1)
14753 (const_int 6) (const_int 11)]))
14754 (vec_select:V4SF (match_dup 2)
14755 (parallel [(const_int 3) (const_int 0)
14756 (const_int 1) (const_int 2)]))))))]
14757 "TARGET_SHMEDIA"
14758 "ftrv.s %1, %2, %0"
14759 [(set_attr "type" "fparith_media")])
14760
14761 (define_insn "ldhi_l"
14762 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
14763 (zero_extract:SI
14764 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
14765 (const_int 3))
14766 (const_int -3)))
14767 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
14768 (const_int 0)))]
14769 "TARGET_SHMEDIA32"
14770 "ldhi.l %U1, %0"
14771 [(set_attr "type" "load_media")])
14772
14773 (define_insn "ldhi_q"
14774 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14775 (zero_extract:DI
14776 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
14777 (const_int 7))
14778 (const_int -7)))
14779 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
14780 (const_int 0)))]
14781 "TARGET_SHMEDIA32"
14782 "ldhi.q %U1, %0"
14783 [(set_attr "type" "load_media")])
14784
14785 (define_insn_and_split "*ldhi_q_comb0"
14786 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14787 (zero_extract:DI
14788 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
14789 "register_operand" "r")
14790 (match_operand:SI 2
14791 "ua_offset" "I06"))
14792 (const_int 7))
14793 (const_int -7)))
14794 (plus:SI (and:SI (match_dup 1) (const_int 7))
14795 (const_int 1))
14796 (const_int 0)))]
14797 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
14798 "#"
14799 ""
14800 [(pc)]
14801 {
14802 emit_insn (gen_ldhi_q (operands[0],
14803 gen_rtx_PLUS (SImode, operands[1], operands[2])));
14804 DONE;
14805 })
14806
14807 (define_insn_and_split "*ldhi_q_comb1"
14808 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14809 (zero_extract:DI
14810 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1
14811 "register_operand" "r")
14812 (match_operand:SI 2
14813 "ua_offset" "I06"))
14814 (const_int 7))
14815 (const_int -7)))
14816 (plus:SI (and:SI (plus:SI (match_dup 1) (match_operand:SI 3
14817 "ua_offset" "I06"))
14818 (const_int 7))
14819 (const_int 1))
14820 (const_int 0)))]
14821 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
14822 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
14823 "#"
14824 ""
14825 [(pc)]
14826 {
14827 emit_insn (gen_ldhi_q (operands[0],
14828 gen_rtx_PLUS (SImode, operands[1], operands[2])));
14829 DONE;
14830 })
14831
14832 (define_insn "ldlo_l"
14833 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
14834 (zero_extract:SI
14835 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
14836 (const_int -4)))
14837 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
14838 (and:SI (match_dup 1) (const_int 3))))]
14839 "TARGET_SHMEDIA32"
14840 "ldlo.l %U1, %0"
14841 [(set_attr "type" "load_media")])
14842
14843 (define_insn "ldlo_q"
14844 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14845 (zero_extract:DI
14846 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
14847 (const_int -8)))
14848 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
14849 (and:SI (match_dup 1) (const_int 7))))]
14850 "TARGET_SHMEDIA32"
14851 "ldlo.q %U1, %0"
14852 [(set_attr "type" "load_media")])
14853
14854 (define_insn_and_split "*ldlo_q_comb0"
14855 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14856 (zero_extract:DI
14857 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
14858 (match_operand:SI 2 "ua_offset" "I06"))
14859 (const_int -8)))
14860 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
14861 (and:SI (match_dup 1) (const_int 7))))]
14862 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
14863 "#"
14864 ""
14865 [(pc)]
14866 {
14867 emit_insn (gen_ldlo_q (operands[0],
14868 gen_rtx_PLUS (SImode, operands[1], operands[2])));
14869 DONE;
14870 })
14871
14872 (define_insn_and_split "*ldlo_q_comb1"
14873 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
14874 (zero_extract:DI
14875 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
14876 (match_operand:SI 2 "ua_offset" "I06"))
14877 (const_int -8)))
14878 (minus:SI (const_int 8)
14879 (and:SI (plus:SI (match_dup 1)
14880 (match_operand:SI 3 "ua_offset" "I06"))
14881 (const_int 7)))
14882 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
14883 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
14884 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
14885 "#"
14886 ""
14887 [(pc)]
14888 {
14889 emit_insn (gen_ldlo_q (operands[0],
14890 gen_rtx_PLUS (SImode, operands[1], operands[2])));
14891 DONE;
14892 })
14893
14894 (define_insn "sthi_l"
14895 [(set (zero_extract:SI
14896 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
14897 (const_int 3))
14898 (const_int -3)))
14899 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
14900 (const_int 0))
14901 (match_operand:SI 1 "arith_reg_operand" "r"))]
14902 "TARGET_SHMEDIA32"
14903 "sthi.l %U0, %1"
14904 [(set_attr "type" "ustore_media")])
14905
14906 ;; All unaligned stores are considered to be 'narrow' because they typically
14907 ;; operate on less that a quadword, and when they operate on a full quadword,
14908 ;; the vanilla store high / store low sequence will cause a stall if not
14909 ;; scheduled apart.
14910 (define_insn "sthi_q"
14911 [(set (zero_extract:DI
14912 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
14913 (const_int 7))
14914 (const_int -7)))
14915 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
14916 (const_int 0))
14917 (match_operand:DI 1 "arith_reg_operand" "r"))]
14918 "TARGET_SHMEDIA32"
14919 "sthi.q %U0, %1"
14920 [(set_attr "type" "ustore_media")])
14921
14922 (define_insn_and_split "*sthi_q_comb0"
14923 [(set (zero_extract:DI
14924 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
14925 "register_operand" "r")
14926 (match_operand:SI 1 "ua_offset"
14927 "I06"))
14928 (const_int 7))
14929 (const_int -7)))
14930 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
14931 (const_int 0))
14932 (match_operand:DI 2 "arith_reg_operand" "r"))]
14933 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
14934 "#"
14935 ""
14936 [(pc)]
14937 {
14938 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
14939 operands[2]));
14940 DONE;
14941 })
14942
14943 (define_insn_and_split "*sthi_q_comb1"
14944 [(set (zero_extract:DI
14945 (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0
14946 "register_operand" "r")
14947 (match_operand:SI 1 "ua_offset"
14948 "I06"))
14949 (const_int 7))
14950 (const_int -7)))
14951 (plus:SI (and:SI (plus:SI (match_dup 0)
14952 (match_operand:SI 2 "ua_offset" "I06"))
14953 (const_int 7))
14954 (const_int 1))
14955 (const_int 0))
14956 (match_operand:DI 3 "arith_reg_operand" "r"))]
14957 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
14958 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
14959 "#"
14960 ""
14961 [(pc)]
14962 {
14963 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
14964 operands[3]));
14965 DONE;
14966 })
14967
14968 ;; This is highpart user because the address is used as full 64 bit.
14969 (define_insn "stlo_l"
14970 [(set (zero_extract:SI
14971 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
14972 (const_int -4)))
14973 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
14974 (and:SI (match_dup 0) (const_int 3)))
14975 (match_operand:SI 1 "arith_reg_operand" "r"))]
14976 "TARGET_SHMEDIA32"
14977 "stlo.l %U0, %1"
14978 [(set_attr "type" "ustore_media")])
14979
14980 (define_insn "stlo_q"
14981 [(set (zero_extract:DI
14982 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
14983 (const_int -8)))
14984 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
14985 (and:SI (match_dup 0) (const_int 7)))
14986 (match_operand:DI 1 "arith_reg_operand" "r"))]
14987 "TARGET_SHMEDIA32"
14988 "stlo.q %U0, %1"
14989 [(set_attr "type" "ustore_media")])
14990
14991 (define_insn_and_split "*stlo_q_comb0"
14992 [(set (zero_extract:DI
14993 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
14994 (match_operand:SI 1 "ua_offset" "I06"))
14995 (const_int -8)))
14996 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
14997 (and:SI (match_dup 0) (const_int 7)))
14998 (match_operand:DI 2 "arith_reg_operand" "r"))]
14999 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
15000 "#"
15001 ""
15002 [(pc)]
15003 {
15004 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15005 operands[2]));
15006 DONE;
15007 })
15008
15009 (define_insn_and_split "*stlo_q_comb1"
15010 [(set (zero_extract:DI
15011 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
15012 (match_operand:SI 1 "ua_offset" "I06"))
15013 (const_int -8)))
15014 (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0)
15015 (match_operand:SI 2
15016 "ua_offset" "I06"))
15017 (const_int 7)))
15018 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
15019 (match_operand:DI 3 "arith_reg_operand" "r"))]
15020 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
15021 "#"
15022 ""
15023 [(pc)]
15024 {
15025 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
15026 operands[3]));
15027 DONE;
15028 })
15029
15030 (define_insn "ldhi_l64"
15031 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15032 (zero_extract:SI
15033 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15034 (const_int 3))
15035 (const_int -3)))
15036 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
15037 (const_int 0)))]
15038 "TARGET_SHMEDIA64"
15039 "ldhi.l %U1, %0"
15040 [(set_attr "type" "load_media")])
15041
15042 (define_insn "ldhi_q64"
15043 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15044 (zero_extract:DI
15045 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
15046 (const_int 7))
15047 (const_int -7)))
15048 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
15049 (const_int 0)))]
15050 "TARGET_SHMEDIA64"
15051 "ldhi.q %U1, %0"
15052 [(set_attr "type" "load_media")])
15053
15054 (define_insn "ldlo_l64"
15055 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15056 (zero_extract:SI
15057 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15058 (const_int -4)))
15059 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
15060 (and:DI (match_dup 1) (const_int 3))))]
15061 "TARGET_SHMEDIA64"
15062 "ldlo.l %U1, %0"
15063 [(set_attr "type" "load_media")])
15064
15065 (define_insn "ldlo_q64"
15066 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15067 (zero_extract:DI
15068 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
15069 (const_int -8)))
15070 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
15071 (and:DI (match_dup 1) (const_int 7))))]
15072 "TARGET_SHMEDIA64"
15073 "ldlo.q %U1, %0"
15074 [(set_attr "type" "load_media")])
15075
15076 (define_insn "sthi_l64"
15077 [(set (zero_extract:SI
15078 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15079 (const_int 3))
15080 (const_int -3)))
15081 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
15082 (const_int 0))
15083 (match_operand:SI 1 "arith_reg_operand" "r"))]
15084 "TARGET_SHMEDIA64"
15085 "sthi.l %U0, %1"
15086 [(set_attr "type" "ustore_media")])
15087
15088 (define_insn "sthi_q64"
15089 [(set (zero_extract:DI
15090 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
15091 (const_int 7))
15092 (const_int -7)))
15093 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
15094 (const_int 0))
15095 (match_operand:DI 1 "arith_reg_operand" "r"))]
15096 "TARGET_SHMEDIA64"
15097 "sthi.q %U0, %1"
15098 [(set_attr "type" "ustore_media")])
15099
15100 (define_insn "stlo_l64"
15101 [(set (zero_extract:SI
15102 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15103 (const_int -4)))
15104 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
15105 (and:DI (match_dup 0) (const_int 3)))
15106 (match_operand:SI 1 "arith_reg_operand" "r"))]
15107 "TARGET_SHMEDIA64"
15108 "stlo.l %U0, %1"
15109 [(set_attr "type" "ustore_media")])
15110
15111 (define_insn "stlo_q64"
15112 [(set (zero_extract:DI
15113 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
15114 (const_int -8)))
15115 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
15116 (and:DI (match_dup 0) (const_int 7)))
15117 (match_operand:DI 1 "arith_reg_operand" "r"))]
15118 "TARGET_SHMEDIA64"
15119 "stlo.q %U0, %1"
15120 [(set_attr "type" "ustore_media")])
15121
15122 (define_insn "nsb"
15123 [(set (match_operand:QI 0 "arith_reg_dest" "=r")
15124 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15125 UNSPEC_NSB))]
15126 "TARGET_SHMEDIA"
15127 "nsb %1, %0"
15128 [(set_attr "type" "arith_media")])
15129
15130 (define_insn "nsbsi"
15131 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
15132 (zero_extend:SI
15133 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15134 UNSPEC_NSB)))]
15135 "TARGET_SHMEDIA"
15136 "nsb %1, %0"
15137 [(set_attr "type" "arith_media")])
15138
15139 (define_insn "nsbdi"
15140 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15141 (zero_extend:DI
15142 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
15143 UNSPEC_NSB)))]
15144 "TARGET_SHMEDIA"
15145 "nsb %1, %0"
15146 [(set_attr "type" "arith_media")])
15147
15148 (define_expand "ffsdi2"
15149 [(set (match_operand:DI 0 "arith_reg_dest" "")
15150 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
15151 "TARGET_SHMEDIA"
15152 {
15153 rtx scratch = gen_reg_rtx (DImode);
15154 rtx last;
15155
15156 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
15157 emit_insn (gen_xordi3 (scratch, operands[1], scratch));
15158 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
15159 emit_insn (gen_nsbdi (scratch, scratch));
15160 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
15161 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
15162 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
15163 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
15164
15165 DONE;
15166 })
15167
15168 (define_expand "ffssi2"
15169 [(set (match_operand:SI 0 "arith_reg_dest" "")
15170 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
15171 "TARGET_SHMEDIA"
15172 {
15173 rtx scratch = gen_reg_rtx (SImode);
15174 rtx discratch = gen_reg_rtx (DImode);
15175 rtx last;
15176
15177 emit_insn (gen_adddi3 (discratch,
15178 simplify_gen_subreg (DImode, operands[1], SImode, 0),
15179 constm1_rtx));
15180 emit_insn (gen_andcdi3 (discratch,
15181 simplify_gen_subreg (DImode, operands[1], SImode, 0),
15182 discratch));
15183 emit_insn (gen_nsbsi (scratch, discratch));
15184 last = emit_insn (gen_subsi3 (operands[0],
15185 force_reg (SImode, GEN_INT (63)), scratch));
15186 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
15187
15188 DONE;
15189 })
15190
15191 (define_insn "byterev"
15192 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15193 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
15194 (parallel [(const_int 7) (const_int 6) (const_int 5)
15195 (const_int 4) (const_int 3) (const_int 2)
15196 (const_int 1) (const_int 0)])))]
15197 "TARGET_SHMEDIA"
15198 "byterev %1, %0"
15199 [(set_attr "type" "arith_media")])
15200
15201 ;; In user mode, the "pref" instruction will raise a RADDERR exception
15202 ;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable
15203 ;; implementation of __builtin_prefetch for VxWorks RTPs.
15204 (define_expand "prefetch"
15205 [(prefetch (match_operand 0 "address_operand" "")
15206 (match_operand:SI 1 "const_int_operand" "")
15207 (match_operand:SI 2 "const_int_operand" ""))]
15208 "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
15209 && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
15210
15211 (define_insn "*prefetch"
15212 [(prefetch (match_operand:SI 0 "register_operand" "r")
15213 (match_operand:SI 1 "const_int_operand" "n")
15214 (match_operand:SI 2 "const_int_operand" "n"))]
15215 "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
15216 "pref @%0"
15217 [(set_attr "type" "other")])
15218
15219 (define_insn "*prefetch_media"
15220 [(prefetch (match_operand:QI 0 "address_operand" "p")
15221 (match_operand:SI 1 "const_int_operand" "n")
15222 (match_operand:SI 2 "const_int_operand" "n"))]
15223 "TARGET_SHMEDIA"
15224 {
15225 operands[0] = gen_rtx_MEM (QImode, operands[0]);
15226 output_asm_insn ("ld%M0.b %m0,r63", operands);
15227 return "";
15228 }
15229 [(set_attr "type" "other")])
15230
15231 (define_insn "alloco_i"
15232 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
15233 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
15234 "TARGET_SHMEDIA32"
15235 {
15236 rtx xops[2];
15237
15238 if (GET_CODE (operands[0]) == PLUS)
15239 {
15240 xops[0] = XEXP (operands[0], 0);
15241 xops[1] = XEXP (operands[0], 1);
15242 }
15243 else
15244 {
15245 xops[0] = operands[0];
15246 xops[1] = const0_rtx;
15247 }
15248 output_asm_insn ("alloco %0, %1", xops);
15249 return "";
15250 }
15251 [(set_attr "type" "other")])
15252
15253 (define_split
15254 [(set (match_operand 0 "any_register_operand" "")
15255 (match_operand 1 "" ""))]
15256 "TARGET_SHMEDIA && reload_completed"
15257 [(set (match_dup 0) (match_dup 1))]
15258 {
15259 int n_changes = 0;
15260
15261 for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes);
15262 if (!n_changes)
15263 FAIL;
15264 })
15265
15266 ; Stack Protector Patterns
15267
15268 (define_expand "stack_protect_set"
15269 [(set (match_operand 0 "memory_operand" "")
15270 (match_operand 1 "memory_operand" ""))]
15271 ""
15272 {
15273 if (TARGET_SHMEDIA)
15274 {
15275 if (TARGET_SHMEDIA64)
15276 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
15277 else
15278 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
15279 }
15280 else
15281 emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
15282
15283 DONE;
15284 })
15285
15286 (define_insn "stack_protect_set_si"
15287 [(set (match_operand:SI 0 "memory_operand" "=m")
15288 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15289 (set (match_scratch:SI 2 "=&r") (const_int 0))]
15290 "!TARGET_SHMEDIA"
15291 {
15292 return "mov.l %1,%2" "\n"
15293 " mov.l %2,%0" "\n"
15294 " mov #0,%2";
15295 }
15296 [(set_attr "type" "other")
15297 (set_attr "length" "6")])
15298
15299 (define_insn "stack_protect_set_si_media"
15300 [(set (match_operand:SI 0 "memory_operand" "=m")
15301 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15302 (set (match_scratch:SI 2 "=&r") (const_int 0))]
15303 "TARGET_SHMEDIA"
15304 {
15305 return "ld%M1.l %m1,%2" "\n"
15306 " st%M0.l %m0,%2" "\n"
15307 " movi 0,%2";
15308 }
15309 [(set_attr "type" "other")
15310 (set_attr "length" "12")])
15311
15312 (define_insn "stack_protect_set_di_media"
15313 [(set (match_operand:DI 0 "memory_operand" "=m")
15314 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
15315 (set (match_scratch:DI 2 "=&r") (const_int 0))]
15316 "TARGET_SHMEDIA64"
15317 {
15318 return "ld%M1.q %m1,%2" "\n"
15319 " st%M0.q %m0,%2" "\n"
15320 " movi 0,%2";
15321 }
15322 [(set_attr "type" "other")
15323 (set_attr "length" "12")])
15324
15325 (define_expand "stack_protect_test"
15326 [(match_operand 0 "memory_operand" "")
15327 (match_operand 1 "memory_operand" "")
15328 (match_operand 2 "" "")]
15329 ""
15330 {
15331 if (TARGET_SHMEDIA)
15332 {
15333 rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
15334 rtx test;
15335
15336 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
15337 if (TARGET_SHMEDIA64)
15338 {
15339 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
15340 operands[1]));
15341 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
15342 }
15343 else
15344 {
15345 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
15346 operands[1]));
15347 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
15348 }
15349 }
15350 else
15351 {
15352 emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
15353 emit_jump_insn (gen_branch_true (operands[2]));
15354 }
15355
15356 DONE;
15357 })
15358
15359 (define_insn "stack_protect_test_si"
15360 [(set (reg:SI T_REG)
15361 (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
15362 (match_operand:SI 1 "memory_operand" "m")]
15363 UNSPEC_SP_TEST))
15364 (set (match_scratch:SI 2 "=&r") (const_int 0))
15365 (set (match_scratch:SI 3 "=&r") (const_int 0))]
15366 "!TARGET_SHMEDIA"
15367 {
15368 return "mov.l %0,%2" "\n"
15369 " mov.l %1,%3" "\n"
15370 " cmp/eq %2,%3" "\n"
15371 " mov #0,%2" "\n"
15372 " mov #0,%3";
15373 }
15374 [(set_attr "type" "other")
15375 (set_attr "length" "10")])
15376
15377 (define_insn "stack_protect_test_si_media"
15378 [(set (match_operand:SI 0 "register_operand" "=&r")
15379 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
15380 (match_operand:SI 2 "memory_operand" "m")]
15381 UNSPEC_SP_TEST))
15382 (set (match_scratch:SI 3 "=&r") (const_int 0))]
15383 "TARGET_SHMEDIA"
15384 {
15385 return "ld%M1.l %m1,%0" "\n"
15386 " ld%M2.l %m2,%3" "\n"
15387 " cmpeq %0,%3,%0" "\n"
15388 " movi 0,%3";
15389 }
15390 [(set_attr "type" "other")
15391 (set_attr "length" "16")])
15392
15393 (define_insn "stack_protect_test_di_media"
15394 [(set (match_operand:DI 0 "register_operand" "=&r")
15395 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
15396 (match_operand:DI 2 "memory_operand" "m")]
15397 UNSPEC_SP_TEST))
15398 (set (match_scratch:DI 3 "=&r") (const_int 0))]
15399 "TARGET_SHMEDIA64"
15400 {
15401 return "ld%M1.q %m1,%0" "\n"
15402 " ld%M2.q %m2,%3" "\n"
15403 " cmpeq %0,%3,%0" "\n"
15404 " movi 0,%3";
15405 }
15406 [(set_attr "type" "other")
15407 (set_attr "length" "16")])
15408
15409 (include "sync.md")