]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/sh/sh.md
e8d3e518121574b0074e6879789ed5ea2783acca
[thirdparty/gcc.git] / gcc / config / sh / sh.md
1 ;;- Machine description for Renesas / SuperH SH.
2 ;; Copyright (C) 1993-2015 Free Software Foundation, Inc.
3 ;; Contributed by Steve Chamberlain (sac@cygnus.com).
4 ;; Improved by Jim Wilson (wilson@cygnus.com).
5
6 ;; This file is part of GCC.
7
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
11 ;; any later version.
12
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
21
22
23 ;; ??? Should prepend a * to all pattern names which are not used.
24 ;; This will make the compiler smaller, and rebuilds after changes faster.
25
26 ;; ??? Should be enhanced to include support for many more GNU superoptimizer
27 ;; sequences. Especially the sequences for arithmetic right shifts.
28
29 ;; ??? Should check all DImode patterns for consistency and usefulness.
30
31 ;; ??? The MAC.W and MAC.L instructions are not supported. There is no
32 ;; way to generate them.
33
34 ;; BSR is not generated by the compiler proper, but when relaxing, it
35 ;; generates .uses pseudo-ops that allow linker relaxation to create
36 ;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c
37
38 ;; Special constraints for SH machine description:
39 ;;
40 ;; t -- T
41 ;; x -- mac
42 ;; l -- pr
43 ;; z -- r0
44 ;;
45 ;; Special formats used for outputting SH instructions:
46 ;;
47 ;; %. -- print a .s if insn needs delay slot
48 ;; %@ -- print rte/rts if is/isn't an interrupt function
49 ;; %# -- output a nop if there is nothing to put in the delay slot
50 ;; %O -- print a constant without the #
51 ;; %R -- print the lsw reg of a double
52 ;; %S -- print the msw reg of a double
53 ;; %T -- print next word of a double REG or MEM
54 ;;
55 ;; Special predicates:
56 ;;
57 ;; arith_operand -- operand is valid source for arithmetic op
58 ;; arith_reg_operand -- operand is valid register for arithmetic op
59 ;; general_movdst_operand -- operand is valid move destination
60 ;; general_movsrc_operand -- operand is valid move source
61 ;; logical_operand -- operand is valid source for logical op
62
63 ;; -------------------------------------------------------------------------
64 ;; Constants
65 ;; -------------------------------------------------------------------------
66
67 (define_constants [
68 (AP_REG 145)
69 (PR_REG 146)
70 (T_REG 147)
71 (GBR_REG 144)
72 (MACH_REG 148)
73 (MACL_REG 149)
74 (FPUL_REG 150)
75 (RAP_REG 152)
76
77 (FPSCR_REG 151)
78
79 ;; Virtual FPSCR - bits that are used by FP ops.
80 (FPSCR_MODES_REG 154)
81
82 ;; Virtual FPSCR - bits that are updated by FP ops.
83 (FPSCR_STAT_REG 155)
84
85 (PIC_REG 12)
86 (FP_REG 14)
87 (SP_REG 15)
88
89 (PR_MEDIA_REG 18)
90 (T_MEDIA_REG 19)
91
92 (R0_REG 0)
93 (R1_REG 1)
94 (R2_REG 2)
95 (R3_REG 3)
96 (R4_REG 4)
97 (R5_REG 5)
98 (R6_REG 6)
99 (R7_REG 7)
100 (R8_REG 8)
101 (R9_REG 9)
102 (R10_REG 10)
103 (R20_REG 20)
104 (R21_REG 21)
105 (R22_REG 22)
106 (R23_REG 23)
107
108 (DR0_REG 64)
109 (DR2_REG 66)
110 (DR4_REG 68)
111 (FR23_REG 87)
112
113 (TR0_REG 128)
114 (TR1_REG 129)
115 (TR2_REG 130)
116
117 (XD0_REG 136)
118
119 (FPSCR_PR 524288) ;; 1 << 19
120 (FPSCR_SZ 1048576) ;; 1 << 20
121 (FPSCR_FR 2097152) ;; 1 << 21
122 ])
123
124 (define_c_enum "unspec" [
125 ;; These are used with unspec.
126 UNSPEC_COMPACT_ARGS
127 UNSPEC_MOVA
128 UNSPEC_CASESI
129 UNSPEC_DATALABEL
130 UNSPEC_BBR
131 UNSPEC_SFUNC
132 UNSPEC_PIC
133 UNSPEC_GOT
134 UNSPEC_GOTOFF
135 UNSPEC_PLT
136 UNSPEC_CALLER
137 UNSPEC_GOTPLT
138 UNSPEC_PCREL
139 UNSPEC_ICACHE
140 UNSPEC_INIT_TRAMP
141 UNSPEC_FCOSA
142 UNSPEC_FSRRA
143 UNSPEC_FSINA
144 UNSPEC_NSB
145 UNSPEC_ALLOCO
146 UNSPEC_TLSGD
147 UNSPEC_TLSLDM
148 UNSPEC_TLSIE
149 UNSPEC_DTPOFF
150 UNSPEC_GOTTPOFF
151 UNSPEC_TPOFF
152 UNSPEC_RA
153 UNSPEC_DIV_INV_M0
154 UNSPEC_DIV_INV_M1
155 UNSPEC_DIV_INV_M2
156 UNSPEC_DIV_INV_M3
157 UNSPEC_DIV_INV20
158 UNSPEC_DIV_INV_TABLE
159 UNSPEC_ASHIFTRT
160 UNSPEC_THUNK
161 UNSPEC_CHKADD
162 UNSPEC_SP_SET
163 UNSPEC_SP_TEST
164 UNSPEC_MOVUA
165 ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
166 ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
167 UNSPEC_EXTRACT_S16
168 UNSPEC_EXTRACT_U16
169 ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
170 UNSPEC_SYMOFF
171 ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
172 UNSPEC_PCREL_SYMOFF
173 ;; Misc builtins
174 UNSPEC_BUILTIN_STRLEN
175 ])
176
177 (define_c_enum "unspecv" [
178 ;; These are used with unspec_volatile.
179 UNSPECV_BLOCKAGE
180 UNSPECV_ALIGN
181 UNSPECV_CONST2
182 UNSPECV_CONST4
183 UNSPECV_CONST8
184 UNSPECV_WINDOW_END
185 UNSPECV_CONST_END
186 UNSPECV_EH_RETURN
187 UNSPECV_GBR
188 UNSPECV_SP_SWITCH_B
189 UNSPECV_SP_SWITCH_E
190
191 UNSPECV_FPSCR_MODES
192 UNSPECV_FPSCR_STAT
193 ])
194
195 ;; -------------------------------------------------------------------------
196 ;; Attributes
197 ;; -------------------------------------------------------------------------
198
199 ;; Target CPU.
200
201 (define_attr "cpu"
202 "sh1,sh2,sh2e,sh2a,sh3,sh3e,sh4,sh4a,sh5"
203 (const (symbol_ref "sh_cpu_attr")))
204
205 (define_attr "endian" "big,little"
206 (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
207 (const_string "little") (const_string "big"))))
208
209 ;; Indicate if the default fpu mode is single precision.
210 (define_attr "fpu_single" "yes,no"
211 (const (if_then_else (symbol_ref "TARGET_FPU_SINGLE")
212 (const_string "yes") (const_string "no"))))
213
214 (define_attr "fmovd" "yes,no"
215 (const (if_then_else (symbol_ref "TARGET_FMOVD")
216 (const_string "yes") (const_string "no"))))
217 ;; pipeline model
218 (define_attr "pipe_model" "sh1,sh4,sh5media"
219 (const
220 (cond [(symbol_ref "TARGET_SHMEDIA") (const_string "sh5media")
221 (symbol_ref "TARGET_SUPERSCALAR") (const_string "sh4")]
222 (const_string "sh1"))))
223
224 ;; cbranch conditional branch instructions
225 ;; jump unconditional jumps
226 ;; arith ordinary arithmetic
227 ;; arith3 a compound insn that behaves similarly to a sequence of
228 ;; three insns of type arith
229 ;; arith3b like above, but might end with a redirected branch
230 ;; load from memory
231 ;; load_si Likewise, SImode variant for general register.
232 ;; fload Likewise, but load to fp register.
233 ;; store to memory
234 ;; fstore floating point register to memory
235 ;; move general purpose register to register
236 ;; movi8 8-bit immediate to general purpose register
237 ;; mt_group other sh4 mt instructions
238 ;; fmove register to register, floating point
239 ;; smpy word precision integer multiply
240 ;; dmpy longword or doublelongword precision integer multiply
241 ;; return rts
242 ;; pload load of pr reg, which can't be put into delay slot of rts
243 ;; prset copy register to pr reg, ditto
244 ;; pstore store of pr reg, which can't be put into delay slot of jsr
245 ;; prget copy pr to register, ditto
246 ;; pcload pc relative load of constant value
247 ;; pcfload Likewise, but load to fp register.
248 ;; pcload_si Likewise, SImode variant for general register.
249 ;; rte return from exception
250 ;; sfunc special function call with known used registers
251 ;; call function call
252 ;; fp floating point
253 ;; fpscr_toggle toggle a bit in the fpscr
254 ;; fdiv floating point divide (or square root)
255 ;; gp_fpul move from general purpose register to fpul
256 ;; fpul_gp move from fpul to general purpose register
257 ;; mac_gp move from mac[lh] to general purpose register
258 ;; gp_mac move from general purpose register to mac[lh]
259 ;; mac_mem move from mac[lh] to memory
260 ;; mem_mac move from memory to mac[lh]
261 ;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
262 ;; ftrc_s fix_truncsfsi2_i4
263 ;; dfdiv double precision floating point divide (or square root)
264 ;; cwb ic_invalidate_line_i
265 ;; movua SH4a unaligned load
266 ;; fsrra square root reciprocal approximate
267 ;; fsca sine and cosine approximate
268 ;; tls_load load TLS related address
269 ;; arith_media SHmedia arithmetic, logical, and shift instructions
270 ;; cbranch_media SHmedia conditional branch instructions
271 ;; cmp_media SHmedia compare instructions
272 ;; dfdiv_media SHmedia double precision divide and square root
273 ;; dfmul_media SHmedia double precision multiply instruction
274 ;; dfparith_media SHmedia double precision floating point arithmetic
275 ;; dfpconv_media SHmedia double precision floating point conversions
276 ;; dmpy_media SHmedia longword multiply
277 ;; fcmp_media SHmedia floating point compare instructions
278 ;; fdiv_media SHmedia single precision divide and square root
279 ;; fload_media SHmedia floating point register load instructions
280 ;; fmove_media SHmedia floating point register moves (inc. fabs and fneg)
281 ;; fparith_media SHmedia single precision floating point arithmetic
282 ;; fpconv_media SHmedia single precision floating point conversions
283 ;; fstore_media SHmedia floating point register store instructions
284 ;; gettr_media SHmedia gettr instruction
285 ;; invalidate_line_media SHmedia invalidate_line sequence
286 ;; jump_media SHmedia unconditional branch instructions
287 ;; load_media SHmedia general register load instructions
288 ;; pt_media SHmedia pt instruction (expanded by assembler)
289 ;; ptabs_media SHmedia ptabs instruction
290 ;; store_media SHmedia general register store instructions
291 ;; mcmp_media SHmedia multimedia compare, absolute, saturating ops
292 ;; mac_media SHmedia mac-style fixed point operations
293 ;; d2mpy_media SHmedia: two 32-bit integer multiplies
294 ;; atrans_media SHmedia approximate transcendental functions
295 ;; ustore_media SHmedia unaligned stores
296 ;; nil no-op move, will be deleted.
297
298 (define_attr "type"
299 "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,
300 fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,
301 prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,
302 dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,
303 gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,
304 arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,
305 dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,
306 fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,
307 jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,
308 d2mpy_media,atrans_media,ustore_media,nil,other"
309 (const_string "other"))
310
311 ;; We define a new attribute namely "insn_class".We use
312 ;; this for the DFA based pipeline description.
313 ;;
314 ;; mt_group SH4 "mt" group instructions.
315 ;;
316 ;; ex_group SH4 "ex" group instructions.
317 ;;
318 ;; ls_group SH4 "ls" group instructions.
319 ;;
320 (define_attr "insn_class"
321 "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
322 (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
323 (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
324 (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,
325 store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
326 (eq_attr "type" "cbranch,jump") (const_string "br_group")
327 (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
328 (const_string "fe_group")
329 (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,
330 prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,
331 gp_mac,mac_mem,mem_mac") (const_string "co_group")]
332 (const_string "none")))
333
334 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
335 ;; so these do not belong in an insn group, although they are modeled
336 ;; with their own define_insn_reservations.
337
338 ;; Indicate what precision must be selected in fpscr for this insn, if any.
339 (define_attr "fp_mode" "single,double,none" (const_string "none"))
340
341 ;; Indicate if the fpu mode is set by this instruction
342 ;; "unknown" must have the value as "none" in fp_mode, and means
343 ;; that the instruction/abi has left the processor in an unknown
344 ;; state.
345 ;; "none" means that nothing has changed and no mode is set.
346 ;; This attribute is only used for the Renesas ABI.
347 (define_attr "fp_set" "single,double,unknown,none" (const_string "none"))
348
349 ; If a conditional branch destination is within -252..258 bytes away
350 ; from the instruction it can be 2 bytes long. Something in the
351 ; range -4090..4100 bytes can be 6 bytes long. All other conditional
352 ; branches are initially assumed to be 16 bytes long.
353 ; In machine_dependent_reorg, we split all branches that are longer than
354 ; 2 bytes.
355
356 ;; The maximum range used for SImode constant pool entries is 1018. A final
357 ;; instruction can add 8 bytes while only being 4 bytes in size, thus we
358 ;; can have a total of 1022 bytes in the pool. Add 4 bytes for a branch
359 ;; instruction around the pool table, 2 bytes of alignment before the table,
360 ;; and 30 bytes of alignment after the table. That gives a maximum total
361 ;; pool size of 1058 bytes.
362 ;; Worst case code/pool content size ratio is 1:2 (using asms).
363 ;; Thus, in the worst case, there is one instruction in front of a maximum
364 ;; sized pool, and then there are 1052 bytes of pool for every 508 bytes of
365 ;; code. For the last n bytes of code, there are 2n + 36 bytes of pool.
366 ;; If we have a forward branch, the initial table will be put after the
367 ;; unconditional branch.
368 ;;
369 ;; ??? We could do much better by keeping track of the actual pcloads within
370 ;; the branch range and in the pcload range in front of the branch range.
371
372 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
373 ;; inside an le.
374 (define_attr "short_cbranch_p" "no,yes"
375 (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
376 (const_string "no")
377 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
378 (const_string "yes")
379 (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
380 (const_string "no")
381 (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
382 (const_string "yes")
383 ] (const_string "no")))
384
385 (define_attr "med_branch_p" "no,yes"
386 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
387 (const_int 1988))
388 (const_string "yes")
389 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
390 (const_string "no")
391 (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
392 (const_int 8186))
393 (const_string "yes")
394 ] (const_string "no")))
395
396 (define_attr "med_cbranch_p" "no,yes"
397 (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
398 (const_int 1986))
399 (const_string "yes")
400 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
401 (const_string "no")
402 (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
403 (const_int 8184))
404 (const_string "yes")
405 ] (const_string "no")))
406
407 (define_attr "braf_branch_p" "no,yes"
408 (cond [(match_test "! TARGET_SH2")
409 (const_string "no")
410 (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
411 (const_int 20660))
412 (const_string "yes")
413 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
414 (const_string "no")
415 (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
416 (const_int 65530))
417 (const_string "yes")
418 ] (const_string "no")))
419
420 (define_attr "braf_cbranch_p" "no,yes"
421 (cond [(match_test "! TARGET_SH2")
422 (const_string "no")
423 (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
424 (const_int 20658))
425 (const_string "yes")
426 (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
427 (const_string "no")
428 (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
429 (const_int 65528))
430 (const_string "yes")
431 ] (const_string "no")))
432
433 ;; An unconditional jump in the range -4092..4098 can be 2 bytes long.
434 ;; For wider ranges, we need a combination of a code and a data part.
435 ;; If we can get a scratch register for a long range jump, the code
436 ;; part can be 4 bytes long; otherwise, it must be 8 bytes long.
437 ;; If the jump is in the range -32764..32770, the data part can be 2 bytes
438 ;; long; otherwise, it must be 6 bytes long.
439
440 ;; All other instructions are two bytes long by default.
441
442 ;; ??? This should use something like *branch_p (minus (match_dup 0) (pc)),
443 ;; but getattrtab doesn't understand this.
444 (define_attr "length" ""
445 (cond [(eq_attr "type" "cbranch")
446 (cond [(eq_attr "short_cbranch_p" "yes")
447 (const_int 2)
448 (eq_attr "med_cbranch_p" "yes")
449 (const_int 6)
450 (eq_attr "braf_cbranch_p" "yes")
451 (const_int 12)
452 ;; ??? using pc is not computed transitively.
453 (ne (match_dup 0) (match_dup 0))
454 (const_int 14)
455 (match_test "flag_pic")
456 (const_int 24)
457 ] (const_int 16))
458 (eq_attr "type" "jump")
459 (cond [(eq_attr "med_branch_p" "yes")
460 (const_int 2)
461 (and (match_test "prev_nonnote_insn (insn)")
462 (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
463 (symbol_ref "INSN"))
464 (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
465 (symbol_ref "code_for_indirect_jump_scratch"))))
466 (cond [(eq_attr "braf_branch_p" "yes")
467 (const_int 6)
468 (not (match_test "flag_pic"))
469 (const_int 10)
470 (match_test "TARGET_SH2")
471 (const_int 10)] (const_int 18))
472 (eq_attr "braf_branch_p" "yes")
473 (const_int 10)
474 ;; ??? using pc is not computed transitively.
475 (ne (match_dup 0) (match_dup 0))
476 (const_int 12)
477 (match_test "flag_pic")
478 (const_int 22)
479 ] (const_int 14))
480 (eq_attr "type" "pt_media")
481 (if_then_else (match_test "TARGET_SHMEDIA64")
482 (const_int 20) (const_int 12))
483 (and (eq_attr "type" "jump_media")
484 (match_test "TARGET_SH5_CUT2_WORKAROUND"))
485 (const_int 8)
486 ] (if_then_else (match_test "TARGET_SHMEDIA")
487 (const_int 4)
488 (const_int 2))))
489
490 ;; DFA descriptions for the pipelines
491
492 (include "sh1.md")
493 (include "shmedia.md")
494 (include "sh4.md")
495
496 (include "iterators.md")
497 (include "predicates.md")
498 (include "constraints.md")
499
500 ;; Definitions for filling delay slots
501
502 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
503
504 (define_attr "banked" "yes,no"
505 (cond [(match_test "sh_loads_bankedreg_p (insn)")
506 (const_string "yes")]
507 (const_string "no")))
508
509 ;; ??? This should be (nil) instead of (const_int 0)
510 (define_attr "hit_stack" "yes,no"
511 (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
512 (const_string "no")]
513 (const_string "yes")))
514
515 (define_attr "interrupt_function" "no,yes"
516 (const (symbol_ref "current_function_interrupt")))
517
518 (define_attr "in_delay_slot" "yes,no"
519 (cond [(eq_attr "type" "cbranch") (const_string "no")
520 (eq_attr "type" "pcload,pcload_si") (const_string "no")
521 (eq_attr "type" "fpscr_toggle") (const_string "no")
522 (eq_attr "needs_delay_slot" "yes") (const_string "no")
523 (eq_attr "length" "2") (const_string "yes")
524 ] (const_string "no")))
525
526 (define_attr "cond_delay_slot" "yes,no"
527 (cond [(eq_attr "in_delay_slot" "yes") (const_string "yes")
528 ] (const_string "no")))
529
530 (define_attr "is_sfunc" ""
531 (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
532
533 (define_attr "is_mac_media" ""
534 (if_then_else (eq_attr "type" "mac_media") (const_int 1) (const_int 0)))
535
536 (define_attr "branch_zero" "yes,no"
537 (cond [(eq_attr "type" "!cbranch") (const_string "no")
538 (ne (symbol_ref "(next_active_insn (insn)\
539 == (prev_active_insn\
540 (XEXP (SET_SRC (PATTERN (insn)), 1))))\
541 && get_attr_length (next_active_insn (insn)) == 2")
542 (const_int 0))
543 (const_string "yes")]
544 (const_string "no")))
545
546 ;; SH4 Double-precision computation with double-precision result -
547 ;; the two halves are ready at different times.
548 (define_attr "dfp_comp" "yes,no"
549 (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
550 (const_string "no")))
551
552 ;; Insns for which the latency of a preceding fp insn is decreased by one.
553 (define_attr "late_fp_use" "yes,no" (const_string "no"))
554 ;; And feeding insns for which this relevant.
555 (define_attr "any_fp_comp" "yes,no"
556 (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
557 (const_string "yes")]
558 (const_string "no")))
559
560 (define_attr "any_int_load" "yes,no"
561 (cond [(eq_attr "type" "load,load_si,pcload,pcload_si")
562 (const_string "yes")]
563 (const_string "no")))
564
565 (define_attr "highpart" "user, ignore, extend, depend, must_split"
566 (const_string "user"))
567
568 (define_delay
569 (eq_attr "needs_delay_slot" "yes")
570 [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
571
572 ;; Since a normal return (rts) implicitly uses the PR register,
573 ;; we can't allow PR register loads in an rts delay slot.
574 ;; On the SH1* and SH2*, the rte instruction reads the return pc from the
575 ;; stack, and thus we can't put a pop instruction in its delay slot.
576 ;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
577 ;; pop instruction can go in the delay slot, unless it references a banked
578 ;; register (the register bank is switched by rte).
579 (define_delay
580 (eq_attr "type" "return")
581 [(and (eq_attr "in_delay_slot" "yes")
582 (ior (and (eq_attr "interrupt_function" "no")
583 (eq_attr "type" "!pload,prset"))
584 (and (eq_attr "interrupt_function" "yes")
585 (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
586 (eq_attr "banked" "no"))))
587 (nil) (nil)])
588
589 ;; Since a call implicitly uses the PR register, we can't allow
590 ;; a PR register store in a jsr delay slot.
591
592 (define_delay
593 (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))
594 [(and (eq_attr "in_delay_slot" "yes")
595 (eq_attr "type" "!pstore,prget")) (nil) (nil)])
596
597 ;; Conditional branches with delay slots are available starting with SH2.
598 (define_delay
599 (and (eq_attr "type" "cbranch") (match_test "TARGET_SH2"))
600 [(eq_attr "cond_delay_slot" "yes") (nil) (nil)])
601 \f
602 ;; -------------------------------------------------------------------------
603 ;; SImode signed integer comparisons
604 ;; -------------------------------------------------------------------------
605
606 ;; Patterns to generate the tst instruction which are usually formed by
607 ;; the combine pass.
608 ;; The canonical form here being used is (eq (and (op) (op)) 0).
609 ;; For some bit patterns, such as contiguous bits, we also must accept
610 ;; zero_extract forms. Single bit tests are also handled via zero_extract
611 ;; patterns in the 'bit field extract patterns' section. All variants
612 ;; are eventually converted to the 'tstsi_t' insn.
613 ;; As long as pseudos can be created (before RA), 'tstsi_t' will also accept
614 ;; constants that won't fit into 8 bits. After having captured the constant
615 ;; we can decide better whether/how to load it into a register and do other
616 ;; post-combine optimizations such as bypassing sign/zero extensions.
617 (define_insn_and_split "tstsi_t"
618 [(set (reg:SI T_REG)
619 (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "%z,r")
620 (match_operand:SI 1 "arith_or_int_operand" "K08,?r"))
621 (const_int 0)))]
622 "TARGET_SH1
623 && (can_create_pseudo_p () || arith_reg_operand (operands[1], SImode)
624 || satisfies_constraint_K08 (operands[1]))"
625 "tst %1,%0"
626 "TARGET_SH1 && can_create_pseudo_p () && CONST_INT_P (operands[1])
627 && !sh_in_recog_treg_set_expr ()"
628 [(const_int 0)]
629 {
630 gcc_assert (CONST_INT_P (operands[1]));
631
632 HOST_WIDE_INT op1val = INTVAL (operands[1]);
633 bool op0_dead_after_this =
634 sh_reg_dead_or_unused_after_insn (curr_insn, REGNO (operands[0]));
635
636 if (optimize)
637 {
638 if (dump_file)
639 fprintf (dump_file,
640 "tstsi_t: trying to optimize const_int 0x%08x\n",
641 (uint32_t)op1val);
642
643 /* See if we can convert a test with a reg and a constant into
644 something simpler, if the reg is known to be zero or sign
645 extended. */
646 sh_extending_set_of_reg eop0 = sh_find_extending_set_of_reg (operands[0],
647 curr_insn);
648 if (eop0.ext_code != UNKNOWN)
649 {
650 /* Adjust the constant, trying to eliminate bits that are not
651 contributing to the result. */
652 if (eop0.from_mode == QImode)
653 op1val = (op1val
654 | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFFFF80)
655 ? 0x80 : 0)) & 0xFF;
656 else if (eop0.from_mode == HImode)
657 op1val = (op1val
658 | (eop0.ext_code == SIGN_EXTEND && (op1val & 0xFFFF8000)
659 ? 0x8000 : 0)) & 0xFFFF;
660
661 if (dump_file)
662 fprintf (dump_file, "tstsi_t: using effective const_int: 0x%08x\n",
663 (uint32_t)op1val);
664
665 /* Try to bypass the sign/zero extension first if op0 dies after
666 this insn. */
667 if (op0_dead_after_this && eop0.can_use_as_unextended_reg ())
668 {
669 if (dump_file)
670 fprintf (dump_file, "tstsi_t: bypassing sign/zero extension\n");
671
672 operands[0] = eop0.use_as_unextended_reg (curr_insn);
673 }
674 else if ((eop0.from_mode == QImode && op1val == 0xFF)
675 || (eop0.from_mode == HImode && op1val == 0xFFFF))
676 {
677 if (dump_file)
678 fprintf (dump_file, "tstsi_t: converting to cmpeqsi_t\n");
679 emit_insn (gen_cmpeqsi_t (eop0.use_as_extended_reg (curr_insn),
680 const0_rtx));
681 DONE;
682 }
683 else if (eop0.ext_code == SIGN_EXTEND
684 && ((eop0.from_mode == QImode && op1val == 0x80)
685 || (eop0.from_mode == HImode && op1val == 0x8000)))
686 {
687 if (dump_file)
688 fprintf (dump_file, "tstsi_t: converting to cmpgesi_t\n");
689 emit_insn (gen_cmpgesi_t (eop0.use_as_extended_reg (curr_insn),
690 const0_rtx));
691 DONE;
692 }
693 else if (!CONST_OK_FOR_K08 (op1val))
694 {
695 if (dump_file)
696 fprintf (dump_file, "tstsi_t: converting const_int to signed "
697 "value\n");
698
699 /* If here we haven't done anything yet. Convert the constant
700 to a signed value to reduce the constant pool size. */
701 operands[0] = eop0.use_as_extended_reg (curr_insn);
702
703 if (eop0.from_mode == QImode)
704 op1val |= (op1val & 0x80) ? 0xFFFFFFFFFFFFFF00LL : 0;
705 else if (eop0.from_mode == HImode)
706 op1val |= (op1val & 0x8000) ? 0xFFFFFFFFFFFF0000LL : 0;
707 }
708 else
709 operands[0] = eop0.use_as_extended_reg (curr_insn);
710 }
711 }
712
713 if (dump_file)
714 fprintf (dump_file, "tstsi_t: using const_int 0x%08x\n",
715 (uint32_t)op1val);
716
717 /* Try to fit the constant into 8 bits by shuffling the value in the
718 register operand.
719 Doing that usually results in smaller code as the constants in the
720 pools are avoided (32 bit constant = load + constant = 6 bytes).
721 However, if the constant load (LS insn) can be hoisted insn dependencies
722 can be avoided and chances for parallel execution increase. The common
723 usage pattern is:
724 - load reg from mem
725 - test bits
726 - conditional branch
727
728 FIXME: For now we do that only when optimizing for size until there is
729 a better heuristic.
730
731 FIXME: If there are multiple tst insns in the block with the same
732 constant, avoid the #imm variant to avoid R0 loads. Use the 'tst Rn,Rm'
733 variant instead and load the constant into a reg. For that we'd need
734 to do some analysis. */
735
736 if (CONST_OK_FOR_K08 (op1val))
737 {
738 /* Do nothing. */
739 }
740 else if ((op1val & 0xFFFF) == 0
741 && CONST_OK_FOR_K08 (op1val >> 16) && optimize_size)
742 {
743 /* Use a swap.w insn to do a shift + reg copy (to R0) in one insn. */
744 op1val = op1val >> 16;
745 rtx r = gen_reg_rtx (SImode);
746 emit_insn (gen_rotlsi3_16 (r, operands[0]));
747 operands[0] = r;
748 }
749 else if ((op1val & 0xFF) == 0
750 && CONST_OK_FOR_K08 (op1val >> 8) && optimize_size)
751 {
752 /* Use a swap.b insn to do a shift + reg copy (to R0) in one insn. */
753 op1val = op1val >> 8;
754 rtx r = gen_reg_rtx (SImode);
755 emit_insn (gen_swapbsi2 (r, operands[0]));
756 operands[0] = r;
757 }
758 else if ((op1val & 3) == 0
759 && CONST_OK_FOR_K08 (op1val >> 2) && optimize_size)
760 {
761 op1val = op1val >> 2;
762 rtx r = gen_reg_rtx (SImode);
763 emit_insn (gen_lshrsi3_k (r, operands[0], GEN_INT (2)));
764 operands[0] = r;
765 }
766 else if ((op1val & 1) == 0
767 && CONST_OK_FOR_K08 (op1val >> 1) && optimize_size)
768 {
769 op1val = op1val >> 1;
770 rtx r = gen_reg_rtx (SImode);
771 emit_insn (gen_shlr (r, operands[0]));
772 operands[0] = r;
773 }
774
775 operands[1] = GEN_INT (op1val);
776
777 if (!satisfies_constraint_K08 (operands[1]))
778 operands[1] = force_reg (SImode, operands[1]);
779
780 emit_insn (gen_tstsi_t (operands[0], operands[1]));
781 DONE;
782 }
783 [(set_attr "type" "mt_group")])
784
785 ;; This pattern is used by combine when testing QI/HImode subregs with a
786 ;; negative constant. Ignore high bits by masking them out in the constant.
787 (define_insn_and_split "*tst<mode>_t"
788 [(set (reg:SI T_REG)
789 (eq:SI (subreg:SI
790 (and:QIHI (match_operand:QIHI 0 "arith_reg_operand")
791 (match_operand 1 "const_int_operand")) 0)
792 (const_int 0)))]
793 "TARGET_SH1 && can_create_pseudo_p ()"
794 "#"
795 "&& 1"
796 [(set (reg:SI T_REG)
797 (eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))]
798 {
799 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
800 operands[1] = GEN_INT (INTVAL (operands[1])
801 & (<MODE>mode == HImode ? 0xFFFF : 0xFF));
802 })
803
804 ;; This pattern might be risky because it also tests the upper bits and not
805 ;; only the subreg. We have to check whether the operands have been sign
806 ;; or zero extended. In the worst case, a zero extension has to be inserted
807 ;; to mask out the unwanted bits.
808 (define_insn_and_split "*tst<mode>_t_subregs"
809 [(set (reg:SI T_REG)
810 (eq:SI
811 (subreg:QIHI
812 (and:SI (match_operand:SI 0 "arith_reg_operand")
813 (match_operand:SI 1 "arith_reg_operand")) <lowpart_le>)
814 (const_int 0)))]
815 "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()"
816 "#"
817 "&& !sh_in_recog_treg_set_expr ()"
818 [(const_int 0)]
819 {
820 sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_le>, operands);
821 DONE;
822 })
823
824 (define_insn_and_split "*tst<mode>_t_subregs"
825 [(set (reg:SI T_REG)
826 (eq:SI
827 (subreg:QIHI
828 (and:SI (match_operand:SI 0 "arith_reg_operand")
829 (match_operand:SI 1 "arith_reg_operand")) <lowpart_be>)
830 (const_int 0)))]
831 "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()"
832 "#"
833 "&& !sh_in_recog_treg_set_expr ()"
834 [(const_int 0)]
835 {
836 sh_split_tst_subregs (curr_insn, <MODE>mode, <lowpart_be>, operands);
837 DONE;
838 })
839
840 ;; Extract contiguous bits and compare them against zero.
841 ;; Notice that this will not be used for single bits. Special single bit
842 ;; extraction patterns are in the 'bit field extract patterns' section.
843 (define_insn_and_split "*tst<mode>_t_zero_extract"
844 [(set (reg:SI T_REG)
845 (eq:SI (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand")
846 (match_operand 1 "const_int_operand")
847 (match_operand 2 "const_int_operand"))
848 (const_int 0)))]
849 "TARGET_SH1 && can_create_pseudo_p ()"
850 "#"
851 "&& 1"
852 [(set (reg:SI T_REG)
853 (eq:SI (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))]
854 {
855 operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
856 if (GET_MODE (operands[0]) != SImode)
857 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
858 })
859
860 ;; Convert '(reg << shift) & mask' into 'reg & (mask >> shift)'.
861 ;; The shifted-out bits in the mask will always be zero, since the
862 ;; shifted-in bits in the reg will also be always zero.
863 (define_insn_and_split "*tstsi_t_shift_mask"
864 [(set (reg:SI T_REG)
865 (eq:SI (and:SI (ashift:SI (match_operand:SI 0 "arith_reg_operand")
866 (match_operand 1 "const_int_operand"))
867 (match_operand 2 "const_int_operand"))
868 (const_int 0)))]
869 "TARGET_SH1 && can_create_pseudo_p ()"
870 "#"
871 "&& 1"
872 [(set (reg:SI T_REG)
873 (eq:SI (and:SI (match_dup 0) (match_dup 2)) (const_int 0)))]
874 {
875 operands[2] = GEN_INT (INTVAL (operands[2]) >> INTVAL (operands[1]));
876 })
877
878 (define_insn "cmpeqsi_t"
879 [(set (reg:SI T_REG)
880 (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
881 (match_operand:SI 1 "arith_operand" "N,rI08,r")))]
882 "TARGET_SH1"
883 "@
884 tst %0,%0
885 cmp/eq %1,%0
886 cmp/eq %1,%0"
887 [(set_attr "type" "mt_group")])
888
889 ;; Sometimes combine fails to form the (eq (and (op) (op)) 0) tst insn.
890 ;; Try to fix that in the split1 pass by looking for the previous set
891 ;; of the tested op. Also see if there is a preceeding sign/zero
892 ;; extension that can be avoided.
893 (define_split
894 [(set (reg:SI T_REG)
895 (eq:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))]
896 "TARGET_SH1 && can_create_pseudo_p () && optimize
897 && !sh_in_recog_treg_set_expr ()"
898 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
899 {
900 if (dump_file)
901 fprintf (dump_file, "cmpeqsi_t: trying to optimize const_int 0\n");
902
903 /* If the tested reg is not dead after this insn, it's probably used by
904 something else after the comparison. It's probably better to leave
905 it as it is. */
906 if (find_regno_note (curr_insn, REG_DEAD, REGNO (operands[0])) == NULL_RTX)
907 FAIL;
908
909 /* FIXME: Maybe also search the predecessor basic blocks to catch
910 more cases. */
911 set_of_reg op = sh_find_set_of_reg (operands[0], curr_insn,
912 prev_nonnote_insn_bb);
913
914 if (op.set_src != NULL && GET_CODE (op.set_src) == AND
915 && !sh_insn_operands_modified_between_p (op.insn, op.insn, curr_insn))
916 {
917 if (dump_file)
918 fprintf (dump_file, "cmpeqsi_t: found preceeding and in insn %d\n",
919 INSN_UID (op.insn));
920
921 if (!(arith_reg_operand (XEXP (op.set_src, 0), SImode)
922 && (arith_reg_operand (XEXP (op.set_src, 1), SImode)
923 || CONST_INT_P (XEXP (op.set_src, 1)))))
924 FAIL;
925
926 /* Assume that the operands of the andsi insn are compatible with the
927 operands of the tstsi_t insn, which is generally the case. */
928 if (dump_file)
929 fprintf (dump_file, "cmpeqsi_t: replacing with tstsi_t\n");
930 emit_insn (gen_tstsi_t (XEXP (op.set_src, 0), XEXP (op.set_src, 1)));
931 DONE;
932 }
933
934 /* Converting HImode into tests against 0xFFFF tends to increase the code
935 size, as it will create constant pool entries. Disable it for now. */
936 const bool enable_himode = false;
937
938 /* FIXME: try to keep the (eq (reg) (const_int 0)). Even if the zero
939 extended reg is used after this insn, if we know that _before_ the zero
940 extension the value was loaded via sign extending mem load, we can just
941 use the value of the mem load directly. */
942 sh_extending_set_of_reg eop = sh_find_extending_set_of_reg (operands[0],
943 curr_insn);
944
945 if (eop.ext_code != UNKNOWN
946 && (eop.from_mode == QImode || (eop.from_mode == HImode && enable_himode))
947 && eop.can_use_as_unextended_reg ()
948 && !reg_used_between_p (operands[0], eop.insn, curr_insn))
949 {
950 /* Bypass the sign/zero extension and test against the bit mask, but
951 only if it's the only use of the sign/zero extracted value.
952 Otherwise we'd be introducing new constants in the pool. */
953 if (dump_file)
954 fprintf (dump_file, "cmpeqsi_t: bypassing sign/zero extension in "
955 "insn %d and using tstsi_t\n", INSN_UID (op.insn));
956
957 emit_insn (gen_tstsi_t (
958 eop.use_as_unextended_reg (curr_insn),
959 GEN_INT (eop.from_mode == QImode ? 0xFF : 0xFFFF)));
960 DONE;
961 }
962
963 if (dump_file)
964 fprintf (dump_file, "cmpeqsi_t: nothing optimized\n");
965 FAIL;
966 })
967
968 ;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
969 ;; pattern by itself. What this actually does is:
970 ;; x == 0: (1 >> 0-0) & 1 = 1
971 ;; x != 0: (1 >> 0-x) & 1 = 0
972 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
973 (define_insn_and_split "*cmpeqsi_t"
974 [(set (reg:SI T_REG)
975 (and:SI (lshiftrt:SI
976 (const_int 1)
977 (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
978 (const_int 1)))]
979 "TARGET_SH1"
980 "#"
981 "&& 1"
982 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
983
984 (define_insn "cmpgtsi_t"
985 [(set (reg:SI T_REG)
986 (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
987 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
988 "TARGET_SH1"
989 "@
990 cmp/pl %0
991 cmp/gt %1,%0"
992 [(set_attr "type" "mt_group")])
993
994 (define_insn "cmpgesi_t"
995 [(set (reg:SI T_REG)
996 (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
997 (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
998 "TARGET_SH1"
999 "@
1000 cmp/pz %0
1001 cmp/ge %1,%0"
1002 [(set_attr "type" "mt_group")])
1003
1004 ;; Recombine a cmp/pz followed by a nott into a shll.
1005 ;; On non-SH2A recombine a cmp/pz followed by a movrt into shll-movt.
1006 ;; On SH2A cmp/pz-movrt is slightly better, as it does not mutate the input.
1007 (define_split
1008 [(set (reg:SI T_REG)
1009 (ge:SI (match_operand:SI 0 "arith_reg_operand") (const_int 0)))]
1010
1011 "TARGET_SH1 && can_create_pseudo_p () && optimize
1012 && !sh_in_recog_treg_set_expr ()"
1013 [(const_int 0)]
1014 {
1015 if (dump_file)
1016 fprintf (dump_file, "cmpgesi_t: trying to optimize for const_int 0\n");
1017
1018 rtx_insn* i = next_nonnote_insn_bb (curr_insn);
1019
1020 if (dump_file)
1021 {
1022 fprintf (dump_file, "cmpgesi_t: following insn is \n");
1023 print_rtl_single (dump_file, i);
1024 fprintf (dump_file, "\n");
1025 }
1026
1027 if (sh_is_nott_insn (i))
1028 {
1029 if (dump_file)
1030 fprintf (dump_file,
1031 "cmpgesi_t: replacing (cmp/pz, nott) with (shll)\n");
1032 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
1033 set_insn_deleted (i);
1034 DONE;
1035 }
1036
1037 /* On non-SH2A negc is used as movrt replacement, which sets T = 1.
1038 Thus we can remove it only if T is marked as dead afterwards. */
1039 if (rtx dest_reg = !TARGET_SH2A
1040 && sh_reg_dead_or_unused_after_insn (i, T_REG)
1041 ? sh_movrt_set_dest (i) : NULL)
1042 {
1043 if (dump_file)
1044 fprintf (dump_file,
1045 "cmpgesi_t: replacing (cmp/pz, movrt) with (shll, movt)\n");
1046 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
1047 add_reg_note (emit_insn (gen_movt (dest_reg, get_t_reg_rtx ())),
1048 REG_DEAD, get_t_reg_rtx ());
1049 set_insn_deleted (i);
1050 DONE;
1051 }
1052
1053 if (dump_file)
1054 fprintf (dump_file, "cmpgesi_t: nothing optimized\n");
1055
1056 FAIL;
1057 })
1058
1059 ;; FIXME: This is actually wrong. There is no way to literally move a
1060 ;; general reg to t reg. Luckily, it seems that this pattern will be only
1061 ;; used when the general reg is known be either '0' or '1' during combine.
1062 ;; What we actually need is reg != 0 -> T, but we have only reg == 0 -> T.
1063 ;; Due to interactions with other patterns, combine fails to pick the latter
1064 ;; and invert the dependent logic.
1065 (define_insn "*negtstsi"
1066 [(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
1067 "TARGET_SH1 && !sh_in_recog_treg_set_expr ()"
1068 "cmp/pl %0"
1069 [(set_attr "type" "mt_group")])
1070
1071 ;; Some integer sign comparison patterns can be realized with the div0s insn.
1072 ;; div0s Rm,Rn T = (Rm >> 31) ^ (Rn >> 31)
1073 ;;
1074 ;; The 'cmp_div0s' pattern is our canonical form, into which all the other
1075 ;; variations are converted. The negative forms will split into a trailing
1076 ;; nott sequence, which will be eliminated either by the
1077 ;; 'any_treg_expr_to_reg' pattern, or by the 'sh_treg_combine' pass.
1078 (define_insn "cmp_div0s"
1079 [(set (reg:SI T_REG)
1080 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand" "%r")
1081 (match_operand:SI 1 "arith_reg_operand" "r"))
1082 (const_int 31)))]
1083 "TARGET_SH1"
1084 "div0s %0,%1"
1085 [(set_attr "type" "arith")])
1086
1087 (define_insn_and_split "*cmp_div0s_1"
1088 [(set (reg:SI T_REG)
1089 (xor:SI (ge:SI (match_operand:SI 0 "arith_reg_operand")
1090 (const_int 0))
1091 (ge:SI (match_operand:SI 1 "arith_reg_operand")
1092 (const_int 0))))]
1093 "TARGET_SH1 && can_create_pseudo_p ()"
1094 "#"
1095 "&& 1"
1096 [(set (reg:SI T_REG)
1097 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))])
1098
1099 (define_insn_and_split "*cmp_div0s_2"
1100 [(set (reg:SI T_REG)
1101 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
1102 (const_int 31))
1103 (ge:SI (match_operand:SI 1 "arith_reg_operand")
1104 (const_int 0))))]
1105 "TARGET_SH1 && can_create_pseudo_p ()"
1106 "#"
1107 "&& 1"
1108 [(set (reg:SI T_REG)
1109 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))])
1110
1111 (define_insn_and_split "*cmp_div0s_3"
1112 [(set (reg:SI T_REG)
1113 (eq:SI (ge:SI (match_operand:SI 0 "arith_reg_operand")
1114 (const_int 0))
1115 (ge:SI (match_operand:SI 1 "arith_reg_operand")
1116 (const_int 0))))]
1117 "TARGET_SH1 && can_create_pseudo_p ()"
1118 "#"
1119 "&& 1"
1120 [(set (reg:SI T_REG)
1121 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1122 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1123
1124 (define_insn_and_split "*cmp_div0s_4"
1125 [(set (reg:SI T_REG)
1126 (ge:SI (xor:SI (match_operand:SI 0 "arith_reg_operand")
1127 (match_operand:SI 1 "arith_reg_operand"))
1128 (const_int 0)))]
1129 "TARGET_SH1 && can_create_pseudo_p ()"
1130 "#"
1131 "&& 1"
1132 [(set (reg:SI T_REG)
1133 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1134 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1135
1136 (define_insn_and_split "*cmp_div0s_5"
1137 [(set (reg:SI T_REG)
1138 (xor:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
1139 (const_int 31))
1140 (ge:SI (match_operand:SI 1 "arith_reg_operand")
1141 (const_int 0))))]
1142 "TARGET_SH1 && can_create_pseudo_p ()"
1143 "#"
1144 "&& 1"
1145 [(set (reg:SI T_REG)
1146 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1147 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1148
1149 (define_insn_and_split "*cmp_div0s_6"
1150 [(set (reg:SI T_REG)
1151 (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
1152 (const_int 31))
1153 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
1154 (const_int 31))))]
1155 "TARGET_SH1 && can_create_pseudo_p ()"
1156 "#"
1157 "&& 1"
1158 [(set (reg:SI T_REG)
1159 (lshiftrt:SI (xor:SI (match_dup 0) (match_dup 1)) (const_int 31)))
1160 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))])
1161
1162 ;; -------------------------------------------------------------------------
1163 ;; SImode compare and branch
1164 ;; -------------------------------------------------------------------------
1165
1166 (define_expand "cbranchsi4"
1167 [(set (pc)
1168 (if_then_else (match_operator 0 "comparison_operator"
1169 [(match_operand:SI 1 "arith_operand" "")
1170 (match_operand:SI 2 "arith_operand" "")])
1171 (label_ref (match_operand 3 "" ""))
1172 (pc)))
1173 (clobber (reg:SI T_REG))]
1174 ""
1175 {
1176 if (TARGET_SHMEDIA)
1177 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1178 operands[2], operands[3]));
1179 else
1180 expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
1181
1182 DONE;
1183 })
1184
1185 ;; Combine patterns to invert compare and branch operations for which we
1186 ;; don't have actual comparison insns. These patterns are used in cases
1187 ;; which appear after the initial cbranchsi expansion, which also does
1188 ;; some condition inversion.
1189 (define_split
1190 [(set (pc)
1191 (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
1192 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1193 (label_ref (match_operand 2))
1194 (pc)))
1195 (clobber (reg:SI T_REG))]
1196 "TARGET_SH1"
1197 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
1198 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1199 (label_ref (match_dup 2))
1200 (pc)))])
1201
1202 ;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
1203 ;; and SH2A combine fails to simplify this pattern by itself.
1204 ;; What this actually does is:
1205 ;; x == 0: (1 >> 0-0) & 1 = 1
1206 ;; x != 0: (1 >> 0-x) & 1 = 0
1207 ;; Without this the test pr51244-8.c fails on SH2A and SH4A.
1208 (define_split
1209 [(set (pc)
1210 (if_then_else
1211 (eq (and:SI (lshiftrt:SI
1212 (const_int 1)
1213 (neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
1214 (const_int 1))
1215 (const_int 0))
1216 (label_ref (match_operand 2))
1217 (pc)))
1218 (clobber (reg:SI T_REG))]
1219 "TARGET_SH1"
1220 [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
1221 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1222 (label_ref (match_dup 2))
1223 (pc)))])
1224
1225 ;; FIXME: These could probably use code iterators for the compare op.
1226 (define_split
1227 [(set (pc)
1228 (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
1229 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1230 (label_ref (match_operand 2))
1231 (pc)))
1232 (clobber (reg:SI T_REG))]
1233 "TARGET_SH1"
1234 [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
1235 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1236 (label_ref (match_dup 2))
1237 (pc)))])
1238
1239 (define_split
1240 [(set (pc)
1241 (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
1242 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1243 (label_ref (match_operand 2))
1244 (pc)))
1245 (clobber (reg:SI T_REG))]
1246 "TARGET_SH1"
1247 [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
1248 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1249 (label_ref (match_dup 2))
1250 (pc)))])
1251
1252 (define_split
1253 [(set (pc)
1254 (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
1255 (match_operand:SI 1 "arith_reg_operand" ""))
1256 (label_ref (match_operand 2))
1257 (pc)))
1258 (clobber (reg:SI T_REG))]
1259 "TARGET_SH1"
1260 [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
1261 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1262 (label_ref (match_dup 2))
1263 (pc)))])
1264
1265 (define_split
1266 [(set (pc)
1267 (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
1268 (match_operand:SI 1 "arith_reg_operand" ""))
1269 (label_ref (match_operand 2))
1270 (pc)))
1271 (clobber (reg:SI T_REG))]
1272 "TARGET_SH1"
1273 [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
1274 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1275 (label_ref (match_dup 2))
1276 (pc)))])
1277
1278 ;; -------------------------------------------------------------------------
1279 ;; SImode unsigned integer comparisons
1280 ;; -------------------------------------------------------------------------
1281
1282 ;; Usually comparisons of 'unsigned int >= 0' are optimized away completely.
1283 ;; However, especially when optimizations are off (e.g. -O0) such comparisons
1284 ;; might remain and we have to handle them. If the '>= 0' case wasn't
1285 ;; handled here, something else would just load a '0' into the second operand
1286 ;; and do the comparison. We can do slightly better by just setting the
1287 ;; T bit to '1'.
1288 (define_insn_and_split "cmpgeusi_t"
1289 [(set (reg:SI T_REG)
1290 (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1291 (match_operand:SI 1 "arith_reg_or_0_operand" "r")))]
1292 "TARGET_SH1"
1293 "cmp/hs %1,%0"
1294 "&& satisfies_constraint_Z (operands[1])"
1295 [(set (reg:SI T_REG) (const_int 1))]
1296 ""
1297 [(set_attr "type" "mt_group")])
1298
1299 (define_insn "cmpgtusi_t"
1300 [(set (reg:SI T_REG)
1301 (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
1302 (match_operand:SI 1 "arith_reg_operand" "r")))]
1303 "TARGET_SH1"
1304 "cmp/hi %1,%0"
1305 [(set_attr "type" "mt_group")])
1306 \f
1307 ;; -------------------------------------------------------------------------
1308 ;; DImode compare and branch
1309 ;; -------------------------------------------------------------------------
1310
1311 ;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
1312 ;; Therefore, we aim to have a set of three branches that go straight to the
1313 ;; destination, i.e. only one of them is taken at any one time.
1314 ;; This mechanism should also be slightly better for the sh4-200.
1315
1316 (define_expand "cbranchdi4"
1317 [(set (pc)
1318 (if_then_else (match_operator 0 "comparison_operator"
1319 [(match_operand:DI 1 "arith_operand" "")
1320 (match_operand:DI 2 "arith_operand" "")])
1321 (label_ref (match_operand 3 "" ""))
1322 (pc)))
1323 (clobber (match_dup 4))
1324 (clobber (reg:SI T_REG))]
1325 "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
1326 {
1327 enum rtx_code comparison;
1328
1329 if (TARGET_SHMEDIA)
1330 {
1331 emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
1332 operands[2], operands[3]));
1333 DONE;
1334 }
1335 else if (!TARGET_CBRANCHDI4)
1336 {
1337 sh_emit_compare_and_branch (operands, DImode);
1338 DONE;
1339 }
1340 else
1341 {
1342 if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
1343 DONE;
1344
1345 comparison = prepare_cbranch_operands (operands, DImode,
1346 LAST_AND_UNUSED_RTX_CODE);
1347 if (comparison != GET_CODE (operands[0]))
1348 operands[0]
1349 = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
1350 operands[4] = gen_rtx_SCRATCH (SImode);
1351 }
1352 })
1353
1354 (define_insn_and_split "cbranchdi4_i"
1355 [(set (pc)
1356 (if_then_else (match_operator 0 "comparison_operator"
1357 [(match_operand:DI 1 "arith_operand" "r,r")
1358 (match_operand:DI 2 "arith_operand" "rN,I08")])
1359 (label_ref (match_operand 3 "" ""))
1360 (pc)))
1361 (clobber (match_scratch:SI 4 "=X,&r"))
1362 (clobber (reg:SI T_REG))]
1363 "TARGET_CBRANCHDI4"
1364 "#"
1365 "&& reload_completed"
1366 [(pc)]
1367 {
1368 if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
1369 FAIL;
1370 DONE;
1371 })
1372
1373 ;; -------------------------------------------------------------------------
1374 ;; DImode signed integer comparisons
1375 ;; -------------------------------------------------------------------------
1376
1377 (define_insn ""
1378 [(set (reg:SI T_REG)
1379 (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
1380 (match_operand:DI 1 "arith_operand" "r"))
1381 (const_int 0)))]
1382 "TARGET_SH1"
1383 {
1384 return output_branchy_insn (EQ, "tst\t%S1,%S0;bf\t%l9;tst\t%R1,%R0",
1385 insn, operands);
1386 }
1387 [(set_attr "length" "6")
1388 (set_attr "type" "arith3b")])
1389
1390 (define_insn "cmpeqdi_t"
1391 [(set (reg:SI T_REG)
1392 (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1393 (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
1394 "TARGET_SH1"
1395 {
1396 static const char* alt[] =
1397 {
1398 "tst %S0,%S0" "\n"
1399 " bf 0f" "\n"
1400 " tst %R0,%R0" "\n"
1401 "0:",
1402
1403 "cmp/eq %S1,%S0" "\n"
1404 " bf 0f" "\n"
1405 " cmp/eq %R1,%R0" "\n"
1406 "0:"
1407 };
1408 return alt[which_alternative];
1409 }
1410 [(set_attr "length" "6")
1411 (set_attr "type" "arith3b")])
1412
1413 (define_split
1414 [(set (reg:SI T_REG)
1415 (eq:SI (match_operand:DI 0 "arith_reg_operand" "")
1416 (match_operand:DI 1 "arith_reg_or_0_operand" "")))]
1417 ;; If we applied this split when not optimizing, it would only be
1418 ;; applied during the machine-dependent reorg, when no new basic blocks
1419 ;; may be created.
1420 "TARGET_SH1 && reload_completed && optimize"
1421 [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
1422 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
1423 (label_ref (match_dup 6))
1424 (pc)))
1425 (set (reg:SI T_REG) (eq:SI (match_dup 4) (match_dup 5)))
1426 (match_dup 6)]
1427 {
1428 operands[2] = gen_highpart (SImode, operands[0]);
1429 operands[3] = operands[1] == const0_rtx
1430 ? const0_rtx
1431 : gen_highpart (SImode, operands[1]);
1432 operands[4] = gen_lowpart (SImode, operands[0]);
1433 operands[5] = gen_lowpart (SImode, operands[1]);
1434 operands[6] = gen_label_rtx ();
1435 })
1436
1437 (define_insn "cmpgtdi_t"
1438 [(set (reg:SI T_REG)
1439 (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1440 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1441 "TARGET_SH2"
1442 {
1443 static const char* alt[] =
1444 {
1445 "cmp/eq %S1,%S0" "\n"
1446 " bf{.|/}s 0f" "\n"
1447 " cmp/gt %S1,%S0" "\n"
1448 " cmp/hi %R1,%R0" "\n"
1449 "0:",
1450
1451 "tst %S0,%S0" "\n"
1452 " bf{.|/}s 0f" "\n"
1453 " cmp/pl %S0" "\n"
1454 " cmp/hi %S0,%R0" "\n"
1455 "0:"
1456 };
1457 return alt[which_alternative];
1458 }
1459 [(set_attr "length" "8")
1460 (set_attr "type" "arith3")])
1461
1462 (define_insn "cmpgedi_t"
1463 [(set (reg:SI T_REG)
1464 (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
1465 (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
1466 "TARGET_SH2"
1467 {
1468 static const char* alt[] =
1469 {
1470 "cmp/eq %S1,%S0" "\n"
1471 " bf{.|/}s 0f" "\n"
1472 " cmp/ge %S1,%S0" "\n"
1473 " cmp/hs %R1,%R0" "\n"
1474 "0:",
1475
1476 "cmp/pz %S0"
1477 };
1478 return alt[which_alternative];
1479 }
1480 [(set_attr "length" "8,2")
1481 (set_attr "type" "arith3,mt_group")])
1482 \f
1483 ;; -------------------------------------------------------------------------
1484 ;; DImode unsigned integer comparisons
1485 ;; -------------------------------------------------------------------------
1486
1487 (define_insn "cmpgeudi_t"
1488 [(set (reg:SI T_REG)
1489 (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1490 (match_operand:DI 1 "arith_reg_operand" "r")))]
1491 "TARGET_SH2"
1492 {
1493 return "cmp/eq %S1,%S0" "\n"
1494 " bf{.|/}s 0f" "\n"
1495 " cmp/hs %S1,%S0" "\n"
1496 " cmp/hs %R1,%R0" "\n"
1497 "0:";
1498 }
1499 [(set_attr "length" "8")
1500 (set_attr "type" "arith3")])
1501
1502 (define_insn "cmpgtudi_t"
1503 [(set (reg:SI T_REG)
1504 (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
1505 (match_operand:DI 1 "arith_reg_operand" "r")))]
1506 "TARGET_SH2"
1507 {
1508 return "cmp/eq %S1,%S0" "\n"
1509 " bf{.|/}s 0f" "\n"
1510 " cmp/hi %S1,%S0" "\n"
1511 " cmp/hi %R1,%R0" "\n"
1512 "0:";
1513 }
1514 [(set_attr "length" "8")
1515 (set_attr "type" "arith3")])
1516
1517 (define_insn "cmpeqsi_media"
1518 [(set (match_operand:SI 0 "register_operand" "=r")
1519 (eq:SI (match_operand:SI 1 "logical_operand" "%r")
1520 (match_operand:SI 2 "cmp_operand" "Nr")))]
1521 "TARGET_SHMEDIA"
1522 "cmpeq %1, %N2, %0"
1523 [(set_attr "type" "cmp_media")])
1524
1525 (define_insn "cmpeqdi_media"
1526 [(set (match_operand:SI 0 "register_operand" "=r")
1527 (eq:SI (match_operand:DI 1 "register_operand" "%r")
1528 (match_operand:DI 2 "cmp_operand" "Nr")))]
1529 "TARGET_SHMEDIA"
1530 "cmpeq %1, %N2, %0"
1531 [(set_attr "type" "cmp_media")])
1532
1533 (define_insn "cmpgtsi_media"
1534 [(set (match_operand:SI 0 "register_operand" "=r")
1535 (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
1536 (match_operand:SI 2 "cmp_operand" "rN")))]
1537 "TARGET_SHMEDIA"
1538 "cmpgt %N1, %N2, %0"
1539 [(set_attr "type" "cmp_media")])
1540
1541 (define_insn "cmpgtdi_media"
1542 [(set (match_operand:SI 0 "register_operand" "=r")
1543 (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1544 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1545 "TARGET_SHMEDIA"
1546 "cmpgt %N1, %N2, %0"
1547 [(set_attr "type" "cmp_media")])
1548
1549 (define_insn "cmpgtusi_media"
1550 [(set (match_operand:SI 0 "register_operand" "=r")
1551 (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
1552 (match_operand:SI 2 "cmp_operand" "rN")))]
1553 "TARGET_SHMEDIA"
1554 "cmpgtu %N1, %N2, %0"
1555 [(set_attr "type" "cmp_media")])
1556
1557 (define_insn "cmpgtudi_media"
1558 [(set (match_operand:SI 0 "register_operand" "=r")
1559 (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
1560 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
1561 "TARGET_SHMEDIA"
1562 "cmpgtu %N1, %N2, %0"
1563 [(set_attr "type" "cmp_media")])
1564
1565 ; This pattern is for combine.
1566 (define_insn "*cmpne0sisi_media"
1567 [(set (match_operand:SI 0 "register_operand" "=r")
1568 (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
1569 "TARGET_SHMEDIA"
1570 "cmpgtu %1,r63,%0"
1571 [(set_attr "type" "cmp_media")])
1572
1573 ;; -------------------------------------------------------------------------
1574 ;; Conditional move instructions
1575 ;; -------------------------------------------------------------------------
1576
1577 ;; The insn names may seem reversed, but note that cmveq performs the move
1578 ;; if op1 == 0, and cmvne does it if op1 != 0.
1579
1580 (define_insn "movdicc_false"
1581 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1582 (if_then_else:DI (eq (match_operand:DI 1 "arith_reg_operand" "r")
1583 (const_int 0))
1584 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1585 (match_operand:DI 3 "arith_reg_operand" "0")))]
1586 "TARGET_SHMEDIA"
1587 "cmveq %1, %N2, %0"
1588 [(set_attr "type" "arith_media")])
1589
1590 (define_insn "movdicc_true"
1591 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1592 (if_then_else:DI (ne (match_operand:DI 1 "arith_reg_operand" "r")
1593 (const_int 0))
1594 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")
1595 (match_operand:DI 3 "arith_reg_operand" "0")))]
1596 "TARGET_SHMEDIA"
1597 "cmvne %1, %N2, %0"
1598 [(set_attr "type" "arith_media")])
1599
1600 (define_peephole2
1601 [(set (match_operand:DI 0 "arith_reg_dest" "")
1602 (if_then_else:DI (match_operator 3 "equality_comparison_operator"
1603 [(match_operand:DI 1 "arith_reg_operand" "")
1604 (const_int 0)])
1605 (match_operand:DI 2 "arith_reg_dest" "")
1606 (match_dup 0)))
1607 (set (match_dup 2) (match_dup 0))]
1608 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1609 [(set (match_dup 2)
1610 (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))]
1611 {
1612 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1613 VOIDmode, operands[1], CONST0_RTX (DImode));
1614 })
1615
1616 (define_peephole2
1617 [(set (match_operand:DI 0 "general_movdst_operand" "")
1618 (match_operand:DI 1 "arith_reg_or_0_operand" ""))
1619 (set (match_operand:DI 2 "arith_reg_dest" "")
1620 (if_then_else:DI (match_operator 4 "equality_comparison_operator"
1621 [(match_operand:DI 3 "arith_reg_operand" "")
1622 (const_int 0)])
1623 (match_dup 0)
1624 (match_dup 2)))]
1625 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1626 [(set (match_dup 2)
1627 (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))]
1628 "")
1629
1630 (define_expand "movdicc"
1631 [(set (match_operand:DI 0 "register_operand" "")
1632 (if_then_else:DI (match_operand 1 "comparison_operator" "")
1633 (match_operand:DI 2 "register_operand" "")
1634 (match_operand:DI 3 "register_operand" "")))]
1635 "TARGET_SHMEDIA"
1636 {
1637 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1638 && GET_MODE (XEXP (operands[1], 0)) == DImode
1639 && XEXP (operands[1], 1) == const0_rtx)
1640 ;
1641 else
1642 {
1643 if (!can_create_pseudo_p ())
1644 FAIL;
1645
1646 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1647 GET_CODE (operands[1]),
1648 XEXP (operands[1], 0),
1649 XEXP (operands[1], 1));
1650 if (!operands[1])
1651 FAIL;
1652 }
1653 })
1654
1655 ;; Add SImode variants for cmveq / cmvne to compensate for not promoting
1656 ;; SImode to DImode.
1657 (define_insn "movsicc_false"
1658 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1659 (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r")
1660 (const_int 0))
1661 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1662 (match_operand:SI 3 "arith_reg_operand" "0")))]
1663 "TARGET_SHMEDIA"
1664 "cmveq %1, %N2, %0"
1665 [(set_attr "type" "arith_media")])
1666
1667 (define_insn "movsicc_true"
1668 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1669 (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r")
1670 (const_int 0))
1671 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1672 (match_operand:SI 3 "arith_reg_operand" "0")))]
1673 "TARGET_SHMEDIA"
1674 "cmvne %1, %N2, %0"
1675 [(set_attr "type" "arith_media")])
1676
1677 (define_peephole2
1678 [(set (match_operand:SI 0 "arith_reg_dest" "")
1679 (if_then_else:SI (match_operator 3 "equality_comparison_operator"
1680 [(match_operand:SI 1 "arith_reg_operand" "")
1681 (const_int 0)])
1682 (match_operand:SI 2 "arith_reg_dest" "")
1683 (match_dup 0)))
1684 (set (match_dup 2) (match_dup 0))]
1685 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])"
1686 [(set (match_dup 2)
1687 (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))]
1688 {
1689 operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])),
1690 VOIDmode, operands[1], CONST0_RTX (SImode));
1691 })
1692
1693 (define_peephole2
1694 [(set (match_operand:SI 0 "general_movdst_operand" "")
1695 (match_operand:SI 1 "arith_reg_or_0_operand" ""))
1696 (set (match_operand:SI 2 "arith_reg_dest" "")
1697 (if_then_else:SI (match_operator 4 "equality_comparison_operator"
1698 [(match_operand:SI 3 "arith_reg_operand" "")
1699 (const_int 0)])
1700 (match_dup 0)
1701 (match_dup 2)))]
1702 "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])
1703 && (!REG_P (operands[1]) || GENERAL_REGISTER_P (REGNO (operands[1])))"
1704 [(set (match_dup 2)
1705 (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))]
1706 {
1707 replace_rtx (operands[4], operands[0], operands[1]);
1708 })
1709
1710 ;; The register allocator is rather clumsy in handling multi-way conditional
1711 ;; moves, so allow the combiner to make them, and we split them up after
1712 ;; reload. */
1713 (define_insn_and_split "*movsicc_umin"
1714 [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
1715 (umin:SI (if_then_else:SI
1716 (eq (match_operand:SI 1 "arith_reg_operand" "r")
1717 (const_int 0))
1718 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")
1719 (match_operand:SI 3 "register_operand" "0"))
1720 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
1721 (clobber (match_scratch:SI 5 "=&r"))]
1722 "TARGET_SHMEDIA && !can_create_pseudo_p ()"
1723 "#"
1724 "TARGET_SHMEDIA && reload_completed"
1725 [(pc)]
1726 {
1727 emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
1728 operands[3]));
1729 emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
1730 emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
1731 operands[0]));
1732 DONE;
1733 })
1734
1735 (define_insn "*movsicc_t_false"
1736 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1737 (if_then_else (eq (reg:SI T_REG) (const_int 0))
1738 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1739 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1740 "TARGET_PRETEND_CMOVE
1741 && (arith_reg_operand (operands[1], SImode)
1742 || (immediate_operand (operands[1], SImode)
1743 && satisfies_constraint_I08 (operands[1])))"
1744 {
1745 return "bt 0f" "\n"
1746 " mov %1,%0" "\n"
1747 "0:";
1748 }
1749 [(set_attr "type" "mt_group,arith") ;; poor approximation
1750 (set_attr "length" "4")])
1751
1752 (define_insn "*movsicc_t_true"
1753 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
1754 (if_then_else (ne (reg:SI T_REG) (const_int 0))
1755 (match_operand:SI 1 "general_movsrc_operand" "r,I08")
1756 (match_operand:SI 2 "arith_reg_operand" "0,0")))]
1757 "TARGET_PRETEND_CMOVE
1758 && (arith_reg_operand (operands[1], SImode)
1759 || (immediate_operand (operands[1], SImode)
1760 && satisfies_constraint_I08 (operands[1])))"
1761 {
1762 return "bf 0f" "\n"
1763 " mov %1,%0" "\n"
1764 "0:";
1765 }
1766 [(set_attr "type" "mt_group,arith") ;; poor approximation
1767 (set_attr "length" "4")])
1768
1769 (define_expand "movsicc"
1770 [(set (match_operand:SI 0 "arith_reg_dest" "")
1771 (if_then_else:SI (match_operand 1 "comparison_operator" "")
1772 (match_operand:SI 2 "arith_reg_or_0_operand" "")
1773 (match_operand:SI 3 "arith_reg_operand" "")))]
1774 "TARGET_SHMEDIA || TARGET_PRETEND_CMOVE"
1775 {
1776 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1777 && GET_MODE (XEXP (operands[1], 0)) == SImode
1778 && (TARGET_SHMEDIA
1779 || (REG_P (XEXP (operands[1], 0))
1780 && REGNO (XEXP (operands[1], 0)) == T_REG))
1781 && XEXP (operands[1], 1) == const0_rtx)
1782 ;
1783
1784 else if (TARGET_PRETEND_CMOVE)
1785 {
1786 enum rtx_code code = GET_CODE (operands[1]);
1787 enum rtx_code new_code = code;
1788 rtx op0 = XEXP (operands[1], 0);
1789 rtx op1 = XEXP (operands[1], 1);
1790
1791 if (! currently_expanding_to_rtl)
1792 FAIL;
1793 switch (code)
1794 {
1795 case LT: case LE: case LEU: case LTU:
1796 if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
1797 break;
1798 case NE:
1799 new_code = reverse_condition (code);
1800 break;
1801 case EQ: case GT: case GE: case GEU: case GTU:
1802 break;
1803 default:
1804 FAIL;
1805 }
1806 sh_emit_scc_to_t (new_code, op0, op1);
1807 operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
1808 gen_rtx_REG (SImode, T_REG), const0_rtx);
1809 }
1810 else
1811 {
1812 if (!can_create_pseudo_p ())
1813 FAIL;
1814
1815 operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
1816 GET_CODE (operands[1]),
1817 XEXP (operands[1], 0),
1818 XEXP (operands[1], 1));
1819 if (!operands[1])
1820 FAIL;
1821 }
1822 })
1823
1824 (define_expand "movqicc"
1825 [(set (match_operand:QI 0 "register_operand" "")
1826 (if_then_else:QI (match_operand 1 "comparison_operator" "")
1827 (match_operand:QI 2 "register_operand" "")
1828 (match_operand:QI 3 "register_operand" "")))]
1829 "TARGET_SHMEDIA"
1830 {
1831 operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
1832 operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
1833 operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0);
1834 emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3]));
1835 DONE;
1836 })
1837 \f
1838 ;; -------------------------------------------------------------------------
1839 ;; Addition instructions
1840 ;; -------------------------------------------------------------------------
1841
1842 (define_expand "adddi3"
1843 [(set (match_operand:DI 0 "arith_reg_operand")
1844 (plus:DI (match_operand:DI 1 "arith_reg_operand")
1845 (match_operand:DI 2 "arith_operand")))]
1846 ""
1847 {
1848 if (TARGET_SH1)
1849 {
1850 operands[2] = force_reg (DImode, operands[2]);
1851 emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
1852 DONE;
1853 }
1854 })
1855
1856 (define_insn "*adddi3_media"
1857 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
1858 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1859 (match_operand:DI 2 "arith_operand" "r,I10")))]
1860 "TARGET_SHMEDIA"
1861 "@
1862 add %1, %2, %0
1863 addi %1, %2, %0"
1864 [(set_attr "type" "arith_media")])
1865
1866 (define_insn "*adddisi3_media"
1867 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0)
1868 (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
1869 (match_operand:DI 2 "arith_operand" "r,I10")))]
1870 "TARGET_SHMEDIA"
1871 "@
1872 add.l %1, %2, %0
1873 addi.l %1, %2, %0"
1874 [(set_attr "type" "arith_media")
1875 (set_attr "highpart" "ignore")])
1876
1877 (define_insn "adddi3z_media"
1878 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
1879 (zero_extend:DI
1880 (plus:SI (match_operand:SI 1 "extend_reg_operand" "r")
1881 (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))]
1882 "TARGET_SHMEDIA"
1883 "addz.l %1, %N2, %0"
1884 [(set_attr "type" "arith_media")
1885 (set_attr "highpart" "ignore")])
1886
1887 (define_insn_and_split "adddi3_compact"
1888 [(set (match_operand:DI 0 "arith_reg_dest")
1889 (plus:DI (match_operand:DI 1 "arith_reg_operand")
1890 (match_operand:DI 2 "arith_reg_operand")))
1891 (clobber (reg:SI T_REG))]
1892 "TARGET_SH1"
1893 "#"
1894 "&& can_create_pseudo_p ()"
1895 [(const_int 0)]
1896 {
1897 emit_insn (gen_clrt ());
1898 emit_insn (gen_addc (gen_lowpart (SImode, operands[0]),
1899 gen_lowpart (SImode, operands[1]),
1900 gen_lowpart (SImode, operands[2])));
1901 emit_insn (gen_addc (gen_highpart (SImode, operands[0]),
1902 gen_highpart (SImode, operands[1]),
1903 gen_highpart (SImode, operands[2])));
1904 DONE;
1905 })
1906
1907 (define_insn "addc"
1908 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
1909 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
1910 (match_operand:SI 2 "arith_reg_operand" "r"))
1911 (reg:SI T_REG)))
1912 (set (reg:SI T_REG)
1913 (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
1914 "TARGET_SH1"
1915 "addc %2,%0"
1916 [(set_attr "type" "arith")])
1917
1918 ;; A simplified version of the addc insn, where the exact value of the
1919 ;; T bit doesn't matter. This is easier for combine to pick up.
1920 ;; We allow a reg or 0 for one of the operands in order to be able to
1921 ;; do 'reg + T' sequences.
1922 (define_insn_and_split "*addc"
1923 [(set (match_operand:SI 0 "arith_reg_dest")
1924 (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand")
1925 (match_operand:SI 2 "arith_reg_or_0_operand"))
1926 (match_operand 3 "treg_set_expr")))
1927 (clobber (reg:SI T_REG))]
1928 "TARGET_SH1 && can_create_pseudo_p ()"
1929 "#"
1930 "&& 1"
1931 [(const_int 0)]
1932 {
1933 sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn);
1934 if (ti.has_trailing_nott ())
1935 {
1936 if (operands[2] == const0_rtx)
1937 {
1938 /* op1 + 0 + (1 - T) = op1 + 1 - T = op1 - (-1) - T */
1939 remove_insn (ti.trailing_nott ());
1940 emit_insn (gen_subc (operands[0], operands[1],
1941 force_reg (SImode, GEN_INT (-1))));
1942 DONE;
1943 }
1944 else if (!TARGET_SH2A)
1945 {
1946 /* op1 + op2 + (1 - T) = op1 - (0 - op2 - 1) - T = op1 - ~op2 - T
1947 On SH2A keep the nott insn, because nott-addc sequence doesn't
1948 mutate the inputs. */
1949 remove_insn (ti.trailing_nott ());
1950 rtx tmp = gen_reg_rtx (SImode);
1951 emit_insn (gen_one_cmplsi2 (tmp, operands[2]));
1952 emit_insn (gen_subc (operands[0], operands[1], tmp));
1953 DONE;
1954 }
1955 }
1956
1957 emit_insn (gen_addc (operands[0], operands[1],
1958 force_reg (SImode, operands[2])));
1959 DONE;
1960 })
1961
1962 (define_insn_and_split "*addc"
1963 [(set (match_operand:SI 0 "arith_reg_dest")
1964 (plus:SI (plus:SI (match_operand 1 "treg_set_expr")
1965 (match_operand:SI 2 "arith_reg_operand"))
1966 (match_operand:SI 3 "arith_reg_operand")))
1967 (clobber (reg:SI T_REG))]
1968 "TARGET_SH1 && can_create_pseudo_p ()"
1969 "#"
1970 "&& 1"
1971 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1972 (match_dup 1)))
1973 (clobber (reg:SI T_REG))])])
1974
1975 (define_insn_and_split "*addc"
1976 [(set (match_operand:SI 0 "arith_reg_dest")
1977 (plus:SI (match_operand 1 "treg_set_expr")
1978 (plus:SI (match_operand:SI 2 "arith_reg_operand")
1979 (match_operand:SI 3 "arith_reg_operand"))))
1980 (clobber (reg:SI T_REG))]
1981 "TARGET_SH1 && can_create_pseudo_p ()"
1982 "#"
1983 "&& 1"
1984 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
1985 (match_dup 1)))
1986 (clobber (reg:SI T_REG))])])
1987
1988 ;; Sometimes combine will try to do 'reg + (0-reg) + 1' if the *addc pattern
1989 ;; matched. Split this up into a simple sub add sequence, as this will save
1990 ;; us one sett insn.
1991 (define_insn_and_split "*minus_plus_one"
1992 [(set (match_operand:SI 0 "arith_reg_dest" "")
1993 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
1994 (match_operand:SI 2 "arith_reg_operand" ""))
1995 (const_int 1)))]
1996 "TARGET_SH1"
1997 "#"
1998 "&& 1"
1999 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
2000 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
2001
2002
2003 ;; The tree optimiziers canonicalize
2004 ;; reg + (reg & 1)
2005 ;; into
2006 ;; (reg + 1) & -2
2007 ;;
2008 ;; On SH2A an add-bclr sequence will be used to handle this.
2009 ;; On non-SH2A re-emit the add-and sequence to improve register utilization.
2010 (define_insn_and_split "*round_int_even"
2011 [(set (match_operand:SI 0 "arith_reg_dest")
2012 (and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand")
2013 (const_int 1))
2014 (const_int -2)))]
2015 "TARGET_SH1 && !TARGET_SH2A && can_create_pseudo_p ()
2016 && !reg_overlap_mentioned_p (operands[0], operands[1])"
2017 "#"
2018 "&& 1"
2019 [(set (match_dup 0) (const_int -2))
2020 (set (match_dup 2) (plus:SI (match_dup 1) (const_int 1)))
2021 (set (match_dup 0) (and:SI (match_dup 0) (match_dup 2)))]
2022 {
2023 operands[2] = gen_reg_rtx (SImode);
2024 })
2025
2026 ;; If the *round_int_even pattern is combined with another plus,
2027 ;; convert it into an addc pattern to emit an shlr-addc sequence.
2028 ;; This split is taken by combine on non-SH2A and SH2A.
2029 (define_split
2030 [(set (match_operand:SI 0 "arith_reg_dest")
2031 (plus:SI (and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand")
2032 (const_int 1))
2033 (const_int -2))
2034 (match_operand:SI 2 "arith_reg_operand")))]
2035 "TARGET_SH1 && can_create_pseudo_p ()"
2036 [(parallel [(set (match_dup 0)
2037 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
2038 (and:SI (match_dup 1) (const_int 1))))
2039 (clobber (reg:SI T_REG))])])
2040
2041 ;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
2042 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
2043 ;; operation, as opposed to sequences such as
2044 ;; movt r2
2045 ;; add r2,r3
2046 ;;
2047 ;; Even if the constant is not CSE-ed, a sequence such as
2048 ;; mov #0,r2
2049 ;; addc r2,r3
2050 ;; can be scheduled much better since the load of the constant can be
2051 ;; done earlier, before any comparison insns that store the result in
2052 ;; the T bit.
2053 ;; However, avoid things like 'reg + 1', which would expand into a
2054 ;; 3 insn sequence, instead of add #imm8.
2055 (define_insn_and_split "*addc_t_r"
2056 [(set (match_operand:SI 0 "arith_reg_dest")
2057 (plus:SI (match_operand 1 "treg_set_expr_not_const01")
2058 (match_operand:SI 2 "arith_reg_operand")))
2059 (clobber (reg:SI T_REG))]
2060 "TARGET_SH1 && can_create_pseudo_p ()"
2061 "#"
2062 "&& 1"
2063 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (const_int 0))
2064 (match_dup 1)))
2065 (clobber (reg:SI T_REG))])])
2066
2067 (define_insn_and_split "*addc_r_t"
2068 [(set (match_operand:SI 0 "arith_reg_dest")
2069 (plus:SI (match_operand:SI 1 "arith_reg_operand")
2070 (match_operand 2 "treg_set_expr_not_const01")))
2071 (clobber (reg:SI T_REG))]
2072 "TARGET_SH1 && can_create_pseudo_p ()"
2073 "#"
2074 "&& 1"
2075 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (const_int 0))
2076 (match_dup 2)))
2077 (clobber (reg:SI T_REG))])])
2078
2079 ;; Convert '2 * reg + T' into 'reg + reg + T'.
2080 (define_insn_and_split "*addc_2r_t"
2081 [(set (match_operand:SI 0 "arith_reg_dest")
2082 (plus:SI (match_operand 1 "treg_set_expr")
2083 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
2084 (const_int 1))))
2085 (clobber (reg:SI T_REG))]
2086 "TARGET_SH1 && can_create_pseudo_p ()"
2087 "#"
2088 "&& 1"
2089 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 2))
2090 (match_dup 1)))
2091 (clobber (reg:SI T_REG))])])
2092
2093 (define_insn_and_split "*addc_2r_t"
2094 [(set (match_operand:SI 0 "arith_reg_dest")
2095 (plus:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
2096 (const_int 1))
2097 (match_operand 2 "treg_set_expr")))
2098 (clobber (reg:SI T_REG))]
2099 "TARGET_SH1 && can_create_pseudo_p ()"
2100 "#"
2101 "&& 1"
2102 [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 1) (match_dup 1))
2103 (match_dup 2)))
2104 (clobber (reg:SI T_REG))])])
2105
2106 ;; Convert '(op2 + T) - op3' into 'op2 + (-op3) + T'
2107 (define_insn_and_split "*addc_negreg_t"
2108 [(set (match_operand:SI 0 "arith_reg_dest")
2109 (minus:SI (plus:SI (match_operand 1 "treg_set_expr")
2110 (match_operand:SI 2 "arith_reg_operand"))
2111 (match_operand:SI 3 "arith_reg_operand")))
2112 (clobber (reg:SI T_REG))]
2113 "TARGET_SH1 && can_create_pseudo_p ()"
2114 "#"
2115 "&& 1"
2116 [(set (match_dup 4) (neg:SI (match_dup 3)))
2117 (parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 4))
2118 (match_dup 1)))
2119 (clobber (reg:SI T_REG))])]
2120 {
2121 operands[4] = gen_reg_rtx (SImode);
2122 })
2123
2124 (define_expand "addsi3"
2125 [(set (match_operand:SI 0 "arith_reg_dest")
2126 (plus:SI (match_operand:SI 1 "arith_reg_operand")
2127 (match_operand:SI 2 "arith_or_int_operand")))]
2128 ""
2129 {
2130 if (TARGET_SH1 && !arith_operand (operands[2], SImode))
2131 {
2132 if (!sh_lra_p () || reg_overlap_mentioned_p (operands[0], operands[1]))
2133 {
2134 emit_insn (gen_addsi3_scr (operands[0], operands[1], operands[2]));
2135 DONE;
2136 }
2137 }
2138 })
2139
2140 (define_insn "addsi3_media"
2141 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
2142 (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r")
2143 (match_operand:SI 2 "arith_operand" "r,I10")))]
2144 "TARGET_SHMEDIA"
2145 "@
2146 add.l %1, %2, %0
2147 addi.l %1, %2, %0"
2148 [(set_attr "type" "arith_media")
2149 (set_attr "highpart" "ignore")])
2150
2151 (define_insn "addsidi3_media"
2152 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
2153 (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand"
2154 "%r,r")
2155 (match_operand:SI 2 "arith_operand"
2156 "r,I10"))))]
2157 "TARGET_SHMEDIA"
2158 "@
2159 add.l %1, %2, %0
2160 addi.l %1, %2, %0"
2161 [(set_attr "type" "arith_media")
2162 (set_attr "highpart" "ignore")])
2163
2164 ;; The *addsi3_compact is made an insn_and_split and accepts actually
2165 ;; impossible constraints to make LRA's register elimination work well on SH.
2166 ;; The problem is that LRA expects something like
2167 ;; (set rA (plus rB (const_int N)))
2168 ;; to work. We can do that, but we have to split out an additional reg-reg
2169 ;; copy or constant load before the actual add insn.
2170 ;; Use u constraint for that case to avoid the invalid value in the stack
2171 ;; pointer.
2172 ;; This also results in better code when LRA is not used. However, we have
2173 ;; to use different sets of patterns and the order of these patterns is
2174 ;; important.
2175 ;; In some cases the constant zero might end up in operands[2] of the
2176 ;; patterns. We have to accept that and convert it into a reg-reg move.
2177 (define_insn_and_split "*addsi3_compact_lra"
2178 [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u")
2179 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r")
2180 (match_operand:SI 2 "arith_or_int_operand" "rI08,rn")))]
2181 "TARGET_SH1 && sh_lra_p ()
2182 && (! reg_overlap_mentioned_p (operands[0], operands[1])
2183 || arith_operand (operands[2], SImode))"
2184 "@
2185 add %2,%0
2186 #"
2187 "&& reload_completed
2188 && ! reg_overlap_mentioned_p (operands[0], operands[1])"
2189 [(set (match_dup 0) (match_dup 2))
2190 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
2191 {
2192 /* Prefer 'mov r0,r1; add #imm8,r1' over 'mov #imm8,r1; add r0,r1' */
2193 if (satisfies_constraint_I08 (operands[2]))
2194 std::swap (operands[1], operands[2]);
2195 }
2196 [(set_attr "type" "arith")])
2197
2198 (define_insn_and_split "addsi3_scr"
2199 [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u,&u")
2200 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r,r")
2201 (match_operand:SI 2 "arith_or_int_operand" "rI08,r,n")))
2202 (clobber (match_scratch:SI 3 "=X,X,&u"))]
2203 "TARGET_SH1"
2204 "@
2205 add %2,%0
2206 #
2207 #"
2208 "&& reload_completed"
2209 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
2210 {
2211 if (operands[2] == const0_rtx)
2212 {
2213 emit_move_insn (operands[0], operands[1]);
2214 DONE;
2215 }
2216
2217 if (CONST_INT_P (operands[2]) && !satisfies_constraint_I08 (operands[2]))
2218 {
2219 if (reg_overlap_mentioned_p (operands[0], operands[1]))
2220 {
2221 emit_move_insn (operands[3], operands[2]);
2222 emit_move_insn (operands[0], operands[1]);
2223 operands[2] = operands[3];
2224 }
2225 else
2226 {
2227 emit_move_insn (operands[0], operands[2]);
2228 operands[2] = operands[1];
2229 }
2230 }
2231 else if (!reg_overlap_mentioned_p (operands[0], operands[1]))
2232 emit_move_insn (operands[0], operands[1]);
2233 }
2234 [(set_attr "type" "arith")])
2235
2236 (define_insn_and_split "*addsi3"
2237 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
2238 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r")
2239 (match_operand:SI 2 "arith_operand" "rI08,Z")))]
2240 "TARGET_SH1 && !sh_lra_p ()"
2241 "@
2242 add %2,%0
2243 #"
2244 "&& operands[2] == const0_rtx"
2245 [(set (match_dup 0) (match_dup 1))]
2246 {
2247 }
2248 [(set_attr "type" "arith")])
2249
2250 ;; -------------------------------------------------------------------------
2251 ;; Subtraction instructions
2252 ;; -------------------------------------------------------------------------
2253
2254 (define_expand "subdi3"
2255 [(set (match_operand:DI 0 "arith_reg_operand" "")
2256 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "")
2257 (match_operand:DI 2 "arith_reg_operand" "")))]
2258 ""
2259 {
2260 if (TARGET_SH1)
2261 {
2262 operands[1] = force_reg (DImode, operands[1]);
2263 emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
2264 DONE;
2265 }
2266 })
2267
2268 (define_insn "*subdi3_media"
2269 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
2270 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2271 (match_operand:DI 2 "arith_reg_operand" "r")))]
2272 "TARGET_SHMEDIA"
2273 "sub %N1, %2, %0"
2274 [(set_attr "type" "arith_media")])
2275
2276 (define_insn "subdisi3_media"
2277 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
2278 (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN")
2279 (match_operand:DI 2 "arith_reg_operand" "r")))]
2280 "TARGET_SHMEDIA"
2281 "sub.l %N1, %2, %0"
2282 [(set_attr "type" "arith_media")
2283 (set_attr "highpart" "ignore")])
2284
2285 (define_insn_and_split "subdi3_compact"
2286 [(set (match_operand:DI 0 "arith_reg_dest")
2287 (minus:DI (match_operand:DI 1 "arith_reg_operand")
2288 (match_operand:DI 2 "arith_reg_operand")))
2289 (clobber (reg:SI T_REG))]
2290 "TARGET_SH1"
2291 "#"
2292 "&& can_create_pseudo_p ()"
2293 [(const_int 0)]
2294 {
2295 emit_insn (gen_clrt ());
2296 emit_insn (gen_subc (gen_lowpart (SImode, operands[0]),
2297 gen_lowpart (SImode, operands[1]),
2298 gen_lowpart (SImode, operands[2])));
2299 emit_insn (gen_subc (gen_highpart (SImode, operands[0]),
2300 gen_highpart (SImode, operands[1]),
2301 gen_highpart (SImode, operands[2])));
2302 DONE;
2303 })
2304
2305 (define_insn "subc"
2306 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2307 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2308 (match_operand:SI 2 "arith_reg_operand" "r"))
2309 (reg:SI T_REG)))
2310 (set (reg:SI T_REG)
2311 (gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
2312 (reg:SI T_REG))
2313 (match_dup 1)))]
2314 "TARGET_SH1"
2315 "subc %2,%0"
2316 [(set_attr "type" "arith")])
2317
2318 ;; A simplified version of the subc insn, where the exact value of the
2319 ;; T bit doesn't matter. This is easier for combine to pick up.
2320 ;; We allow a reg or 0 for one of the operands in order to be able to
2321 ;; do 'reg - T' sequences. Reload will load the constant 0 into the reg
2322 ;; as needed.
2323 (define_insn_and_split "*subc"
2324 [(set (match_operand:SI 0 "arith_reg_dest")
2325 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand")
2326 (match_operand:SI 2 "arith_reg_or_0_operand"))
2327 (match_operand 3 "treg_set_expr")))
2328 (clobber (reg:SI T_REG))]
2329 "TARGET_SH1 && can_create_pseudo_p ()"
2330 "#"
2331 "&& 1"
2332 [(const_int 0)]
2333 {
2334 sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn);
2335 if (ti.has_trailing_nott ())
2336 {
2337 if (operands[2] == const0_rtx)
2338 {
2339 /* op1 - (1 - T) = op1 - 1 + T = op1 + (-1) + T */
2340 remove_insn (ti.trailing_nott ());
2341 emit_insn (gen_addc (operands[0], operands[1],
2342 force_reg (SImode, GEN_INT (-1))));
2343 DONE;
2344 }
2345 else if (!TARGET_SH2A)
2346 {
2347 /* op1 - op2 - (1 - T) = op1 + (0 - op2 - 1) + T = op1 + ~op2 + T
2348 On SH2A keep the nott insn, because nott-subc sequence doesn't
2349 mutate the inputs. */
2350 remove_insn (ti.trailing_nott ());
2351 rtx tmp = gen_reg_rtx (SImode);
2352 emit_insn (gen_one_cmplsi2 (tmp, operands[2]));
2353 emit_insn (gen_addc (operands[0], operands[1], tmp));
2354 DONE;
2355 }
2356 }
2357
2358 emit_insn (gen_subc (operands[0], operands[1],
2359 force_reg (SImode, operands[2])));
2360 DONE;
2361 })
2362
2363 ;; Convert reg - T - reg = reg - reg - T
2364 (define_insn_and_split "*subc"
2365 [(set (match_operand:SI 0 "arith_reg_dest")
2366 (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand")
2367 (match_operand 2 "treg_set_expr"))
2368 (match_operand:SI 3 "arith_reg_operand")))
2369 (clobber (reg:SI T_REG))]
2370 "TARGET_SH1 && can_create_pseudo_p ()"
2371 "#"
2372 "&& 1"
2373 [(parallel [(set (match_dup 0)
2374 (minus:SI (minus:SI (match_dup 1) (match_dup 3))
2375 (match_dup 2)))
2376 (clobber (reg:SI T_REG))])])
2377
2378 ;; Split reg - reg - 1 into a sett subc sequence, as it can be scheduled
2379 ;; better, if the sett insn can be done early.
2380 ;; Notice that combine turns 'a - b - 1' into 'a + (~b)'.
2381 (define_insn_and_split "*subc"
2382 [(set (match_operand:SI 0 "arith_reg_dest" "")
2383 (plus:SI (not:SI (match_operand:SI 1 "arith_reg_operand" ""))
2384 (match_operand:SI 2 "arith_reg_operand" "")))
2385 (clobber (reg:SI T_REG))]
2386 "TARGET_SH1 && can_create_pseudo_p ()"
2387 "#"
2388 "&& 1"
2389 [(parallel [(set (match_dup 0)
2390 (minus:SI (minus:SI (match_dup 2) (match_dup 1))
2391 (const_int 1)))
2392 (clobber (reg:SI T_REG))])])
2393
2394 ;; Split 'reg - T' into 'reg - 0 - T' to utilize the subc insn.
2395 ;; If the 0 constant can be CSE-ed, this becomes a one instruction
2396 ;; operation, as opposed to sequences such as
2397 ;; movt r2
2398 ;; sub r2,r3
2399 ;;
2400 ;; Even if the constant is not CSE-ed, a sequence such as
2401 ;; mov #0,r2
2402 ;; subc r2,r3
2403 ;; can be scheduled much better since the load of the constant can be
2404 ;; done earlier, before any comparison insns that store the result in
2405 ;; the T bit.
2406 ;; However, avoid things like 'reg - 1', which would expand into a
2407 ;; 3 insn sequence, instead of add #imm8.
2408 (define_insn_and_split "*subc"
2409 [(set (match_operand:SI 0 "arith_reg_dest" "")
2410 (minus:SI (match_operand:SI 1 "arith_reg_operand" "")
2411 (match_operand 2 "treg_set_expr_not_const01")))
2412 (clobber (reg:SI T_REG))]
2413 "TARGET_SH1 && can_create_pseudo_p ()"
2414 "#"
2415 "&& 1"
2416 [(parallel [(set (match_dup 0)
2417 (minus:SI (minus:SI (match_dup 1) (const_int 0))
2418 (match_dup 2)))
2419 (clobber (reg:SI T_REG))])])
2420
2421 ;; Convert
2422 ;; (1 - T) - op2 = 1 - op2 - T
2423 (define_insn_and_split "*subc_negt_reg"
2424 [(set (match_operand:SI 0 "arith_reg_dest")
2425 (minus:SI (match_operand 1 "treg_set_expr_not_const01")
2426 (match_operand:SI 2 "arith_reg_operand")))
2427 (clobber (reg:SI T_REG))]
2428 "TARGET_SH1 && can_create_pseudo_p ()"
2429 "#"
2430 "&& 1"
2431 [(const_int 0)]
2432 {
2433 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
2434 if (ti.remove_trailing_nott ())
2435 {
2436 /* (1 - T) - op2 = 1 - op2 - T */
2437 emit_insn (gen_subc (operands[0],
2438 force_reg (SImode, GEN_INT (1)), operands[2]));
2439 }
2440 else
2441 {
2442 /* T - op2: use movt,sub sequence. */
2443 rtx tmp = gen_reg_rtx (SImode);
2444 emit_insn (gen_movt (tmp, get_t_reg_rtx ()));
2445 emit_insn (gen_subsi3 (operands[0], tmp, operands[2]));
2446 }
2447 DONE;
2448 })
2449
2450 ;; Convert
2451 ;; op1 - (1 - T) + op3 = op1 - 1 + T + op3
2452 ;; (op1 - T) + op3 = op1 - (-op3) - T
2453 (define_insn_and_split "*subc_negreg_t"
2454 [(set (match_operand:SI 0 "arith_reg_dest")
2455 (plus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand")
2456 (match_operand 2 "treg_set_expr"))
2457 (match_operand:SI 3 "arith_reg_operand")))
2458 (clobber (reg:SI T_REG))]
2459 "TARGET_SH1 && can_create_pseudo_p ()"
2460 "#"
2461 "&& 1"
2462 [(const_int 0)]
2463 {
2464 sh_treg_insns ti = sh_split_treg_set_expr (operands[2], curr_insn);
2465 if (ti.remove_trailing_nott ())
2466 {
2467 /* op1 - (1 - T) + op3 = (op1 - 1) + op3 + T */
2468 rtx tmp = gen_reg_rtx (SImode);
2469 emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (-1)));
2470 emit_insn (gen_addc (operands[0], tmp, operands[3]));
2471 }
2472 else
2473 {
2474 /* (op1 - T) + op3' = 'op1 - (-op3) - T */
2475 rtx tmp = gen_reg_rtx (SImode);
2476 emit_insn (gen_negsi2 (tmp, operands[3]));
2477 emit_insn (gen_subc (operands[0], operands[1], tmp));
2478 }
2479 DONE;
2480 })
2481
2482 (define_insn "*subsi3_internal"
2483 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2484 (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
2485 (match_operand:SI 2 "arith_reg_operand" "r")))]
2486 "TARGET_SH1"
2487 "sub %2,%0"
2488 [(set_attr "type" "arith")])
2489
2490 (define_insn_and_split "*subsi3_media"
2491 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2492 (minus:SI (match_operand:SI 1 "minuend_operand" "rN")
2493 (match_operand:SI 2 "extend_reg_operand" "r")))]
2494 "TARGET_SHMEDIA
2495 && (operands[1] != constm1_rtx
2496 || (GET_CODE (operands[2]) != TRUNCATE
2497 && GET_CODE (operands[2]) != SUBREG))"
2498 "sub.l %N1, %2, %0"
2499 "operands[1] == constm1_rtx"
2500 [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))]
2501 ""
2502 [(set_attr "type" "arith_media")
2503 (set_attr "highpart" "ignore")])
2504
2505 (define_split
2506 [(set (match_operand:SI 0 "arith_reg_dest" "")
2507 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2508 "general_extend_operand"
2509 "") 0)) 0)))]
2510 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
2511 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2512 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2513 "")
2514
2515 (define_split
2516 [(set (match_operand:SI 0 "arith_reg_dest" "")
2517 (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
2518 "general_extend_operand"
2519 "") 0)) 3)))]
2520 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
2521 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
2522 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
2523 "")
2524
2525 ;; Convert
2526 ;; constant - reg
2527 ;; to
2528 ;; neg reg
2529 ;; add reg, #const
2530 ;; since this will sometimes save one instruction.
2531 ;; Otherwise we might get a sequence like
2532 ;; mov #const, rY
2533 ;; sub rY, rX
2534 ;; mov rX, rY
2535 ;; if the source and dest regs are the same.
2536 (define_expand "subsi3"
2537 [(set (match_operand:SI 0 "arith_reg_operand" "")
2538 (minus:SI (match_operand:SI 1 "arith_operand" "")
2539 (match_operand:SI 2 "arith_reg_operand" "")))]
2540 ""
2541 {
2542 if (TARGET_SH1 && CONST_INT_P (operands[1]))
2543 {
2544 emit_insn (gen_negsi2 (operands[0], operands[2]));
2545 emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
2546 DONE;
2547 }
2548 if (TARGET_SHMEDIA)
2549 {
2550 if (!can_create_pseudo_p ()
2551 && ! arith_reg_or_0_operand (operands[1], SImode))
2552 FAIL;
2553 if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
2554 operands[1] = force_reg (SImode, operands[1]);
2555 }
2556 })
2557 \f
2558 ;; -------------------------------------------------------------------------
2559 ;; Division instructions
2560 ;; -------------------------------------------------------------------------
2561
2562 ;; We take advantage of the library routines which don't clobber as many
2563 ;; registers as a normal function call would.
2564
2565 ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
2566 ;; also has an effect on the register that holds the address of the sfunc.
2567 ;; To make this work, we have an extra dummy insn that shows the use
2568 ;; of this register for reorg.
2569
2570 (define_insn "use_sfunc_addr"
2571 [(set (reg:SI PR_REG)
2572 (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
2573 "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])"
2574 ""
2575 [(set_attr "length" "0")])
2576
2577 (define_insn "udivsi3_sh2a"
2578 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2579 (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0")
2580 (match_operand:SI 2 "arith_reg_operand" "z")))]
2581 "TARGET_SH2A"
2582 "divu %2,%1"
2583 [(set_attr "type" "arith")
2584 (set_attr "in_delay_slot" "no")])
2585
2586 ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
2587 ;; hard register 0. If we used hard register 0, then the next instruction
2588 ;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg
2589 ;; gets allocated to a stack slot that needs its address reloaded, then
2590 ;; there is nothing to prevent reload from using r0 to reload the address.
2591 ;; This reload would clobber the value in r0 we are trying to store.
2592 ;; If we let reload allocate r0, then this problem can never happen.
2593 (define_insn "udivsi3_i1"
2594 [(set (match_operand:SI 0 "register_operand" "=z")
2595 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2596 (clobber (reg:SI T_REG))
2597 (clobber (reg:SI PR_REG))
2598 (clobber (reg:SI R1_REG))
2599 (clobber (reg:SI R4_REG))
2600 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2601 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2602 "jsr @%1%#"
2603 [(set_attr "type" "sfunc")
2604 (set_attr "needs_delay_slot" "yes")])
2605
2606 ; Since shmedia-nofpu code could be linked against shcompact code, and
2607 ; the udivsi3 libcall has the same name, we must consider all registers
2608 ; clobbered that are in the union of the registers clobbered by the
2609 ; shmedia and the shcompact implementation. Note, if the shcompact
2610 ; implementation actually used shcompact code, we'd need to clobber
2611 ; also r23 and fr23.
2612 (define_insn "udivsi3_i1_media"
2613 [(set (match_operand:SI 0 "register_operand" "=z")
2614 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2615 (clobber (reg:SI T_MEDIA_REG))
2616 (clobber (reg:SI PR_MEDIA_REG))
2617 (clobber (reg:SI R20_REG))
2618 (clobber (reg:SI R21_REG))
2619 (clobber (reg:SI R22_REG))
2620 (clobber (reg:DI TR0_REG))
2621 (clobber (reg:DI TR1_REG))
2622 (clobber (reg:DI TR2_REG))
2623 (use (match_operand 1 "target_reg_operand" "b"))]
2624 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2625 "blink %1, r18"
2626 [(set_attr "type" "sfunc")
2627 (set_attr "needs_delay_slot" "yes")])
2628
2629 (define_expand "udivsi3_i4_media"
2630 [(set (match_dup 3)
2631 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
2632 (set (match_dup 4)
2633 (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
2634 (set (match_dup 5) (float:DF (match_dup 3)))
2635 (set (match_dup 6) (float:DF (match_dup 4)))
2636 (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
2637 (set (match_dup 8) (fix:DI (match_dup 7)))
2638 (set (match_operand:SI 0 "register_operand" "")
2639 (truncate:SI (match_dup 8)))]
2640 "TARGET_SHMEDIA_FPU"
2641 {
2642 operands[3] = gen_reg_rtx (DImode);
2643 operands[4] = gen_reg_rtx (DImode);
2644 operands[5] = gen_reg_rtx (DFmode);
2645 operands[6] = gen_reg_rtx (DFmode);
2646 operands[7] = gen_reg_rtx (DFmode);
2647 operands[8] = gen_reg_rtx (DImode);
2648 })
2649
2650 (define_insn "udivsi3_i4"
2651 [(set (match_operand:SI 0 "register_operand" "=y")
2652 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2653 (clobber (reg:SI T_REG))
2654 (clobber (reg:SI PR_REG))
2655 (clobber (reg:DF DR0_REG))
2656 (clobber (reg:DF DR2_REG))
2657 (clobber (reg:DF DR4_REG))
2658 (clobber (reg:SI R0_REG))
2659 (clobber (reg:SI R1_REG))
2660 (clobber (reg:SI R4_REG))
2661 (clobber (reg:SI R5_REG))
2662 (clobber (reg:SI FPSCR_STAT_REG))
2663 (use (match_operand:SI 1 "arith_reg_operand" "r"))
2664 (use (reg:SI FPSCR_MODES_REG))]
2665 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2666 "jsr @%1%#"
2667 [(set_attr "type" "sfunc")
2668 (set_attr "fp_mode" "double")
2669 (set_attr "needs_delay_slot" "yes")])
2670
2671 (define_insn "udivsi3_i4_single"
2672 [(set (match_operand:SI 0 "register_operand" "=y")
2673 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2674 (clobber (reg:SI T_REG))
2675 (clobber (reg:SI PR_REG))
2676 (clobber (reg:DF DR0_REG))
2677 (clobber (reg:DF DR2_REG))
2678 (clobber (reg:DF DR4_REG))
2679 (clobber (reg:SI R0_REG))
2680 (clobber (reg:SI R1_REG))
2681 (clobber (reg:SI R4_REG))
2682 (clobber (reg:SI R5_REG))
2683 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2684 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2685 && TARGET_FPU_SINGLE"
2686 "jsr @%1%#"
2687 [(set_attr "type" "sfunc")
2688 (set_attr "needs_delay_slot" "yes")])
2689
2690 (define_insn "udivsi3_i4_int"
2691 [(set (match_operand:SI 0 "register_operand" "=z")
2692 (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2693 (clobber (reg:SI T_REG))
2694 (clobber (reg:SI R1_REG))
2695 (clobber (reg:SI PR_REG))
2696 (clobber (reg:SI MACH_REG))
2697 (clobber (reg:SI MACL_REG))
2698 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2699 "TARGET_SH1"
2700 "jsr @%1%#"
2701 [(set_attr "type" "sfunc")
2702 (set_attr "needs_delay_slot" "yes")])
2703
2704
2705 (define_expand "udivsi3"
2706 [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
2707 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2708 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2709 (parallel [(set (match_operand:SI 0 "register_operand" "")
2710 (udiv:SI (reg:SI R4_REG)
2711 (reg:SI R5_REG)))
2712 (clobber (reg:SI T_REG))
2713 (clobber (reg:SI PR_REG))
2714 (clobber (reg:SI R4_REG))
2715 (use (match_dup 3))])]
2716 ""
2717 {
2718 rtx last;
2719
2720 operands[3] = gen_reg_rtx (Pmode);
2721 /* Emit the move of the address to a pseudo outside of the libcall. */
2722 if (TARGET_DIVIDE_CALL_TABLE)
2723 {
2724 /* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
2725 that causes problems when the divide code is supposed to come from a
2726 separate library. Division by zero is undefined, so dividing 1 can be
2727 implemented by comparing with the divisor. */
2728 if (operands[1] == const1_rtx && currently_expanding_to_rtl)
2729 {
2730 rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
2731 emit_insn (gen_cstoresi4 (operands[0], test,
2732 operands[1], operands[2]));
2733 DONE;
2734 }
2735 else if (operands[2] == const0_rtx)
2736 {
2737 emit_move_insn (operands[0], operands[2]);
2738 DONE;
2739 }
2740 function_symbol (operands[3], "__udivsi3_i4i", SFUNC_GOT);
2741 last = gen_udivsi3_i4_int (operands[0], operands[3]);
2742 }
2743 else if (TARGET_DIVIDE_CALL_FP)
2744 {
2745 function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC);
2746 if (TARGET_FPU_SINGLE)
2747 last = gen_udivsi3_i4_single (operands[0], operands[3]);
2748 else
2749 last = gen_udivsi3_i4 (operands[0], operands[3]);
2750 }
2751 else if (TARGET_SHMEDIA_FPU)
2752 {
2753 operands[1] = force_reg (SImode, operands[1]);
2754 operands[2] = force_reg (SImode, operands[2]);
2755 emit_insn (gen_udivsi3_i4_media (operands[0], operands[1], operands[2]));
2756 DONE;
2757 }
2758 else if (TARGET_SH2A)
2759 {
2760 operands[1] = force_reg (SImode, operands[1]);
2761 operands[2] = force_reg (SImode, operands[2]);
2762 emit_insn (gen_udivsi3_sh2a (operands[0], operands[1], operands[2]));
2763 DONE;
2764 }
2765 else if (TARGET_SH5)
2766 {
2767 function_symbol (operands[3],
2768 TARGET_FPU_ANY ? "__udivsi3_i4" : "__udivsi3",
2769 SFUNC_STATIC);
2770
2771 if (TARGET_SHMEDIA)
2772 last = gen_udivsi3_i1_media (operands[0], operands[3]);
2773 else if (TARGET_FPU_ANY)
2774 last = gen_udivsi3_i4_single (operands[0], operands[3]);
2775 else
2776 last = gen_udivsi3_i1 (operands[0], operands[3]);
2777 }
2778 else
2779 {
2780 function_symbol (operands[3], "__udivsi3", SFUNC_STATIC);
2781 last = gen_udivsi3_i1 (operands[0], operands[3]);
2782 }
2783 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
2784 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
2785 emit_insn (last);
2786 DONE;
2787 })
2788
2789 (define_insn "divsi3_sh2a"
2790 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
2791 (div:SI (match_operand:SI 1 "arith_reg_operand" "0")
2792 (match_operand:SI 2 "arith_reg_operand" "z")))]
2793 "TARGET_SH2A"
2794 "divs %2,%1"
2795 [(set_attr "type" "arith")
2796 (set_attr "in_delay_slot" "no")])
2797
2798 (define_insn "divsi3_i1"
2799 [(set (match_operand:SI 0 "register_operand" "=z")
2800 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2801 (clobber (reg:SI T_REG))
2802 (clobber (reg:SI PR_REG))
2803 (clobber (reg:SI R1_REG))
2804 (clobber (reg:SI R2_REG))
2805 (clobber (reg:SI R3_REG))
2806 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2807 "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
2808 "jsr @%1%#"
2809 [(set_attr "type" "sfunc")
2810 (set_attr "needs_delay_slot" "yes")])
2811
2812 (define_insn "divsi3_i1_media"
2813 [(set (match_operand:SI 0 "register_operand" "=z")
2814 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2815 (clobber (reg:SI T_MEDIA_REG))
2816 (clobber (reg:SI PR_MEDIA_REG))
2817 (clobber (reg:SI R1_REG))
2818 (clobber (reg:SI R20_REG))
2819 (clobber (reg:SI R21_REG))
2820 (clobber (reg:SI TR0_REG))
2821 (use (match_operand 1 "target_reg_operand" "b"))]
2822 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2823 "blink %1, r18"
2824 [(set_attr "type" "sfunc")])
2825
2826 (define_insn "divsi3_media_2"
2827 [(set (match_operand:SI 0 "register_operand" "=z")
2828 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2829 (clobber (reg:SI T_MEDIA_REG))
2830 (clobber (reg:SI PR_MEDIA_REG))
2831 (clobber (reg:SI R1_REG))
2832 (clobber (reg:SI R21_REG))
2833 (clobber (reg:SI TR0_REG))
2834 (use (reg:SI R20_REG))
2835 (use (match_operand 1 "target_reg_operand" "b"))]
2836 "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
2837 "blink %1, r18"
2838 [(set_attr "type" "sfunc")])
2839
2840 ;; This pattern acts as a placeholder for -mdiv=inv:call to carry
2841 ;; hard reg clobbers and data dependencies that we need when we want
2842 ;; to rematerialize the division into a call.
2843 (define_insn_and_split "divsi_inv_call"
2844 [(set (match_operand:SI 0 "register_operand" "=r")
2845 (div:SI (match_operand:SI 1 "register_operand" "r")
2846 (match_operand:SI 2 "register_operand" "r")))
2847 (clobber (reg:SI R4_REG))
2848 (clobber (reg:SI R5_REG))
2849 (clobber (reg:SI T_MEDIA_REG))
2850 (clobber (reg:SI PR_MEDIA_REG))
2851 (clobber (reg:SI R1_REG))
2852 (clobber (reg:SI R21_REG))
2853 (clobber (reg:SI TR0_REG))
2854 (clobber (reg:SI R20_REG))
2855 (use (match_operand:SI 3 "register_operand" "r"))]
2856 "TARGET_SHMEDIA"
2857 "#"
2858 "&& (reload_in_progress || reload_completed)"
2859 [(set (match_dup 0) (match_dup 3))]
2860 ""
2861 [(set_attr "highpart" "must_split")])
2862
2863 ;; This is the combiner pattern for -mdiv=inv:call .
2864 (define_insn_and_split "*divsi_inv_call_combine"
2865 [(set (match_operand:SI 0 "register_operand" "=z")
2866 (div:SI (match_operand:SI 1 "register_operand" "r")
2867 (match_operand:SI 2 "register_operand" "r")))
2868 (clobber (reg:SI R4_REG))
2869 (clobber (reg:SI R5_REG))
2870 (clobber (reg:SI T_MEDIA_REG))
2871 (clobber (reg:SI PR_MEDIA_REG))
2872 (clobber (reg:SI R1_REG))
2873 (clobber (reg:SI R21_REG))
2874 (clobber (reg:SI TR0_REG))
2875 (clobber (reg:SI R20_REG))
2876 (use (unspec:SI [(match_dup 1)
2877 (match_operand:SI 3 "" "")
2878 (unspec:SI [(match_operand:SI 4 "" "")
2879 (match_dup 3)
2880 (match_operand:DI 5 "" "")]
2881 UNSPEC_DIV_INV_M2)
2882 (match_operand:DI 6 "" "")
2883 (const_int 0)
2884 (const_int 0)]
2885 UNSPEC_DIV_INV_M3))]
2886 "TARGET_SHMEDIA"
2887 "#"
2888 "&& (reload_in_progress || reload_completed)"
2889 [(pc)]
2890 {
2891 const char *name = sh_divsi3_libfunc;
2892 enum sh_function_kind kind = SFUNC_GOT;
2893 rtx sym;
2894
2895 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
2896 emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]);
2897 while (TARGET_DIVIDE_INV_CALL2)
2898 {
2899 rtx x = operands[3];
2900
2901 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1)
2902 break;
2903 x = XVECEXP (x, 0, 0);
2904 name = "__sdivsi3_2";
2905 kind = SFUNC_STATIC;
2906 emit_move_insn (gen_rtx_REG (DImode, R20_REG), x);
2907 break;
2908 }
2909 sym = function_symbol (NULL, name, kind);
2910 emit_insn (gen_divsi3_media_2 (operands[0], sym));
2911 DONE;
2912 }
2913 [(set_attr "highpart" "must_split")])
2914
2915 (define_expand "divsi3_i4_media"
2916 [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r")))
2917 (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r")))
2918 (set (match_dup 5) (div:DF (match_dup 3) (match_dup 4)))
2919 (set (match_operand:SI 0 "register_operand" "=r")
2920 (fix:SI (match_dup 5)))]
2921 "TARGET_SHMEDIA_FPU"
2922 {
2923 operands[3] = gen_reg_rtx (DFmode);
2924 operands[4] = gen_reg_rtx (DFmode);
2925 operands[5] = gen_reg_rtx (DFmode);
2926 })
2927
2928 (define_insn "divsi3_i4"
2929 [(set (match_operand:SI 0 "register_operand" "=y")
2930 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2931 (clobber (reg:SI PR_REG))
2932 (clobber (reg:DF DR0_REG))
2933 (clobber (reg:DF DR2_REG))
2934 (clobber (reg:SI FPSCR_STAT_REG))
2935 (use (match_operand:SI 1 "arith_reg_operand" "r"))
2936 (use (reg:SI FPSCR_MODES_REG))]
2937 "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
2938 "jsr @%1%#"
2939 [(set_attr "type" "sfunc")
2940 (set_attr "fp_mode" "double")
2941 (set_attr "needs_delay_slot" "yes")])
2942
2943 (define_insn "divsi3_i4_single"
2944 [(set (match_operand:SI 0 "register_operand" "=y")
2945 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2946 (clobber (reg:SI PR_REG))
2947 (clobber (reg:DF DR0_REG))
2948 (clobber (reg:DF DR2_REG))
2949 (clobber (reg:SI R2_REG))
2950 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2951 "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT)
2952 && TARGET_FPU_SINGLE"
2953 "jsr @%1%#"
2954 [(set_attr "type" "sfunc")
2955 (set_attr "needs_delay_slot" "yes")])
2956
2957 (define_insn "divsi3_i4_int"
2958 [(set (match_operand:SI 0 "register_operand" "=z")
2959 (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
2960 (clobber (reg:SI T_REG))
2961 (clobber (reg:SI PR_REG))
2962 (clobber (reg:SI R1_REG))
2963 (clobber (reg:SI MACH_REG))
2964 (clobber (reg:SI MACL_REG))
2965 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
2966 "TARGET_SH1"
2967 "jsr @%1%#"
2968 [(set_attr "type" "sfunc")
2969 (set_attr "needs_delay_slot" "yes")])
2970
2971 (define_expand "divsi3"
2972 [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
2973 (set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
2974 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
2975 (parallel [(set (match_operand:SI 0 "register_operand" "")
2976 (div:SI (reg:SI R4_REG)
2977 (reg:SI R5_REG)))
2978 (clobber (reg:SI T_REG))
2979 (clobber (reg:SI PR_REG))
2980 (clobber (reg:SI R1_REG))
2981 (clobber (reg:SI R2_REG))
2982 (clobber (reg:SI R3_REG))
2983 (use (match_dup 3))])]
2984 ""
2985 {
2986 rtx last;
2987
2988 operands[3] = gen_reg_rtx (Pmode);
2989 /* Emit the move of the address to a pseudo outside of the libcall. */
2990 if (TARGET_DIVIDE_CALL_TABLE)
2991 {
2992 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
2993 last = gen_divsi3_i4_int (operands[0], operands[3]);
2994 }
2995 else if (TARGET_DIVIDE_CALL_FP)
2996 {
2997 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
2998 if (TARGET_FPU_SINGLE)
2999 last = gen_divsi3_i4_single (operands[0], operands[3]);
3000 else
3001 last = gen_divsi3_i4 (operands[0], operands[3]);
3002 }
3003 else if (TARGET_SH2A)
3004 {
3005 operands[1] = force_reg (SImode, operands[1]);
3006 operands[2] = force_reg (SImode, operands[2]);
3007 emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2]));
3008 DONE;
3009 }
3010 else if (TARGET_DIVIDE_INV)
3011 {
3012 rtx dividend = operands[1];
3013 rtx divisor = operands[2];
3014 rtx tab_base;
3015 rtx nsb_res = gen_reg_rtx (DImode);
3016 rtx norm64 = gen_reg_rtx (DImode);
3017 rtx tab_ix = gen_reg_rtx (DImode);
3018 rtx norm32 = gen_reg_rtx (SImode);
3019 rtx i92 = force_reg (DImode, GEN_INT (92));
3020 rtx scratch0a = gen_reg_rtx (DImode);
3021 rtx scratch0b = gen_reg_rtx (DImode);
3022 rtx inv0 = gen_reg_rtx (SImode);
3023 rtx scratch1a = gen_reg_rtx (DImode);
3024 rtx scratch1b = gen_reg_rtx (DImode);
3025 rtx shift = gen_reg_rtx (DImode);
3026 rtx i2p27, i43;
3027 rtx inv1 = gen_reg_rtx (SImode);
3028 rtx scratch2a = gen_reg_rtx (DImode);
3029 rtx scratch2b = gen_reg_rtx (SImode);
3030 rtx inv2 = gen_reg_rtx (SImode);
3031 rtx scratch3a = gen_reg_rtx (DImode);
3032 rtx scratch3b = gen_reg_rtx (DImode);
3033 rtx scratch3c = gen_reg_rtx (DImode);
3034 rtx scratch3d = gen_reg_rtx (SImode);
3035 rtx scratch3e = gen_reg_rtx (DImode);
3036 rtx result = gen_reg_rtx (SImode);
3037
3038 if (! arith_reg_or_0_operand (dividend, SImode))
3039 dividend = force_reg (SImode, dividend);
3040 if (! arith_reg_operand (divisor, SImode))
3041 divisor = force_reg (SImode, divisor);
3042 if (flag_pic && Pmode != DImode)
3043 {
3044 tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
3045 tab_base = gen_datalabel_ref (tab_base);
3046 tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base));
3047 }
3048 else
3049 {
3050 tab_base = gen_rtx_SYMBOL_REF (DImode, "__div_table");
3051 tab_base = gen_datalabel_ref (tab_base);
3052 tab_base = force_reg (DImode, tab_base);
3053 }
3054 if (TARGET_DIVIDE_INV20U)
3055 i2p27 = force_reg (DImode, GEN_INT ((unsigned HOST_WIDE_INT)-2 << 27));
3056 else
3057 i2p27 = GEN_INT (0);
3058 if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)
3059 i43 = force_reg (DImode, GEN_INT (43));
3060 else
3061 i43 = GEN_INT (0);
3062 emit_insn (gen_nsbdi (nsb_res,
3063 simplify_gen_subreg (DImode, divisor, SImode, 0)));
3064 emit_insn (gen_ashldi3_media (norm64,
3065 gen_rtx_SUBREG (DImode, divisor, 0),
3066 nsb_res));
3067 emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58)));
3068 emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32)));
3069 emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32,
3070 inv0, scratch0a, scratch0b,
3071 scratch1a, scratch1b));
3072 emit_insn (gen_subdi3 (shift, i92, nsb_res));
3073 emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92,
3074 scratch2a));
3075 emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift,
3076 i2p27, i43,
3077 scratch3a, scratch3b, scratch3c,
3078 scratch2a, scratch2b, scratch3d, scratch3e));
3079 if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2)
3080 emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result));
3081 else if (TARGET_DIVIDE_INV_FP)
3082 emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result,
3083 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
3084 gen_reg_rtx (DFmode), gen_reg_rtx (DFmode),
3085 gen_reg_rtx (DFmode)));
3086 else
3087 emit_move_insn (operands[0], result);
3088 DONE;
3089 }
3090 else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP)
3091 {
3092 operands[1] = force_reg (SImode, operands[1]);
3093 operands[2] = force_reg (SImode, operands[2]);
3094 emit_insn (gen_divsi3_i4_media (operands[0], operands[1], operands[2]));
3095 DONE;
3096 }
3097 else if (TARGET_SH5)
3098 {
3099 if (TARGET_DIVIDE_CALL2)
3100 {
3101 rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, "__div_table");
3102 tab_base = gen_datalabel_ref (tab_base);
3103 emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base);
3104 }
3105 if (TARGET_FPU_ANY && TARGET_SH1)
3106 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC);
3107 else if (TARGET_DIVIDE_CALL2)
3108 function_symbol (operands[3], "__sdivsi3_2", SFUNC_STATIC);
3109 else
3110 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
3111
3112 if (TARGET_SHMEDIA)
3113 last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media)
3114 (operands[0], operands[3]));
3115 else if (TARGET_FPU_ANY)
3116 last = gen_divsi3_i4_single (operands[0], operands[3]);
3117 else
3118 last = gen_divsi3_i1 (operands[0], operands[3]);
3119 }
3120 else
3121 {
3122 function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
3123 last = gen_divsi3_i1 (operands[0], operands[3]);
3124 }
3125 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
3126 emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
3127 emit_insn (last);
3128 DONE;
3129 })
3130
3131 ;; operands: scratch, tab_base, tab_ix
3132 ;; These are unspecs because we could generate an indexed addressing mode
3133 ;; even if -m5-32media, where INDEX_REG_CLASS == NO_REGS, and this would
3134 ;; confuse reload. See PR27117.
3135 (define_insn "divsi_inv_qitable"
3136 [(set (match_operand:DI 0 "register_operand" "=r")
3137 (zero_extend:DI (unspec:QI [(match_operand:DI 1 "register_operand" "r")
3138 (match_operand:DI 2 "register_operand" "r")]
3139 UNSPEC_DIV_INV_TABLE)))]
3140 "TARGET_SHMEDIA"
3141 "ldx.ub %1, %2, %0"
3142 [(set_attr "type" "load_media")
3143 (set_attr "highpart" "user")])
3144
3145 ;; operands: scratch, tab_base, tab_ix
3146 (define_insn "divsi_inv_hitable"
3147 [(set (match_operand:DI 0 "register_operand" "=r")
3148 (sign_extend:DI (unspec:HI [(match_operand:DI 1 "register_operand" "r")
3149 (match_operand:DI 2 "register_operand" "r")]
3150 UNSPEC_DIV_INV_TABLE)))]
3151 "TARGET_SHMEDIA"
3152 "ldx.w %1, %2, %0"
3153 [(set_attr "type" "load_media")
3154 (set_attr "highpart" "user")])
3155
3156 ;; operands: inv0, tab_base, tab_ix, norm32
3157 ;; scratch equiv in sdivsi3_2: r19, r21
3158 (define_expand "divsi_inv_m0"
3159 [(set (match_operand:SI 0 "register_operand" "=r")
3160 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
3161 (match_operand:DI 2 "register_operand" "r")
3162 (match_operand:SI 3 "register_operand" "r")]
3163 UNSPEC_DIV_INV_M0))
3164 (clobber (match_operand:DI 4 "register_operand" "=r"))
3165 (clobber (match_operand:DI 5 "register_operand" "=r"))]
3166 "TARGET_SHMEDIA"
3167 {
3168 /*
3169 tab_base: r20
3170 tab_ix: r21
3171 norm32: r25
3172 ldx.ub r20, r21, r19 // u0.8
3173 shlli r21, 1, r21
3174 muls.l r25, r19, r19 // s2.38
3175 ldx.w r20, r21, r21 // s2.14
3176 shari r19, 24, r19 // truncate to s2.14
3177 sub r21, r19, r19 // some 11 bit inverse in s1.14
3178 */
3179
3180 rtx inv0 = operands[0];
3181 rtx tab_base = operands[1];
3182 rtx tab_ix = operands[2];
3183 rtx norm32 = operands[3];
3184 rtx scratch0 = operands[4];
3185 rtx scratch0_si = gen_lowpart (SImode, scratch0);
3186 rtx scratch1 = operands[5];
3187
3188 emit_insn (gen_divsi_inv_qitable (scratch0, tab_base, tab_ix));
3189 emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1)));
3190 emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si));
3191 emit_insn (gen_divsi_inv_hitable (scratch1, tab_base, scratch1));
3192 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24)));
3193 emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0));
3194 DONE;
3195 })
3196
3197 ;; operands: inv1, tab_base, tab_ix, norm32
3198 (define_insn_and_split "divsi_inv_m1"
3199 [(set (match_operand:SI 0 "register_operand" "=r")
3200 (unspec:SI [(match_operand:DI 1 "register_operand" "r")
3201 (match_operand:DI 2 "register_operand" "r")
3202 (match_operand:SI 3 "register_operand" "r")]
3203 UNSPEC_DIV_INV_M1))
3204 (clobber (match_operand:SI 4 "register_operand" "=r"))
3205 (clobber (match_operand:DI 5 "register_operand" "=r"))
3206 (clobber (match_operand:DI 6 "register_operand" "=r"))
3207 (clobber (match_operand:DI 7 "register_operand" "=r"))
3208 (clobber (match_operand:DI 8 "register_operand" "=r"))]
3209 "TARGET_SHMEDIA"
3210 "#"
3211 "&& !can_create_pseudo_p ()"
3212 [(pc)]
3213 {
3214 /* inv0: r19
3215 muls.l r19, r19, r18 // u0.28
3216 muls.l r25, r18, r18 // s2.58
3217 shlli r19, 45, r0 // multiply by two and convert to s2.58
3218 sub r0, r18, r18
3219 shari r18, 28, r18 // some 18 bit inverse in s1.30
3220 */
3221
3222 rtx inv1 = operands[0];
3223 rtx tab_base = operands[1];
3224 rtx tab_ix = operands[2];
3225 rtx norm32 = operands[3];
3226 rtx inv0 = operands[4];
3227 rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0);
3228 rtx scratch0a = operands[5];
3229 rtx scratch0b = operands[6];
3230 rtx scratch0 = operands[7];
3231 rtx scratch1 = operands[8];
3232 rtx scratch1_si = gen_lowpart (SImode, scratch1);
3233
3234 emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32,
3235 scratch0a, scratch0b));
3236 emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0));
3237 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3238 emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45)));
3239 emit_insn (gen_subdi3 (scratch1, scratch0, scratch1));
3240 emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28)));
3241 DONE;
3242 })
3243
3244 ;; operands: inv2, norm32, inv1, i92
3245 (define_insn_and_split "divsi_inv_m2"
3246 [(set (match_operand:SI 0 "register_operand" "=r")
3247 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3248 (match_operand:SI 2 "register_operand" "r")
3249 (match_operand:DI 3 "register_operand" "r")]
3250 UNSPEC_DIV_INV_M2))
3251 (clobber (match_operand:DI 4 "register_operand" "=r"))]
3252 "TARGET_SHMEDIA"
3253 "#"
3254 "&& !can_create_pseudo_p ()"
3255 [(pc)]
3256 {
3257 /*
3258 muls.l r18, r25, r0 // s2.60
3259 shari r0, 16, r0 // s-16.44
3260 sub
3261 muls.l r0, r18, r19 // s-16.74
3262 shari r19, 30, r19 // s-16.44
3263 */
3264 rtx inv2 = operands[0];
3265 rtx norm32 = operands[1];
3266 rtx inv1 = operands[2];
3267 rtx i92 = operands[3];
3268 rtx scratch0 = operands[4];
3269 rtx scratch0_si = gen_lowpart (SImode, scratch0);
3270
3271 emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32));
3272 emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16)));
3273 emit_insn (gen_subdi3 (scratch0, i92, scratch0));
3274 emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1));
3275 emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30)));
3276 DONE;
3277 })
3278
3279 (define_insn_and_split "divsi_inv_m3"
3280 [(set (match_operand:SI 0 "register_operand" "=r")
3281 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3282 (match_operand:SI 2 "register_operand" "r")
3283 (match_operand:SI 3 "register_operand" "r")
3284 (match_operand:DI 4 "register_operand" "r")
3285 (match_operand:DI 5 "arith_reg_or_0_operand" "rN")
3286 (match_operand:DI 6 "arith_reg_or_0_operand" "rN")]
3287 UNSPEC_DIV_INV_M3))
3288 (clobber (match_operand:DI 7 "register_operand" "=r"))
3289 (clobber (match_operand:DI 8 "register_operand" "=r"))
3290 (clobber (match_operand:DI 9 "register_operand" "=r"))
3291 (clobber (match_operand:DI 10 "register_operand" "=r"))
3292 (clobber (match_operand:SI 11 "register_operand" "=r"))
3293 (clobber (match_operand:SI 12 "register_operand" "=r"))
3294 (clobber (match_operand:DI 13 "register_operand" "=r"))]
3295 "TARGET_SHMEDIA"
3296 "#"
3297 "&& !can_create_pseudo_p ()"
3298 [(pc)]
3299 {
3300 /*
3301 r0: result r1: shift r4: dividend r18: inv1 r19: inv2
3302 r0: scratch0 r19: scratch1 r21: scratch2
3303
3304 muls.l r18, r4, r25 // s32.30
3305 muls.l r19, r4, r19 // s15.30
3306 shari r25, 63, r21
3307 shari r19, 14, r19 // s18.-14
3308 sub r25, r19, r0
3309 shard r0, r1, r0
3310 sub r0, r21, r0
3311 */
3312
3313 rtx result = operands[0];
3314 rtx dividend = operands[1];
3315 rtx inv1 = operands[2];
3316 rtx inv2 = operands[3];
3317 rtx shift = operands[4];
3318 rtx scratch0 = operands[7];
3319 rtx scratch1 = operands[8];
3320 rtx scratch2 = operands[9];
3321
3322 if (satisfies_constraint_N (dividend))
3323 {
3324 emit_move_insn (result, dividend);
3325 DONE;
3326 }
3327
3328 emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
3329 emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
3330 emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
3331 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14)));
3332 emit_insn (gen_adddi3 (scratch0, scratch0, scratch1));
3333 emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift));
3334 emit_insn (gen_subdisi3_media (result, scratch0, scratch2));
3335 DONE;
3336 })
3337
3338 ;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43
3339 ;; inv1: tab_base, tab_ix, norm32
3340 ;; inv2: norm32, inv1, i92
3341 (define_insn_and_split "divsi_inv_m1_3"
3342 [(set (match_operand:SI 0 "register_operand" "=r")
3343 (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
3344 (unspec:SI [(match_operand:DI 2 "register_operand" "r")
3345 (match_operand:DI 3 "register_operand" "r")
3346 (match_operand:SI 4 "register_operand" "r")]
3347 UNSPEC_DIV_INV_M1)
3348 (unspec:SI [(match_dup 4)
3349 (unspec:SI [(match_dup 2)
3350 (match_dup 3)
3351 (match_dup 4)] UNSPEC_DIV_INV_M1)
3352 (match_operand:SI 5 "" "")]
3353 UNSPEC_DIV_INV_M2)
3354 (match_operand:DI 6 "register_operand" "r")
3355 (match_operand:DI 7 "arith_reg_or_0_operand" "rN")
3356 (match_operand:DI 8 "arith_reg_or_0_operand" "rN")]
3357 UNSPEC_DIV_INV_M3))
3358 (clobber (match_operand:DI 9 "register_operand" "=r"))
3359 (clobber (match_operand:DI 10 "register_operand" "=r"))
3360 (clobber (match_operand:DI 11 "register_operand" "=r"))
3361 (clobber (match_operand:DI 12 "register_operand" "=r"))
3362 (clobber (match_operand:SI 13 "register_operand" "=r"))
3363 (clobber (match_operand:SI 14 "register_operand" "=r"))
3364 (clobber (match_operand:DI 15 "register_operand" "=r"))]
3365 "TARGET_SHMEDIA
3366 && (TARGET_DIVIDE_INV_MINLAT
3367 || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3368 "#"
3369 "&& !can_create_pseudo_p ()"
3370 [(pc)]
3371 {
3372 rtx result = operands[0];
3373 rtx dividend = operands[1];
3374 rtx tab_base = operands[2];
3375 rtx tab_ix = operands[3];
3376 rtx norm32 = operands[4];
3377 /* rtx i92 = operands[5]; */
3378 rtx shift = operands[6];
3379 rtx i2p27 = operands[7];
3380 rtx i43 = operands[8];
3381 rtx scratch0 = operands[9];
3382 rtx scratch0_si = gen_lowpart (SImode, scratch0);
3383 rtx scratch1 = operands[10];
3384 rtx scratch1_si = gen_lowpart (SImode, scratch1);
3385 rtx scratch2 = operands[11];
3386 rtx scratch3 = operands[12];
3387 rtx scratch4 = operands[13];
3388 rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0);
3389 rtx scratch5 = operands[14];
3390 rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0);
3391 rtx scratch6 = operands[15];
3392
3393 emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32,
3394 scratch0, scratch1));
3395 /* inv0 == scratch4 */
3396 if (! TARGET_DIVIDE_INV20U)
3397 {
3398 emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4));
3399 i2p27 = scratch0;
3400 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si));
3401 }
3402 else
3403 {
3404 emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4));
3405 emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si));
3406 }
3407 emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45)));
3408 emit_insn (gen_subdi3 (scratch1, scratch2, scratch1));
3409 emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28)));
3410 /* inv1 == scratch4 */
3411
3412 if (TARGET_DIVIDE_INV_MINLAT)
3413 {
3414 emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32));
3415 emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4));
3416 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16)));
3417 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4));
3418 emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63)));
3419 emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14)));
3420 emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30)));
3421 emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5));
3422 emit_insn (gen_xordi3 (scratch0, scratch3, i2p27));
3423 emit_insn (gen_adddi3 (scratch2, scratch2, scratch0));
3424 emit_insn (gen_subdi3 (scratch2, scratch2, scratch1));
3425 }
3426 else
3427 {
3428 rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
3429 /* Use separate scratch regs for nsb and sign to allow scheduling. */
3430 emit_insn (gen_nsbdi (scratch6,
3431 simplify_gen_subreg (DImode, dividend, SImode, 0)));
3432 emit_insn (gen_xorsi3 (scratch5, dividend, norm32));
3433 emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63)));
3434 emit_insn (gen_divsi_inv20 (scratch2,
3435 norm32, scratch4, dividend,
3436 scratch6, scratch3, i43,
3437 /* scratch0 may be shared with i2p27. */
3438 scratch0, scratch1, scratch5,
3439 label, label, i2p27));
3440 }
3441 emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift));
3442 emit_insn (gen_subdisi3_media (result, scratch2, scratch3));
3443 DONE;
3444 })
3445
3446 (define_insn "divsi_inv20"
3447 [(set (match_operand:DI 0 "register_operand" "=&r")
3448 (unspec:DI [(match_operand:SI 1 "register_operand" "r")
3449 (match_operand:SI 2 "register_operand" "r")
3450 (match_operand:SI 3 "register_operand" "r")
3451 (match_operand:DI 4 "register_operand" "r")
3452 (match_operand:DI 5 "register_operand" "r")
3453 (match_operand:DI 6 "register_operand" "r")
3454 (match_operand:DI 12 "register_operand" "r")
3455 (match_operand 10 "target_operand" "b")
3456 (match_operand 11 "immediate_operand" "i")]
3457 UNSPEC_DIV_INV20))
3458 (clobber (match_operand:DI 7 "register_operand" "=&r"))
3459 (clobber (match_operand:DI 8 "register_operand" "=&r"))
3460 (clobber (match_operand:SI 9 "register_operand" "=r"))]
3461 "TARGET_SHMEDIA
3462 && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
3463 {
3464 /* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend,
3465 %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27,
3466 %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si)
3467 %10 label (tr), %11 label (imm)
3468
3469 muls.l inv1, norm32, scratch0 // s2.60
3470 muls.l inv1, dividend, result // s32.30
3471 xor i2p27, result_sign, round_scratch
3472 bge/u dividend_nsb, i43, tr.. (label)
3473 shari scratch0, 16, scratch0 // s-16.44
3474 muls.l sratch0_si, inv1, scratch0 // s-16.74
3475 sub result, round_scratch, result
3476 shari dividend, 14, scratch1 // s19.-14
3477 shari scratch0, 30, scratch0 // s-16.44
3478 muls.l scratch0, scratch1, round_scratch // s15.30
3479 label:
3480 sub result, round_scratch, result */
3481
3482 const bool likely = TARGET_DIVIDE_INV20L;
3483 if (likely)
3484 return
3485 "muls.l %2, %3, %0" "\n"
3486 " xor %12, %5, %7" "\n"
3487 " bge/l %4, %6, %10" "\n"
3488 " muls.l %2, %1, %8" "\n"
3489 " shari %8, 16, %8" "\n"
3490 " muls.l %8, %2, %8" "\n"
3491 " shari %3, 14, %9" "\n"
3492 " shari %8, 30, %8" "\n"
3493 " muls.l %8, %9, %8" "\n"
3494 " sub %0, %8, %0" "\n"
3495 "%11: add %0, %7, %0";
3496 else
3497 return
3498 "muls.l %2, %1, %8" "\n"
3499 " muls.l %2, %3, %0" "\n"
3500 " xor %12, %5, %7" "\n"
3501 " bge/u %4, %6, %10" "\n"
3502 " shari %8, 16, %8" "\n"
3503 " muls.l %8, %2, %8" "\n"
3504 " sub %0, %7, %0" "\n"
3505 " shari %3, 14, %9" "\n"
3506 " shari %8, 30, %8" "\n"
3507 " muls.l %8, %9, %7" "\n"
3508 "%11: sub %0, %7, %0";
3509 })
3510
3511 (define_insn_and_split "divsi_inv_fp"
3512 [(set (match_operand:SI 0 "general_movdst_operand" "=rf")
3513 (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf")
3514 (match_operand:SI 2 "register_operand" "rf")))
3515 (use (match_operand:SI 3 "general_movsrc_operand" "r"))
3516 (clobber (match_operand:SI 4 "register_operand" "=r"))
3517 (clobber (match_operand:SI 5 "register_operand" "=r"))
3518 (clobber (match_operand:DF 6 "register_operand" "=r"))
3519 (clobber (match_operand:DF 7 "register_operand" "=r"))
3520 (clobber (match_operand:DF 8 "register_operand" "=r"))]
3521 "TARGET_SHMEDIA_FPU"
3522 "#"
3523 "&& (reload_in_progress || reload_completed)"
3524 [(set (match_dup 0) (match_dup 3))]
3525 ""
3526 [(set_attr "highpart" "must_split")])
3527
3528 ;; If a matching group of divide-by-inverse instructions is in the same
3529 ;; basic block after gcse & loop optimizations, we want to transform them
3530 ;; to a straight division using floating point for TARGET_DIVIDE_INV_FP.
3531 (define_insn_and_split "*divsi_inv_fp_combine"
3532 [(set (match_operand:SI 0 "register_operand" "=f")
3533 (div:SI (match_operand:SI 1 "register_operand" "f")
3534 (match_operand:SI 2 "register_operand" "f")))
3535 (use (unspec:SI [(match_dup 1)
3536 (match_operand:SI 3 "" "")
3537 (unspec:SI [(match_operand:SI 4 "" "")
3538 (match_dup 3)
3539 (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2)
3540 (match_operand:DI 6 "" "")
3541 (const_int 0)
3542 (const_int 0)] UNSPEC_DIV_INV_M3))
3543 (clobber (match_operand:SI 7 "fp_arith_reg_operand" ""))
3544 (clobber (match_operand:SI 8 "fp_arith_reg_operand" ""))
3545 (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
3546 (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
3547 (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
3548 "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
3549 "#"
3550 "&& 1"
3551 [(set (match_dup 9) (float:DF (match_dup 1)))
3552 (set (match_dup 10) (float:DF (match_dup 2)))
3553 (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10)))
3554 (set (match_dup 8)
3555 (fix:SI (match_dup 11)))
3556 (set (match_dup 0) (match_dup 8))]
3557 {
3558 if (! fp_arith_reg_operand (operands[1], SImode))
3559 {
3560 emit_move_insn (operands[7], operands[1]);
3561 operands[1] = operands[7];
3562 }
3563 if (! fp_arith_reg_operand (operands[2], SImode))
3564 {
3565 emit_move_insn (operands[8], operands[2]);
3566 operands[2] = operands[8];
3567 }
3568 }
3569 [(set_attr "highpart" "must_split")])
3570 \f
3571 ;; -------------------------------------------------------------------------
3572 ;; Multiplication instructions
3573 ;; -------------------------------------------------------------------------
3574
3575 (define_insn "umulhisi3_i"
3576 [(set (reg:SI MACL_REG)
3577 (mult:SI (zero_extend:SI
3578 (match_operand:HI 0 "arith_reg_operand" "r"))
3579 (zero_extend:SI
3580 (match_operand:HI 1 "arith_reg_operand" "r"))))]
3581 "TARGET_SH1"
3582 "mulu.w %1,%0"
3583 [(set_attr "type" "smpy")])
3584
3585 (define_insn "mulhisi3_i"
3586 [(set (reg:SI MACL_REG)
3587 (mult:SI (sign_extend:SI
3588 (match_operand:HI 0 "arith_reg_operand" "r"))
3589 (sign_extend:SI
3590 (match_operand:HI 1 "arith_reg_operand" "r"))))]
3591 "TARGET_SH1"
3592 "muls.w %1,%0"
3593 [(set_attr "type" "smpy")])
3594
3595 (define_expand "mulhisi3"
3596 [(set (reg:SI MACL_REG)
3597 (mult:SI (sign_extend:SI
3598 (match_operand:HI 1 "arith_reg_operand" ""))
3599 (sign_extend:SI
3600 (match_operand:HI 2 "arith_reg_operand" ""))))
3601 (set (match_operand:SI 0 "arith_reg_operand" "")
3602 (reg:SI MACL_REG))]
3603 "TARGET_SH1"
3604 {
3605 rtx_insn *insn;
3606 rtx macl;
3607
3608 macl = gen_rtx_REG (SImode, MACL_REG);
3609 start_sequence ();
3610 emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
3611 insn = get_insns ();
3612 end_sequence ();
3613 /* expand_binop can't find a suitable code in umul_widen_optab to
3614 make a REG_EQUAL note from, so make one here.
3615 See also smulsi3_highpart.
3616 ??? Alternatively, we could put this at the calling site of expand_binop,
3617 i.e. expand_expr. */
3618 /* Use emit_libcall_block for loop invariant code motion and to make
3619 a REG_EQUAL note. */
3620 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3621
3622 DONE;
3623 })
3624
3625 (define_expand "umulhisi3"
3626 [(set (reg:SI MACL_REG)
3627 (mult:SI (zero_extend:SI
3628 (match_operand:HI 1 "arith_reg_operand" ""))
3629 (zero_extend:SI
3630 (match_operand:HI 2 "arith_reg_operand" ""))))
3631 (set (match_operand:SI 0 "arith_reg_operand" "")
3632 (reg:SI MACL_REG))]
3633 "TARGET_SH1"
3634 {
3635 rtx_insn *insn;
3636 rtx macl;
3637
3638 macl = gen_rtx_REG (SImode, MACL_REG);
3639 start_sequence ();
3640 emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
3641 insn = get_insns ();
3642 end_sequence ();
3643 /* expand_binop can't find a suitable code in umul_widen_optab to
3644 make a REG_EQUAL note from, so make one here.
3645 See also smulsi3_highpart.
3646 ??? Alternatively, we could put this at the calling site of expand_binop,
3647 i.e. expand_expr. */
3648 /* Use emit_libcall_block for loop invariant code motion and to make
3649 a REG_EQUAL note. */
3650 emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
3651
3652 DONE;
3653 })
3654
3655 ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
3656 ;; a call to a routine which clobbers known registers.
3657 (define_insn ""
3658 [(set (match_operand:SI 1 "register_operand" "=z")
3659 (mult:SI (reg:SI R4_REG) (reg:SI R5_REG)))
3660 (clobber (reg:SI MACL_REG))
3661 (clobber (reg:SI T_REG))
3662 (clobber (reg:SI PR_REG))
3663 (clobber (reg:SI R3_REG))
3664 (clobber (reg:SI R2_REG))
3665 (clobber (reg:SI R1_REG))
3666 (use (match_operand:SI 0 "arith_reg_operand" "r"))]
3667 "TARGET_SH1"
3668 "jsr @%0%#"
3669 [(set_attr "type" "sfunc")
3670 (set_attr "needs_delay_slot" "yes")])
3671
3672 (define_expand "mulsi3_call"
3673 [(set (reg:SI R4_REG) (match_operand:SI 1 "general_operand" ""))
3674 (set (reg:SI R5_REG) (match_operand:SI 2 "general_operand" ""))
3675 (parallel[(set (match_operand:SI 0 "register_operand" "")
3676 (mult:SI (reg:SI R4_REG)
3677 (reg:SI R5_REG)))
3678 (clobber (reg:SI MACL_REG))
3679 (clobber (reg:SI T_REG))
3680 (clobber (reg:SI PR_REG))
3681 (clobber (reg:SI R3_REG))
3682 (clobber (reg:SI R2_REG))
3683 (clobber (reg:SI R1_REG))
3684 (use (match_operand:SI 3 "register_operand" ""))])]
3685 "TARGET_SH1"
3686 "")
3687
3688 (define_insn "mul_r"
3689 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
3690 (mult:SI (match_operand:SI 1 "arith_reg_operand" "0")
3691 (match_operand:SI 2 "arith_reg_operand" "z")))]
3692 "TARGET_SH2A"
3693 "mulr %2,%0"
3694 [(set_attr "type" "dmpy")])
3695
3696 (define_insn "mul_l"
3697 [(set (reg:SI MACL_REG)
3698 (mult:SI (match_operand:SI 0 "arith_reg_operand" "r")
3699 (match_operand:SI 1 "arith_reg_operand" "r")))]
3700 "TARGET_SH2"
3701 "mul.l %1,%0"
3702 [(set_attr "type" "dmpy")])
3703
3704 (define_expand "mulsi3"
3705 [(set (reg:SI MACL_REG)
3706 (mult:SI (match_operand:SI 1 "arith_reg_operand" "")
3707 (match_operand:SI 2 "arith_reg_operand" "")))
3708 (set (match_operand:SI 0 "arith_reg_operand" "")
3709 (reg:SI MACL_REG))]
3710 "TARGET_SH1"
3711 {
3712 if (!TARGET_SH2)
3713 {
3714 /* The address must be set outside the libcall,
3715 since it goes into a pseudo. */
3716 rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC);
3717 rtx addr = force_reg (SImode, sym);
3718 rtx insns = gen_mulsi3_call (operands[0], operands[1],
3719 operands[2], addr);
3720 emit_insn (insns);
3721 }
3722 else
3723 {
3724 rtx macl = gen_rtx_REG (SImode, MACL_REG);
3725
3726 emit_insn (gen_mul_l (operands[1], operands[2]));
3727 /* consec_sets_giv can only recognize the first insn that sets a
3728 giv as the giv insn. So we must tag this also with a REG_EQUAL
3729 note. */
3730 emit_insn (gen_movsi_i ((operands[0]), macl));
3731 }
3732 DONE;
3733 })
3734
3735 (define_insn "mulsidi3_i"
3736 [(set (reg:SI MACH_REG)
3737 (truncate:SI
3738 (lshiftrt:DI
3739 (mult:DI
3740 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3741 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3742 (const_int 32))))
3743 (set (reg:SI MACL_REG)
3744 (mult:SI (match_dup 0)
3745 (match_dup 1)))]
3746 "TARGET_SH2"
3747 "dmuls.l %1,%0"
3748 [(set_attr "type" "dmpy")])
3749
3750 (define_expand "mulsidi3"
3751 [(set (match_operand:DI 0 "arith_reg_dest" "")
3752 (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3753 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3754 "TARGET_SH2 || TARGET_SHMEDIA"
3755 {
3756 if (TARGET_SH2)
3757 {
3758 emit_insn (gen_mulsidi3_compact (operands[0], operands[1], operands[2]));
3759 DONE;
3760 }
3761 })
3762
3763 (define_insn "mulsidi3_media"
3764 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3765 (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3766 (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3767 "TARGET_SHMEDIA"
3768 "muls.l %1, %2, %0"
3769 [(set_attr "type" "dmpy_media")
3770 (set_attr "highpart" "ignore")])
3771
3772 (define_insn_and_split "mulsidi3_compact"
3773 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3774 (mult:DI
3775 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3776 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3777 (clobber (reg:SI MACH_REG))
3778 (clobber (reg:SI MACL_REG))]
3779 "TARGET_SH2"
3780 "#"
3781 "&& 1"
3782 [(const_int 0)]
3783 {
3784 rtx low_dst = gen_lowpart (SImode, operands[0]);
3785 rtx high_dst = gen_highpart (SImode, operands[0]);
3786
3787 emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
3788
3789 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3790 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3791 /* We need something to tag the possible REG_EQUAL notes on to. */
3792 emit_move_insn (operands[0], operands[0]);
3793 DONE;
3794 })
3795
3796 (define_insn "umulsidi3_i"
3797 [(set (reg:SI MACH_REG)
3798 (truncate:SI
3799 (lshiftrt:DI
3800 (mult:DI
3801 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3802 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3803 (const_int 32))))
3804 (set (reg:SI MACL_REG)
3805 (mult:SI (match_dup 0)
3806 (match_dup 1)))]
3807 "TARGET_SH2"
3808 "dmulu.l %1,%0"
3809 [(set_attr "type" "dmpy")])
3810
3811 (define_expand "umulsidi3"
3812 [(set (match_operand:DI 0 "arith_reg_dest" "")
3813 (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3814 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))]
3815 "TARGET_SH2 || TARGET_SHMEDIA"
3816 {
3817 if (TARGET_SH2)
3818 {
3819 emit_insn (gen_umulsidi3_compact (operands[0], operands[1], operands[2]));
3820 DONE;
3821 }
3822 })
3823
3824 (define_insn "umulsidi3_media"
3825 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3826 (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r"))
3827 (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))]
3828 "TARGET_SHMEDIA"
3829 "mulu.l %1, %2, %0"
3830 [(set_attr "type" "dmpy_media")
3831 (set_attr "highpart" "ignore")])
3832
3833 (define_insn_and_split "umulsidi3_compact"
3834 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3835 (mult:DI
3836 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
3837 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
3838 (clobber (reg:SI MACH_REG))
3839 (clobber (reg:SI MACL_REG))]
3840 "TARGET_SH2"
3841 "#"
3842 "&& 1"
3843 [(const_int 0)]
3844 {
3845 rtx low_dst = gen_lowpart (SImode, operands[0]);
3846 rtx high_dst = gen_highpart (SImode, operands[0]);
3847
3848 emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
3849
3850 emit_move_insn (low_dst, gen_rtx_REG (SImode, MACL_REG));
3851 emit_move_insn (high_dst, gen_rtx_REG (SImode, MACH_REG));
3852 /* We need something to tag the possible REG_EQUAL notes on to. */
3853 emit_move_insn (operands[0], operands[0]);
3854 DONE;
3855 })
3856
3857 (define_insn "smulsi3_highpart_i"
3858 [(set (reg:SI MACH_REG)
3859 (truncate:SI
3860 (lshiftrt:DI
3861 (mult:DI
3862 (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3863 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3864 (const_int 32))))
3865 (clobber (reg:SI MACL_REG))]
3866 "TARGET_SH2"
3867 "dmuls.l %1,%0"
3868 [(set_attr "type" "dmpy")])
3869
3870 (define_expand "smulsi3_highpart"
3871 [(parallel
3872 [(set (reg:SI MACH_REG)
3873 (truncate:SI
3874 (lshiftrt:DI
3875 (mult:DI
3876 (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3877 (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3878 (const_int 32))))
3879 (clobber (reg:SI MACL_REG))])
3880 (set (match_operand:SI 0 "arith_reg_operand" "")
3881 (reg:SI MACH_REG))]
3882 "TARGET_SH2"
3883 {
3884 rtx_insn *insn;
3885 rtx mach;
3886
3887 mach = gen_rtx_REG (SImode, MACH_REG);
3888 start_sequence ();
3889 emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
3890 insn = get_insns ();
3891 end_sequence ();
3892 /* expand_binop can't find a suitable code in mul_highpart_optab to
3893 make a REG_EQUAL note from, so make one here.
3894 See also {,u}mulhisi.
3895 ??? Alternatively, we could put this at the calling site of expand_binop,
3896 i.e. expand_mult_highpart. */
3897 /* Use emit_libcall_block for loop invariant code motion and to make
3898 a REG_EQUAL note. */
3899 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3900
3901 DONE;
3902 })
3903
3904 (define_insn "umulsi3_highpart_i"
3905 [(set (reg:SI MACH_REG)
3906 (truncate:SI
3907 (lshiftrt:DI
3908 (mult:DI
3909 (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
3910 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
3911 (const_int 32))))
3912 (clobber (reg:SI MACL_REG))]
3913 "TARGET_SH2"
3914 "dmulu.l %1,%0"
3915 [(set_attr "type" "dmpy")])
3916
3917 (define_expand "umulsi3_highpart"
3918 [(parallel
3919 [(set (reg:SI MACH_REG)
3920 (truncate:SI
3921 (lshiftrt:DI
3922 (mult:DI
3923 (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
3924 (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))
3925 (const_int 32))))
3926 (clobber (reg:SI MACL_REG))])
3927 (set (match_operand:SI 0 "arith_reg_operand" "")
3928 (reg:SI MACH_REG))]
3929 "TARGET_SH2"
3930 {
3931 rtx_insn *insn;
3932 rtx mach;
3933
3934 mach = gen_rtx_REG (SImode, MACH_REG);
3935 start_sequence ();
3936 emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
3937 insn = get_insns ();
3938 end_sequence ();
3939 /* Use emit_libcall_block for loop invariant code motion and to make
3940 a REG_EQUAL note. */
3941 emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
3942
3943 DONE;
3944 })
3945
3946 (define_insn_and_split "muldi3"
3947 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
3948 (mult:DI (match_operand:DI 1 "arith_reg_operand" "r")
3949 (match_operand:DI 2 "arith_reg_operand" "r")))
3950 (clobber (match_scratch:DI 3 "=&r"))
3951 (clobber (match_scratch:DI 4 "=r"))]
3952 "TARGET_SHMEDIA"
3953 "#"
3954 "reload_completed"
3955 [(const_int 0)]
3956 {
3957 rtx op3_v2si, op2_v2si;
3958
3959 op3_v2si = operands[3];
3960 if (GET_CODE (op3_v2si) == SIGN_EXTEND)
3961 {
3962 op3_v2si = XEXP (op3_v2si, 0);
3963 op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0);
3964 }
3965 op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0);
3966 op2_v2si = operands[2];
3967 if (GET_CODE (op2_v2si) == SIGN_EXTEND)
3968 {
3969 op2_v2si = XEXP (op2_v2si, 0);
3970 op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0);
3971 }
3972 op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0);
3973 emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32)));
3974 emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si));
3975 emit_insn (gen_umulsidi3_media (operands[4],
3976 sh_gen_truncate (SImode, operands[1], 0),
3977 sh_gen_truncate (SImode, operands[2], 0)));
3978 emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL)));
3979 emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32)));
3980 emit_insn (gen_adddi3 (operands[0], operands[3], operands[0]));
3981 emit_insn (gen_adddi3 (operands[0], operands[4], operands[0]));
3982 DONE;
3983 })
3984 \f
3985 ;; -------------------------------------------------------------------------
3986 ;; Logical operations
3987 ;; -------------------------------------------------------------------------
3988
3989 (define_expand "andsi3"
3990 [(set (match_operand:SI 0 "arith_reg_operand" "")
3991 (and:SI (match_operand:SI 1 "logical_reg_operand" "")
3992 (match_operand:SI 2 "logical_and_operand" "")))]
3993 ""
3994 {
3995 /* If it is possible to turn the and insn into a zero extension
3996 already, redundant zero extensions will be folded, which results
3997 in better code.
3998 Ideally the splitter of *andsi_compact would be enough, if redundant
3999 zero extensions were detected after the combine pass, which does not
4000 happen at the moment. */
4001 if (TARGET_SH1)
4002 {
4003 if (satisfies_constraint_Jmb (operands[2]))
4004 {
4005 emit_insn (gen_zero_extendqisi2 (operands[0],
4006 gen_lowpart (QImode, operands[1])));
4007 DONE;
4008 }
4009 else if (satisfies_constraint_Jmw (operands[2]))
4010 {
4011 emit_insn (gen_zero_extendhisi2 (operands[0],
4012 gen_lowpart (HImode, operands[1])));
4013 DONE;
4014 }
4015 }
4016 })
4017
4018 (define_insn_and_split "*andsi_compact"
4019 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,z,r")
4020 (and:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,0,0")
4021 (match_operand:SI 2 "logical_and_operand" "Jmb,Jmw,K08,r")))]
4022 "TARGET_SH1"
4023 "@
4024 extu.b %1,%0
4025 extu.w %1,%0
4026 and %2,%0
4027 and %2,%0"
4028 "&& 1"
4029 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
4030 {
4031 if (satisfies_constraint_Jmb (operands[2]))
4032 operands[1] = gen_lowpart (QImode, operands[1]);
4033 else if (satisfies_constraint_Jmw (operands[2]))
4034 operands[1] = gen_lowpart (HImode, operands[1]);
4035 else
4036 FAIL;
4037 }
4038 [(set_attr "type" "arith")])
4039
4040 (define_insn "*andsi3_media"
4041 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4042 (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
4043 (match_operand:SI 2 "logical_operand" "r,I10")))]
4044 "TARGET_SHMEDIA"
4045 "@
4046 and %1, %2, %0
4047 andi %1, %2, %0"
4048 [(set_attr "type" "arith_media")])
4049
4050 (define_insn "*andsi3_bclr"
4051 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4052 (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
4053 (match_operand:SI 2 "const_int_operand" "Psz")))]
4054 "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
4055 "bclr %W2,%0"
4056 [(set_attr "type" "arith")])
4057
4058 (define_insn_and_split "anddi3"
4059 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r")
4060 (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r")
4061 (match_operand:DI 2 "and_operand" "r,I10,J16")))]
4062 "TARGET_SHMEDIA"
4063 "@
4064 and %1, %2, %0
4065 andi %1, %2, %0
4066 #"
4067 "reload_completed
4068 && ! logical_operand (operands[2], DImode)"
4069 [(const_int 0)]
4070 {
4071 if ((unsigned)INTVAL (operands[2]) == (unsigned) 0xffffffff)
4072 emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode)));
4073 else
4074 emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1]));
4075 DONE;
4076 }
4077 [(set_attr "type" "arith_media")])
4078
4079 (define_insn "andcsi3"
4080 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4081 (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
4082 (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
4083 "TARGET_SHMEDIA"
4084 "andc %1,%2,%0"
4085 [(set_attr "type" "arith_media")])
4086
4087 (define_insn "andcdi3"
4088 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4089 (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
4090 (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
4091 "TARGET_SHMEDIA"
4092 "andc %1,%2,%0"
4093 [(set_attr "type" "arith_media")])
4094
4095 (define_expand "iorsi3"
4096 [(set (match_operand:SI 0 "arith_reg_operand" "")
4097 (ior:SI (match_operand:SI 1 "logical_reg_operand" "")
4098 (match_operand:SI 2 "logical_operand" "")))]
4099 ""
4100 "")
4101
4102 (define_insn "*iorsi3_compact"
4103 [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
4104 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
4105 (match_operand:SI 2 "logical_operand" "r,K08")))]
4106 "TARGET_SH1
4107 && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
4108 "or %2,%0"
4109 [(set_attr "type" "arith")])
4110
4111 (define_insn "*iorsi3_media"
4112 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4113 (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
4114 (match_operand:SI 2 "logical_operand" "r,I10")))]
4115 "TARGET_SHMEDIA"
4116 "@
4117 or %1, %2, %0
4118 ori %1, %2, %0"
4119 [(set_attr "type" "arith_media")])
4120
4121 (define_insn "*iorsi3_bset"
4122 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4123 (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
4124 (match_operand:SI 2 "const_int_operand" "Pso")))]
4125 "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
4126 "bset %V2,%0"
4127 [(set_attr "type" "arith")])
4128
4129 (define_insn "iordi3"
4130 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4131 (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
4132 (match_operand:DI 2 "logical_operand" "r,I10")))]
4133 "TARGET_SHMEDIA"
4134 "@
4135 or %1, %2, %0
4136 ori %1, %2, %0"
4137 [(set_attr "type" "arith_media")])
4138
4139 (define_insn_and_split "*logical_sidi3"
4140 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4141 (sign_extend:DI (match_operator:SI 3 "logical_operator"
4142 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
4143 (match_operand:SI 2 "logical_operand" "r,I10")])))]
4144 "TARGET_SHMEDIA"
4145 "#"
4146 "&& reload_completed"
4147 [(set (match_dup 0) (match_dup 3))]
4148 {
4149 operands[3]
4150 = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
4151 simplify_gen_subreg (DImode, operands[1], SImode, 0),
4152 simplify_gen_subreg (DImode, operands[2], SImode, 0));
4153 })
4154
4155 (define_insn_and_split "*logical_sidisi3"
4156 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4157 (truncate:SI (sign_extend:DI
4158 (match_operator:SI 3 "logical_operator"
4159 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
4160 (match_operand:SI 2 "logical_operand" "r,I10")]))))]
4161 "TARGET_SHMEDIA"
4162 "#"
4163 "&& 1"
4164 [(set (match_dup 0) (match_dup 3))])
4165
4166 (define_insn_and_split "*logical_sidi3_2"
4167 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4168 (sign_extend:DI (truncate:SI (sign_extend:DI
4169 (match_operator:SI 3 "logical_operator"
4170 [(match_operand:SI 1 "arith_reg_operand" "%r,r")
4171 (match_operand:SI 2 "logical_operand" "r,I10")])))))]
4172 "TARGET_SHMEDIA"
4173 "#"
4174 "&& 1"
4175 [(set (match_dup 0) (sign_extend:DI (match_dup 3)))])
4176
4177 (define_expand "xorsi3"
4178 [(set (match_operand:SI 0 "arith_reg_operand" "")
4179 (xor:SI (match_operand:SI 1 "logical_reg_operand" "")
4180 (match_operand:SI 2 "xor_operand" "")))]
4181 ""
4182 "")
4183
4184 (define_insn "*xorsi3_compact"
4185 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
4186 (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
4187 (match_operand:SI 2 "logical_operand" "K08,r")))]
4188 "TARGET_SH1"
4189 "xor %2,%0"
4190 [(set_attr "type" "arith")])
4191
4192 ;; The *logical_op_t pattern helps combine eliminating sign/zero extensions
4193 ;; of results where one of the inputs is a T bit store. Notice that this
4194 ;; pattern must not match during reload. If reload picks this pattern it
4195 ;; will be impossible to split it afterwards.
4196 (define_insn_and_split "*logical_op_t"
4197 [(set (match_operand:SI 0 "arith_reg_dest")
4198 (match_operator:SI 3 "logical_operator"
4199 [(match_operand:SI 1 "arith_reg_operand")
4200 (match_operand:SI 2 "t_reg_operand")]))]
4201 "TARGET_SH1 && can_create_pseudo_p ()"
4202 "#"
4203 "&& 1"
4204 [(set (match_dup 4) (reg:SI T_REG))
4205 (set (match_dup 0) (match_dup 3))]
4206 {
4207 operands[4] = gen_reg_rtx (SImode);
4208 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
4209 operands[1], operands[4]);
4210 })
4211
4212 (define_insn "*xorsi3_media"
4213 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4214 (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r")
4215 (match_operand:SI 2 "xor_operand" "r,I06")))]
4216 "TARGET_SHMEDIA"
4217 "@
4218 xor %1, %2, %0
4219 xori %1, %2, %0"
4220 [(set_attr "type" "arith_media")])
4221
4222 (define_insn "xordi3"
4223 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
4224 (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
4225 (match_operand:DI 2 "xor_operand" "r,I06")))]
4226 "TARGET_SHMEDIA"
4227 "@
4228 xor %1, %2, %0
4229 xori %1, %2, %0"
4230 [(set_attr "type" "arith_media")])
4231
4232 ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate.
4233 ;; converts 2 * sign extend -> logical op into logical op -> sign extend
4234 (define_split
4235 [(set (match_operand:DI 0 "arith_reg_dest" "")
4236 (sign_extend:DI (match_operator 4 "binary_logical_operator"
4237 [(match_operand 1 "any_register_operand" "")
4238 (match_operand 2 "any_register_operand" "")])))]
4239 "TARGET_SHMEDIA"
4240 [(set (match_dup 5) (match_dup 4))
4241 (set (match_dup 0) (sign_extend:DI (match_dup 5)))]
4242 {
4243 machine_mode inmode = GET_MODE (operands[1]);
4244 int offset = 0;
4245
4246 if (GET_CODE (operands[0]) == SUBREG)
4247 {
4248 offset = SUBREG_BYTE (operands[0]);
4249 operands[0] = SUBREG_REG (operands[0]);
4250 }
4251 gcc_assert (REG_P (operands[0]));
4252 if (TARGET_BIG_ENDIAN)
4253 offset += 8 - GET_MODE_SIZE (inmode);
4254 operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
4255 })
4256 \f
4257 ;; -------------------------------------------------------------------------
4258 ;; Shifts and rotates
4259 ;; -------------------------------------------------------------------------
4260
4261 ;; Let combine see that we can get the MSB and LSB into the T bit
4262 ;; via shll and shlr. This allows it to plug it into insns that can have
4263 ;; the T bit as an input (e.g. addc).
4264 ;; On SH2A use bld #0,Rn instead of shlr to avoid mutating the input.
4265 (define_insn_and_split "*reg_lsb_t"
4266 [(set (reg:SI T_REG)
4267 (and:SI (match_operand:SI 0 "arith_reg_operand")
4268 (const_int 1)))]
4269 "TARGET_SH1 && can_create_pseudo_p ()"
4270 "#"
4271 "&& 1"
4272 [(const_int 0)]
4273 {
4274 emit_insn (TARGET_SH2A ? gen_bldsi_reg (operands[0], const0_rtx)
4275 : gen_shlr (gen_reg_rtx (SImode), operands[0]));
4276 })
4277
4278 (define_insn_and_split "*reg_msb_t"
4279 [(set (reg:SI T_REG)
4280 (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand")
4281 (const_int 31)))]
4282 "TARGET_SH1 && can_create_pseudo_p ()"
4283 "#"
4284 "&& 1"
4285 [(const_int 0)]
4286 {
4287 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
4288 })
4289
4290 (define_expand "rotldi3"
4291 [(set (match_operand:DI 0 "arith_reg_dest" "")
4292 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "")
4293 (match_operand:HI 2 "mextr_bit_offset" "")))]
4294 "TARGET_SHMEDIA"
4295 {
4296 if (! mextr_bit_offset (operands[2], HImode))
4297 FAIL;
4298 })
4299
4300 (define_insn "rotldi3_mextr"
4301 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4302 (rotate:DI (match_operand:DI 1 "arith_reg_operand" "r")
4303 (match_operand:HI 2 "mextr_bit_offset" "i")))]
4304 "TARGET_SHMEDIA"
4305 {
4306 static char templ[16];
4307 sprintf (templ, "mextr%d %%1,%%1,%%0",
4308 8 - (int) (INTVAL (operands[2]) >> 3));
4309 return templ;
4310 }
4311 [(set_attr "type" "arith_media")])
4312
4313 (define_expand "rotrdi3"
4314 [(set (match_operand:DI 0 "arith_reg_dest" "")
4315 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "")
4316 (match_operand:HI 2 "mextr_bit_offset" "")))]
4317 "TARGET_SHMEDIA"
4318 {
4319 if (! mextr_bit_offset (operands[2], HImode))
4320 FAIL;
4321 })
4322
4323 (define_insn "rotrdi3_mextr"
4324 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
4325 (rotatert:DI (match_operand:DI 1 "arith_reg_operand" "r")
4326 (match_operand:HI 2 "mextr_bit_offset" "i")))]
4327 "TARGET_SHMEDIA"
4328 {
4329 static char templ[16];
4330 sprintf (templ, "mextr%d %%1,%%1,%%0", (int) INTVAL (operands[2]) >> 3);
4331 return templ;
4332 }
4333 [(set_attr "type" "arith_media")])
4334
4335 (define_split
4336 [(set (match_operand:DI 0 "arith_reg_dest" "")
4337 (ior:DI (zero_extend:DI (mem:QI (match_operand 1
4338 "ua_address_operand" "")))
4339 (ashift:DI (match_operand:DI 2 "arith_reg_operand" "")
4340 (const_int 8))))
4341 (clobber (match_operand:DI 3 "register_operand" ""))]
4342 "TARGET_SHMEDIA"
4343 [(match_dup 4) (match_dup 5)]
4344 {
4345 operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q)
4346 (operands[3], operands[1]));
4347 operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2],
4348 GEN_INT (56), GEN_INT (8));
4349 })
4350
4351 (define_expand "rotrsi3"
4352 [(set (match_operand:SI 0 "arith_reg_dest")
4353 (rotatert:SI (match_operand:SI 1 "arith_reg_operand")
4354 (match_operand:SI 2 "const_int_operand")))]
4355 "TARGET_SH1"
4356 {
4357 HOST_WIDE_INT ival = INTVAL (operands[2]);
4358 if (ival == 1)
4359 {
4360 emit_insn (gen_rotrsi3_1 (operands[0], operands[1]));
4361 DONE;
4362 }
4363
4364 FAIL;
4365 })
4366
4367 (define_insn "rotrsi3_1"
4368 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4369 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4370 (const_int 1)))
4371 (set (reg:SI T_REG)
4372 (and:SI (match_dup 1) (const_int 1)))]
4373 "TARGET_SH1"
4374 "rotr %0"
4375 [(set_attr "type" "arith")])
4376
4377 ;; A slimplified version of rotr for combine.
4378 (define_insn "*rotrsi3_1"
4379 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4380 (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
4381 (const_int 1)))
4382 (clobber (reg:SI T_REG))]
4383 "TARGET_SH1"
4384 "rotr %0"
4385 [(set_attr "type" "arith")])
4386
4387 (define_insn "rotlsi3_1"
4388 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4389 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4390 (const_int 1)))
4391 (set (reg:SI T_REG)
4392 (lshiftrt:SI (match_dup 1) (const_int 31)))]
4393 "TARGET_SH1"
4394 "rotl %0"
4395 [(set_attr "type" "arith")])
4396
4397 ;; A simplified version of rotl for combine.
4398 (define_insn "*rotlsi3_1"
4399 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4400 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4401 (const_int 1)))
4402 (clobber (reg:SI T_REG))]
4403 "TARGET_SH1"
4404 "rotl %0"
4405 [(set_attr "type" "arith")])
4406
4407 (define_insn "rotlsi3_31"
4408 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4409 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
4410 (const_int 31)))
4411 (clobber (reg:SI T_REG))]
4412 "TARGET_SH1"
4413 "rotr %0"
4414 [(set_attr "type" "arith")])
4415
4416 (define_insn "rotlsi3_16"
4417 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4418 (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
4419 (const_int 16)))]
4420 "TARGET_SH1"
4421 "swap.w %1,%0"
4422 [(set_attr "type" "arith")])
4423
4424 (define_expand "rotlsi3"
4425 [(set (match_operand:SI 0 "arith_reg_dest")
4426 (rotate:SI (match_operand:SI 1 "arith_reg_operand")
4427 (match_operand:SI 2 "const_int_operand")))]
4428 "TARGET_SH1"
4429 {
4430 static const char rot_tab[] = {
4431 000, 000, 000, 000, 000, 000, 010, 001,
4432 001, 001, 011, 013, 003, 003, 003, 003,
4433 003, 003, 003, 003, 003, 013, 012, 002,
4434 002, 002, 010, 000, 000, 000, 000, 000,
4435 };
4436
4437 int count = INTVAL (operands[2]);
4438 int choice = rot_tab[count];
4439 if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
4440 FAIL;
4441 choice &= 7;
4442 switch (choice)
4443 {
4444 case 0:
4445 emit_move_insn (operands[0], operands[1]);
4446 count -= (count & 16) * 2;
4447 break;
4448 case 3:
4449 emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
4450 count -= 16;
4451 break;
4452 case 1:
4453 case 2:
4454 {
4455 rtx parts[2];
4456 parts[0] = gen_reg_rtx (SImode);
4457 parts[1] = gen_reg_rtx (SImode);
4458 emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
4459 emit_move_insn (parts[choice-1], operands[1]);
4460 emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
4461 emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
4462 emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
4463 count = (count & ~16) - 8;
4464 }
4465 }
4466
4467 for (; count > 0; count--)
4468 emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
4469 for (; count < 0; count++)
4470 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
4471
4472 DONE;
4473 })
4474
4475 (define_insn "rotlhi3_8"
4476 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
4477 (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
4478 (const_int 8)))]
4479 "TARGET_SH1"
4480 "swap.b %1,%0"
4481 [(set_attr "type" "arith")])
4482
4483 (define_expand "rotlhi3"
4484 [(set (match_operand:HI 0 "arith_reg_operand")
4485 (rotate:HI (match_operand:HI 1 "arith_reg_operand")
4486 (match_operand:HI 2 "const_int_operand")))]
4487 "TARGET_SH1"
4488 {
4489 if (INTVAL (operands[2]) != 8)
4490 FAIL;
4491 })
4492
4493 ;; The rotcr and rotcl insns are used primarily in DImode shifts by one.
4494 ;; They can also be used to implement things like
4495 ;; bool t = a == b;
4496 ;; int x0 = (y >> 1) | (t << 31); // rotcr
4497 ;; int x1 = (y << 1) | t; // rotcl
4498 (define_insn "rotcr"
4499 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4500 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
4501 (const_int 1))
4502 (ashift:SI (match_operand:SI 2 "t_reg_operand")
4503 (const_int 31))))
4504 (set (reg:SI T_REG)
4505 (and:SI (match_dup 1) (const_int 1)))]
4506 "TARGET_SH1"
4507 "rotcr %0"
4508 [(set_attr "type" "arith")])
4509
4510 (define_insn "rotcl"
4511 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4512 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4513 (const_int 1))
4514 (match_operand:SI 2 "t_reg_operand")))
4515 (set (reg:SI T_REG)
4516 (lshiftrt:SI (match_dup 1) (const_int 31)))]
4517 "TARGET_SH1"
4518 "rotcl %0"
4519 [(set_attr "type" "arith")])
4520
4521 ;; Simplified rotcr version for combine, which allows arbitrary shift
4522 ;; amounts for the reg. If the shift amount is '1' rotcr can be used
4523 ;; directly. Otherwise we have to insert a shift in between.
4524 (define_insn_and_split "*rotcr"
4525 [(set (match_operand:SI 0 "arith_reg_dest")
4526 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_or_0_operand")
4527 (match_operand:SI 2 "const_int_operand"))
4528 (ashift:SI (match_operand 3 "arith_reg_or_treg_set_expr")
4529 (const_int 31))))
4530 (clobber (reg:SI T_REG))]
4531 "TARGET_SH1 && can_create_pseudo_p ()"
4532 "#"
4533 "&& 1"
4534 [(const_int 0)]
4535 {
4536 rtx prev_set_t_insn = NULL_RTX;
4537
4538 if (!arith_reg_operand (operands[3], SImode))
4539 {
4540 sh_treg_insns ti = sh_split_treg_set_expr (operands[3], curr_insn);
4541 if (!ti.was_treg_operand ())
4542 prev_set_t_insn = ti.first_insn ();
4543
4544 operands[3] = get_t_reg_rtx ();
4545
4546 if (TARGET_SH2A && ti.has_trailing_nott () && operands[1] == const0_rtx)
4547 {
4548 /* Convert to a movrt, rotr sequence. */
4549 remove_insn (ti.trailing_nott ());
4550 rtx tmp = gen_reg_rtx (SImode);
4551 emit_insn (gen_movnegt (tmp, get_t_reg_rtx ()));
4552 emit_insn (gen_rotrsi3_1 (operands[0], tmp));
4553 DONE;
4554 }
4555 }
4556
4557 if (operands[1] == const0_rtx)
4558 {
4559 operands[1] = gen_reg_rtx (SImode);
4560 emit_insn (gen_movt (operands[1], get_t_reg_rtx ()));
4561 }
4562
4563 if (INTVAL (operands[2]) > 1)
4564 {
4565 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4566 rtx tmp_t_reg = NULL_RTX;
4567
4568 /* If we're going to emit a shift sequence that clobbers the T_REG,
4569 try to find the previous insn that sets the T_REG and emit the
4570 shift insn before that insn, to remove the T_REG dependency.
4571 If the insn that sets the T_REG cannot be found, store the T_REG
4572 in a temporary reg and restore it after the shift. */
4573 if (sh_lshrsi_clobbers_t_reg_p (shift_count)
4574 && ! sh_dynamicalize_shift_p (shift_count))
4575 {
4576 if (prev_set_t_insn == NULL)
4577 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4578
4579 /* Skip the nott insn, which was probably inserted by the splitter
4580 of *rotcr_neg_t. Don't use one of the recog functions
4581 here during insn splitting, since that causes problems in later
4582 passes. */
4583 if (prev_set_t_insn != NULL_RTX)
4584 {
4585 rtx pat = PATTERN (prev_set_t_insn);
4586 if (GET_CODE (pat) == SET
4587 && t_reg_operand (XEXP (pat, 0), SImode)
4588 && negt_reg_operand (XEXP (pat, 1), SImode))
4589 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4590 }
4591
4592 if (! (prev_set_t_insn != NULL_RTX
4593 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4594 && ! reg_referenced_p (get_t_reg_rtx (),
4595 PATTERN (prev_set_t_insn))))
4596 {
4597 prev_set_t_insn = NULL_RTX;
4598 tmp_t_reg = gen_reg_rtx (SImode);
4599 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4600 }
4601 }
4602
4603 rtx shift_result = gen_reg_rtx (SImode);
4604 rtx shift_insn = gen_lshrsi3 (shift_result, operands[1], shift_count);
4605 operands[1] = shift_result;
4606
4607 /* Emit the shift insn before the insn that sets T_REG, if possible. */
4608 if (prev_set_t_insn != NULL_RTX)
4609 emit_insn_before (shift_insn, prev_set_t_insn);
4610 else
4611 emit_insn (shift_insn);
4612
4613 /* Restore T_REG if it has been saved before. */
4614 if (tmp_t_reg != NULL_RTX)
4615 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4616 }
4617
4618 /* For the rotcr insn to work, operands[3] must be in T_REG.
4619 If it is not we can get it there by shifting it right one bit.
4620 In this case T_REG is not an input for this insn, thus we don't have to
4621 pay attention as of where to insert the shlr insn. */
4622 if (! t_reg_operand (operands[3], SImode))
4623 {
4624 /* We don't care about the shifted result here, only the T_REG. */
4625 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4626 operands[3] = get_t_reg_rtx ();
4627 }
4628
4629 emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
4630 DONE;
4631 })
4632
4633 ;; If combine tries the same as above but with swapped operands, split
4634 ;; it so that it will try the pattern above.
4635 (define_split
4636 [(set (match_operand:SI 0 "arith_reg_dest")
4637 (ior:SI (ashift:SI (match_operand 1 "arith_reg_or_treg_set_expr")
4638 (const_int 31))
4639 (lshiftrt:SI (match_operand:SI 2 "arith_reg_or_0_operand")
4640 (match_operand:SI 3 "const_int_operand"))))]
4641 "TARGET_SH1 && can_create_pseudo_p ()"
4642 [(parallel [(set (match_dup 0)
4643 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4644 (ashift:SI (match_dup 1) (const_int 31))))
4645 (clobber (reg:SI T_REG))])])
4646
4647 ;; Basically the same as the rotcr pattern above, but for rotcl.
4648 ;; FIXME: Fold copy pasted split code for rotcr and rotcl.
4649 (define_insn_and_split "*rotcl"
4650 [(set (match_operand:SI 0 "arith_reg_dest")
4651 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4652 (match_operand:SI 2 "const_int_operand"))
4653 (and:SI (match_operand:SI 3 "arith_reg_or_t_reg_operand")
4654 (const_int 1))))
4655 (clobber (reg:SI T_REG))]
4656 "TARGET_SH1"
4657 "#"
4658 "&& can_create_pseudo_p ()"
4659 [(const_int 0)]
4660 {
4661 gcc_assert (INTVAL (operands[2]) > 0);
4662
4663 if (INTVAL (operands[2]) > 1)
4664 {
4665 const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
4666 rtx prev_set_t_insn = NULL_RTX;
4667 rtx tmp_t_reg = NULL_RTX;
4668
4669 /* If we're going to emit a shift sequence that clobbers the T_REG,
4670 try to find the previous insn that sets the T_REG and emit the
4671 shift insn before that insn, to remove the T_REG dependency.
4672 If the insn that sets the T_REG cannot be found, store the T_REG
4673 in a temporary reg and restore it after the shift. */
4674 if (sh_ashlsi_clobbers_t_reg_p (shift_count)
4675 && ! sh_dynamicalize_shift_p (shift_count))
4676 {
4677 prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
4678
4679 /* Skip the nott insn, which was probably inserted by the splitter
4680 of *rotcl_neg_t. Don't use one of the recog functions
4681 here during insn splitting, since that causes problems in later
4682 passes. */
4683 if (prev_set_t_insn != NULL_RTX)
4684 {
4685 rtx pat = PATTERN (prev_set_t_insn);
4686 if (GET_CODE (pat) == SET
4687 && t_reg_operand (XEXP (pat, 0), SImode)
4688 && negt_reg_operand (XEXP (pat, 1), SImode))
4689 prev_set_t_insn = prev_nonnote_insn_bb (prev_set_t_insn);
4690 }
4691
4692 if (! (prev_set_t_insn != NULL_RTX
4693 && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
4694 && ! reg_referenced_p (get_t_reg_rtx (),
4695 PATTERN (prev_set_t_insn))))
4696 {
4697 prev_set_t_insn = NULL_RTX;
4698 tmp_t_reg = gen_reg_rtx (SImode);
4699 emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
4700 }
4701 }
4702
4703 rtx shift_result = gen_reg_rtx (SImode);
4704 rtx shift_insn = gen_ashlsi3 (shift_result, operands[1], shift_count);
4705 operands[1] = shift_result;
4706
4707 /* Emit the shift insn before the insn that sets T_REG, if possible. */
4708 if (prev_set_t_insn != NULL_RTX)
4709 emit_insn_before (shift_insn, prev_set_t_insn);
4710 else
4711 emit_insn (shift_insn);
4712
4713 /* Restore T_REG if it has been saved before. */
4714 if (tmp_t_reg != NULL_RTX)
4715 emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
4716 }
4717
4718 /* For the rotcl insn to work, operands[3] must be in T_REG.
4719 If it is not we can get it there by shifting it right one bit.
4720 In this case T_REG is not an input for this insn, thus we don't have to
4721 pay attention as of where to insert the shlr insn. */
4722 if (! t_reg_operand (operands[3], SImode))
4723 {
4724 /* We don't care about the shifted result here, only the T_REG. */
4725 emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[3]));
4726 operands[3] = get_t_reg_rtx ();
4727 }
4728
4729 emit_insn (gen_rotcl (operands[0], operands[1], operands[3]));
4730 DONE;
4731 })
4732
4733 ;; rotcl combine pattern variations
4734 (define_insn_and_split "*rotcl"
4735 [(set (match_operand:SI 0 "arith_reg_dest")
4736 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4737 (match_operand:SI 2 "const_int_operand"))
4738 (match_operand 3 "treg_set_expr")))
4739 (clobber (reg:SI T_REG))]
4740 "TARGET_SH1"
4741 "#"
4742 "&& can_create_pseudo_p ()"
4743 [(parallel [(set (match_dup 0)
4744 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4745 (and:SI (match_dup 3) (const_int 1))))
4746 (clobber (reg:SI T_REG))])]
4747 {
4748 sh_split_treg_set_expr (operands[3], curr_insn);
4749 operands[3] = get_t_reg_rtx ();
4750 })
4751
4752 (define_insn_and_split "*rotcl"
4753 [(set (match_operand:SI 0 "arith_reg_dest")
4754 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_or_t_reg_operand")
4755 (const_int 1))
4756 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4757 (match_operand:SI 3 "const_int_operand"))))
4758 (clobber (reg:SI T_REG))]
4759 "TARGET_SH1"
4760 "#"
4761 "&& can_create_pseudo_p ()"
4762 [(parallel [(set (match_dup 0)
4763 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4764 (and:SI (match_dup 1) (const_int 1))))
4765 (clobber (reg:SI T_REG))])])
4766
4767 (define_insn_and_split "*rotcl"
4768 [(set (match_operand:SI 0 "arith_reg_dest")
4769 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4770 (match_operand:SI 2 "const_int_operand"))
4771 (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4772 (const_int 31))))
4773 (clobber (reg:SI T_REG))]
4774 "TARGET_SH1"
4775 "#"
4776 "&& can_create_pseudo_p ()"
4777 [(parallel [(set (match_dup 0)
4778 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4779 (and:SI (reg:SI T_REG) (const_int 1))))
4780 (clobber (reg:SI T_REG))])]
4781 {
4782 /* We don't care about the result of the left shift, only the T_REG. */
4783 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4784 })
4785
4786 (define_insn_and_split "*rotcl"
4787 [(set (match_operand:SI 0 "arith_reg_dest")
4788 (ior:SI (lshiftrt:SI (match_operand:SI 3 "arith_reg_operand")
4789 (const_int 31))
4790 (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4791 (match_operand:SI 2 "const_int_operand"))))
4792 (clobber (reg:SI T_REG))]
4793 "TARGET_SH1"
4794 "#"
4795 "&& can_create_pseudo_p ()"
4796 [(parallel [(set (match_dup 0)
4797 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4798 (and:SI (reg:SI T_REG) (const_int 1))))
4799 (clobber (reg:SI T_REG))])]
4800 {
4801 /* We don't care about the result of the left shift, only the T_REG. */
4802 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[3]));
4803 })
4804
4805 (define_insn_and_split "*rotcl"
4806 [(set (match_operand:SI 0 "arith_reg_dest")
4807 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand")
4808 (match_operand 2 "const_int_operand"))
4809 (zero_extract:SI (match_operand:SI 3 "arith_reg_operand")
4810 (const_int 1)
4811 (match_operand 4 "const_int_operand"))))
4812 (clobber (reg:SI T_REG))]
4813 "TARGET_SH1"
4814 "#"
4815 "&& can_create_pseudo_p ()"
4816 [(parallel [(set (match_dup 0)
4817 (ior:SI (ashift:SI (match_dup 1) (match_dup 2))
4818 (and:SI (match_dup 5) (const_int 1))))
4819 (clobber (reg:SI T_REG))])]
4820 {
4821 if (TARGET_SH2A && satisfies_constraint_K03 (operands[4]))
4822 {
4823 /* On SH2A we can use the bld insn to zero extract a single bit
4824 into the T bit. */
4825 operands[5] = get_t_reg_rtx ();
4826 emit_insn (gen_bldsi_reg (operands[3], operands[4]));
4827 }
4828 else
4829 {
4830 /* If we can't use the bld insn we have to emit a tst + nott sequence
4831 to get the extracted bit into the T bit.
4832 This will probably be worse than pre-shifting the operand. */
4833 operands[5] = gen_reg_rtx (SImode);
4834 emit_insn (gen_lshrsi3 (operands[5], operands[3], operands[4]));
4835 }
4836 })
4837
4838 ;; rotcr combine bridge pattern which will make combine try out more
4839 ;; complex patterns.
4840 (define_insn_and_split "*rotcr"
4841 [(set (match_operand:SI 0 "arith_reg_dest")
4842 (ashift:SI (match_operand 1 "treg_set_expr") (const_int 31)))]
4843 "TARGET_SH1 && can_create_pseudo_p ()"
4844 "#"
4845 "&& 1"
4846 [(parallel [(set (match_dup 0)
4847 (ior:SI (lshiftrt:SI (const_int 0) (const_int 1))
4848 (ashift:SI (match_dup 1) (const_int 31))))
4849 (clobber (reg:SI T_REG))])])
4850
4851 (define_insn_and_split "*rotcr"
4852 [(set (match_operand:SI 0 "arith_reg_dest")
4853 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
4854 (const_int -2147483648)) ;; 0xffffffff80000000
4855 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4856 (const_int 1))))
4857 (clobber (reg:SI T_REG))]
4858 "TARGET_SH1"
4859 "#"
4860 "&& can_create_pseudo_p ()"
4861 [(const_int 0)]
4862 {
4863 rtx tmp = gen_reg_rtx (SImode);
4864 emit_insn (gen_shll (tmp, operands[1]));
4865 emit_insn (gen_rotcr (operands[0], operands[2], get_t_reg_rtx ()));
4866 DONE;
4867 })
4868
4869 ;; rotcr combine patterns for rotating in the negated T_REG value.
4870 (define_insn_and_split "*rotcr_neg_t"
4871 [(set (match_operand:SI 0 "arith_reg_dest")
4872 (ior:SI (match_operand:SI 1 "negt_reg_shl31_operand")
4873 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
4874 (match_operand:SI 3 "const_int_operand"))))
4875 (clobber (reg:SI T_REG))]
4876 "TARGET_SH1"
4877 "#"
4878 "&& can_create_pseudo_p ()"
4879 [(parallel [(set (match_dup 0)
4880 (ior:SI (lshiftrt:SI (match_dup 2) (match_dup 3))
4881 (ashift:SI (reg:SI T_REG) (const_int 31))))
4882 (clobber (reg:SI T_REG))])]
4883 {
4884 emit_insn (gen_nott (get_t_reg_rtx ()));
4885 })
4886
4887 (define_insn_and_split "*rotcr_neg_t"
4888 [(set (match_operand:SI 0 "arith_reg_dest")
4889 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
4890 (match_operand:SI 2 "const_int_operand"))
4891 (match_operand:SI 3 "negt_reg_shl31_operand")))
4892 (clobber (reg:SI T_REG))]
4893 "TARGET_SH1"
4894 "#"
4895 "&& can_create_pseudo_p ()"
4896 [(parallel [(set (match_dup 0)
4897 (ior:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
4898 (ashift:SI (reg:SI T_REG) (const_int 31))))
4899 (clobber (reg:SI T_REG))])]
4900 {
4901 emit_insn (gen_nott (get_t_reg_rtx ()));
4902 })
4903
4904 ;; rotcl combine patterns for rotating in the negated T_REG value.
4905 ;; For some strange reason these have to be specified as splits which combine
4906 ;; will pick up. If they are specified as insn_and_split like the
4907 ;; *rotcr_neg_t patterns above, combine would recognize them successfully
4908 ;; but not emit them on non-SH2A targets.
4909 (define_split
4910 [(set (match_operand:SI 0 "arith_reg_dest")
4911 (ior:SI (match_operand:SI 1 "negt_reg_operand")
4912 (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4913 (match_operand:SI 3 "const_int_operand"))))]
4914 "TARGET_SH1"
4915 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4916 (parallel [(set (match_dup 0)
4917 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4918 (and:SI (reg:SI T_REG) (const_int 1))))
4919 (clobber (reg:SI T_REG))])])
4920
4921 (define_split
4922 [(set (match_operand:SI 0 "arith_reg_dest")
4923 (ior:SI (ashift:SI (match_operand:SI 2 "arith_reg_operand")
4924 (match_operand:SI 3 "const_int_operand"))
4925 (match_operand:SI 1 "negt_reg_operand")))]
4926 "TARGET_SH1"
4927 [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
4928 (parallel [(set (match_dup 0)
4929 (ior:SI (ashift:SI (match_dup 2) (match_dup 3))
4930 (and:SI (reg:SI T_REG) (const_int 1))))
4931 (clobber (reg:SI T_REG))])])
4932
4933 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4934 ;; SImode shift left
4935
4936 (define_expand "ashlsi3"
4937 [(set (match_operand:SI 0 "arith_reg_operand" "")
4938 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
4939 (match_operand:SI 2 "shift_count_operand" "")))]
4940 ""
4941 {
4942 if (TARGET_SHMEDIA)
4943 {
4944 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
4945 {
4946 operands[2] = GEN_INT (-INTVAL (operands[2]));
4947 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
4948 DONE;
4949 }
4950 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
4951 DONE;
4952 }
4953 if (TARGET_DYNSHIFT
4954 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
4955 operands[2] = force_reg (SImode, operands[2]);
4956
4957 /* If the ashlsi3_* insn is going to clobber the T_REG it must be
4958 expanded here. */
4959 if (CONST_INT_P (operands[2])
4960 && sh_ashlsi_clobbers_t_reg_p (operands[2])
4961 && ! sh_dynamicalize_shift_p (operands[2]))
4962 {
4963 emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1],
4964 operands[2]));
4965 DONE;
4966 }
4967
4968 /* Expand a library call for the dynamic shift. */
4969 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
4970 {
4971 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
4972 rtx funcaddr = gen_reg_rtx (Pmode);
4973 function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
4974 emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
4975
4976 DONE;
4977 }
4978 })
4979
4980 (define_insn "ashlsi3_k"
4981 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
4982 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
4983 (match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
4984 "TARGET_SH1"
4985 "@
4986 add %0,%0
4987 shll%O2 %0"
4988 [(set_attr "type" "arith")])
4989
4990 (define_insn_and_split "ashlsi3_d"
4991 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
4992 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
4993 (match_operand:SI 2 "shift_count_operand" "r")))]
4994 "TARGET_DYNSHIFT"
4995 "shld %2,%0"
4996 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
4997 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
4998 [(const_int 0)]
4999 {
5000 if (satisfies_constraint_P27 (operands[2]))
5001 {
5002 emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
5003 DONE;
5004 }
5005 else if (! satisfies_constraint_P27 (operands[2]))
5006 {
5007 /* This must happen before reload, otherwise the constant will be moved
5008 into a register due to the "r" constraint, after which this split
5009 cannot be done anymore.
5010 Unfortunately the move insn will not always be eliminated.
5011 Also, here we must not create a shift sequence that clobbers the
5012 T_REG. */
5013 emit_move_insn (operands[0], operands[1]);
5014 gen_shifty_op (ASHIFT, operands);
5015 DONE;
5016 }
5017
5018 FAIL;
5019 }
5020 [(set_attr "type" "dyn_shift")])
5021
5022 ;; If dynamic shifts are not available use a library function.
5023 ;; By specifying the pattern we reduce the number of call clobbered regs.
5024 ;; In order to make combine understand the truncation of the shift amount
5025 ;; operand we have to allow it to use pseudo regs for the shift operands.
5026 (define_insn "ashlsi3_d_call"
5027 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
5028 (ashift:SI (reg:SI R4_REG)
5029 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
5030 (const_int 31))))
5031 (use (match_operand:SI 2 "arith_reg_operand" "r"))
5032 (clobber (reg:SI T_REG))
5033 (clobber (reg:SI PR_REG))]
5034 "TARGET_SH1 && !TARGET_DYNSHIFT"
5035 "jsr @%2%#"
5036 [(set_attr "type" "sfunc")
5037 (set_attr "needs_delay_slot" "yes")])
5038
5039 (define_insn_and_split "ashlsi3_n"
5040 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5041 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5042 (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
5043 "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])"
5044 "#"
5045 "&& (reload_completed
5046 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5047 [(const_int 0)]
5048 {
5049 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5050 {
5051 /* If this pattern was picked and dynamic shifts are supported, switch
5052 to dynamic shift pattern before reload. */
5053 operands[2] = force_reg (SImode, operands[2]);
5054 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
5055 }
5056 else
5057 gen_shifty_op (ASHIFT, operands);
5058
5059 DONE;
5060 })
5061
5062 (define_insn_and_split "ashlsi3_n_clobbers_t"
5063 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5064 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
5065 (match_operand:SI 2 "not_p27_shift_count_operand" "")))
5066 (clobber (reg:SI T_REG))]
5067 "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])"
5068 "#"
5069 "&& (reload_completed || INTVAL (operands[2]) == 31
5070 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5071 [(const_int 0)]
5072 {
5073 if (INTVAL (operands[2]) == 31)
5074 {
5075 /* If the shift amount is 31 we split into a different sequence before
5076 reload so that it gets a chance to allocate R0 for the sequence.
5077 If it fails to do so (due to pressure on R0), it will take one insn
5078 more for the and. */
5079 emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
5080 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
5081 }
5082 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5083 {
5084 /* If this pattern was picked and dynamic shifts are supported, switch
5085 to dynamic shift pattern before reload. */
5086 operands[2] = force_reg (SImode, operands[2]);
5087 emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
5088 }
5089 else
5090 gen_shifty_op (ASHIFT, operands);
5091
5092 DONE;
5093 })
5094
5095 (define_insn "shll"
5096 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5097 (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
5098 (set (reg:SI T_REG)
5099 (lt:SI (match_dup 1) (const_int 0)))]
5100 "TARGET_SH1"
5101 "shll %0"
5102 [(set_attr "type" "arith")])
5103
5104 (define_insn "*ashlsi_c_void"
5105 [(set (reg:SI T_REG)
5106 (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))
5107 (clobber (match_scratch:SI 1 "=0"))]
5108 "TARGET_SH1 && cse_not_expected"
5109 "shll %0"
5110 [(set_attr "type" "arith")])
5111
5112 (define_peephole2
5113 [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0))
5114 (set (reg:SI T_REG)
5115 (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))]
5116 "TARGET_SH1
5117 && peep2_reg_dead_p (2, operands[0])
5118 && peep2_reg_dead_p (2, operands[1])"
5119 [(const_int 0)]
5120 {
5121 emit_insn (gen_shll (operands[1], operands[1]));
5122 DONE;
5123 })
5124
5125 (define_insn "ashlsi3_media"
5126 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5127 (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5128 (match_operand:SI 2 "shift_count_operand" "r,n")))]
5129 "TARGET_SHMEDIA"
5130 "@
5131 shlld.l %1, %2, %0
5132 shlli.l %1, %2, %0"
5133 [(set_attr "type" "arith_media")
5134 (set_attr "highpart" "ignore")])
5135
5136 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5137 ;; HImode shift left
5138
5139 (define_expand "ashlhi3"
5140 [(parallel [(set (match_operand:HI 0 "arith_reg_operand" "")
5141 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
5142 (match_operand:SI 2 "nonmemory_operand" "")))
5143 (clobber (reg:SI T_REG))])]
5144 "TARGET_SH1"
5145 {
5146 if (!CONST_INT_P (operands[2]))
5147 FAIL;
5148 /* It may be possible to call gen_ashlhi3 directly with more generic
5149 operands. Make sure operands[1] is a HImode register here. */
5150 if (!arith_reg_operand (operands[1], HImode))
5151 operands[1] = copy_to_mode_reg (HImode, operands[1]);
5152 })
5153
5154 (define_insn "ashlhi3_k"
5155 [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
5156 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
5157 (match_operand:HI 2 "const_int_operand" "M,P27")))]
5158 "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
5159 "@
5160 add %0,%0
5161 shll%O2 %0"
5162 [(set_attr "type" "arith")])
5163
5164 (define_insn_and_split "*ashlhi3_n"
5165 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
5166 (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
5167 (match_operand:HI 2 "const_int_operand" "n")))
5168 (clobber (reg:SI T_REG))]
5169 "TARGET_SH1"
5170 "#"
5171 "&& reload_completed"
5172 [(use (reg:SI R0_REG))]
5173 {
5174 gen_shifty_hi_op (ASHIFT, operands);
5175 DONE;
5176 })
5177
5178 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5179 ;; DImode shift left
5180
5181 (define_expand "ashldi3"
5182 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5183 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
5184 (match_operand:DI 2 "immediate_operand" "")))
5185 (clobber (reg:SI T_REG))])]
5186 ""
5187 {
5188 if (TARGET_SHMEDIA)
5189 {
5190 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5191 {
5192 operands[2] = GEN_INT (-INTVAL (operands[2]));
5193 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
5194 DONE;
5195 }
5196 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5197 DONE;
5198 }
5199 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
5200 {
5201 emit_insn (gen_ashldi3_k (operands[0], operands[1]));
5202 DONE;
5203 }
5204 else if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32)
5205 {
5206 emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
5207 DONE;
5208 }
5209 else
5210 FAIL;
5211 })
5212
5213 ;; Expander for DImode shift left with SImode operations.
5214 (define_expand "ashldi3_std"
5215 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5216 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
5217 (match_operand:DI 2 "const_int_operand" "n")))]
5218 "TARGET_SH1 && INTVAL (operands[2]) < 32"
5219 {
5220 rtx low_src = gen_lowpart (SImode, operands[1]);
5221 rtx high_src = gen_highpart (SImode, operands[1]);
5222 rtx dst = gen_reg_rtx (DImode);
5223 rtx low_dst = gen_lowpart (SImode, dst);
5224 rtx high_dst = gen_highpart (SImode, dst);
5225 rtx tmp0 = gen_reg_rtx (SImode);
5226 rtx tmp1 = gen_reg_rtx (SImode);
5227
5228 emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
5229 emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
5230 emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
5231 emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
5232 emit_move_insn (operands[0], dst);
5233 DONE;
5234 })
5235
5236 (define_insn_and_split "ashldi3_k"
5237 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5238 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
5239 (const_int 1)))
5240 (clobber (reg:SI T_REG))]
5241 "TARGET_SH1"
5242 "#"
5243 "&& reload_completed"
5244 [(const_int 0)]
5245 {
5246 rtx high = gen_highpart (SImode, operands[0]);
5247 rtx low = gen_lowpart (SImode, operands[0]);
5248 emit_insn (gen_shll (low, low));
5249 emit_insn (gen_rotcl (high, high, get_t_reg_rtx ()));
5250 DONE;
5251 })
5252
5253 (define_insn "ashldi3_media"
5254 [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
5255 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5256 (match_operand:DI 2 "shift_count_operand" "r,n")))]
5257 "TARGET_SHMEDIA"
5258 "@
5259 shlld %1, %2, %0
5260 shlli %1, %2, %0"
5261 [(set_attr "type" "arith_media")])
5262
5263 (define_insn "*ashldisi3_media"
5264 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5265 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
5266 (match_operand:DI 2 "const_int_operand" "n")))]
5267 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5268 "shlli.l %1, %2, %0"
5269 [(set_attr "type" "arith_media")
5270 (set_attr "highpart" "ignore")])
5271
5272 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5273 ;; SImode arithmetic shift right
5274 ;;
5275 ;; We can't do HImode right shifts correctly unless we start out with an
5276 ;; explicit zero / sign extension; doing that would result in worse overall
5277 ;; code, so just let the machine independent code widen the mode.
5278 ;; That's why we don't have ashrhi3_k / lshrhi3_k / lshrhi3_m / lshrhi3 .
5279
5280 (define_expand "ashrsi3"
5281 [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
5282 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
5283 (match_operand:SI 2 "nonmemory_operand" "")))
5284 (clobber (reg:SI T_REG))])]
5285 ""
5286 {
5287 if (TARGET_SHMEDIA)
5288 {
5289 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5290 {
5291 operands[2] = GEN_INT (-INTVAL (operands[2]));
5292 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
5293 DONE;
5294 }
5295 emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
5296 DONE;
5297 }
5298 if (expand_ashiftrt (operands))
5299 DONE;
5300 else
5301 FAIL;
5302 })
5303
5304 (define_insn "shar"
5305 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5306 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5307 (const_int 1)))
5308 (set (reg:SI T_REG)
5309 (and:SI (match_dup 1) (const_int 1)))]
5310 "TARGET_SH1"
5311 "shar %0"
5312 [(set_attr "type" "arith")])
5313
5314 (define_insn "ashrsi3_k"
5315 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5316 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5317 (match_operand:SI 2 "const_int_operand" "M")))
5318 (clobber (reg:SI T_REG))]
5319 "TARGET_SH1 && INTVAL (operands[2]) == 1"
5320 "shar %0"
5321 [(set_attr "type" "arith")])
5322
5323 (define_insn_and_split "ashrsi2_16"
5324 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5325 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
5326 (const_int 16)))]
5327 "TARGET_SH1"
5328 "#"
5329 "&& 1"
5330 [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
5331 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
5332 {
5333 operands[2] = gen_lowpart (HImode, operands[0]);
5334 })
5335
5336 (define_insn_and_split "ashrsi2_31"
5337 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5338 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5339 (const_int 31)))
5340 (clobber (reg:SI T_REG))]
5341 "TARGET_SH1"
5342 "#"
5343 "&& 1"
5344 [(const_int 0)]
5345 {
5346 emit_insn (gen_shll (operands[0], operands[1]));
5347 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
5348 DONE;
5349 })
5350
5351 ;; If the shift amount is changed by combine it will try to plug the
5352 ;; use on the symbol of the library function and the PR clobber.
5353 (define_insn_and_split "*ashrsi2_31"
5354 [(set (match_operand:SI 0 "arith_reg_dest")
5355 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand")
5356 (const_int 31)))
5357 (clobber (reg:SI T_REG))
5358 (clobber (reg:SI PR_REG))
5359 (use (match_operand:SI 2 "symbol_ref_operand"))]
5360 "TARGET_SH1"
5361 "#"
5362 "&& 1"
5363 [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))
5364 (clobber (reg:SI T_REG))])])
5365
5366 (define_insn "ashrsi3_d"
5367 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5368 (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5369 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
5370 "TARGET_DYNSHIFT"
5371 "shad %2,%0"
5372 [(set_attr "type" "dyn_shift")])
5373
5374 (define_insn "ashrsi3_n"
5375 [(set (reg:SI R4_REG)
5376 (ashiftrt:SI (reg:SI R4_REG)
5377 (match_operand:SI 0 "const_int_operand" "i")))
5378 (clobber (reg:SI T_REG))
5379 (clobber (reg:SI PR_REG))
5380 (use (match_operand:SI 1 "arith_reg_operand" "r"))]
5381 "TARGET_SH1"
5382 "jsr @%1%#"
5383 [(set_attr "type" "sfunc")
5384 (set_attr "needs_delay_slot" "yes")])
5385
5386 (define_insn "ashrsi3_media"
5387 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5388 (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5389 (match_operand:SI 2 "shift_count_operand" "r,n")))]
5390 "TARGET_SHMEDIA"
5391 "@
5392 shard.l %1, %2, %0
5393 shari.l %1, %2, %0"
5394 [(set_attr "type" "arith_media")
5395 (set_attr "highpart" "ignore")])
5396
5397 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5398 ;; DImode arithmetic shift right
5399
5400 (define_expand "ashrdi3"
5401 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5402 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5403 (match_operand:DI 2 "immediate_operand" "")))
5404 (clobber (reg:SI T_REG))])]
5405 ""
5406 {
5407 if (TARGET_SHMEDIA)
5408 {
5409 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5410 {
5411 operands[2] = GEN_INT (-INTVAL (operands[2]));
5412 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5413 DONE;
5414 }
5415 emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
5416 DONE;
5417 }
5418 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5419 FAIL;
5420 })
5421
5422 (define_insn_and_split "ashrdi3_k"
5423 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5424 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5425 (const_int 1)))
5426 (clobber (reg:SI T_REG))]
5427 "TARGET_SH1"
5428 "#"
5429 "&& reload_completed"
5430 [(const_int 0)]
5431 {
5432 rtx high = gen_highpart (SImode, operands[0]);
5433 rtx low = gen_lowpart (SImode, operands[0]);
5434 emit_insn (gen_shar (high, high));
5435 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5436 DONE;
5437 })
5438
5439 (define_insn "ashrdi3_media"
5440 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5441 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5442 (match_operand:DI 2 "shift_count_operand" "r,n")))]
5443 "TARGET_SHMEDIA
5444 && (arith_reg_dest (operands[0], DImode)
5445 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 32))"
5446 "@
5447 shard %1, %2, %0
5448 shari %1, %2, %0"
5449 [(set_attr "type" "arith_media")])
5450
5451 (define_insn "*ashrdisi3_media"
5452 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5453 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5454 (match_operand:DI 2 "const_int_operand" "n")))]
5455 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5456 "shari.l %1, %2, %0"
5457 [(set_attr "type" "arith_media")
5458 (set_attr "highpart" "ignore")])
5459
5460 (define_insn "ashrdisi3_media_high"
5461 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5462 (truncate:SI
5463 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5464 (match_operand:DI 2 "const_int_operand" "n"))))]
5465 "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32"
5466 "shari %1, %2, %0"
5467 [(set_attr "type" "arith_media")])
5468
5469 (define_insn "ashrdisi3_media_opaque"
5470 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5471 (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r")
5472 (match_operand:DI 2 "const_int_operand" "n")]
5473 UNSPEC_ASHIFTRT))]
5474 "TARGET_SHMEDIA"
5475 "shari %1, %2, %0"
5476 [(set_attr "type" "arith_media")])
5477
5478 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5479 ;; SImode logical shift right
5480
5481 (define_expand "lshrsi3"
5482 [(set (match_operand:SI 0 "arith_reg_dest" "")
5483 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
5484 (match_operand:SI 2 "shift_count_operand" "")))]
5485 ""
5486 {
5487 if (TARGET_SHMEDIA)
5488 {
5489 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5490 {
5491 operands[2] = GEN_INT (-INTVAL (operands[2]));
5492 emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
5493 DONE;
5494 }
5495 emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
5496 DONE;
5497 }
5498
5499 /* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
5500 here, otherwise the pattern will never match due to the shift amount reg
5501 negation. */
5502 if (TARGET_DYNSHIFT
5503 && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
5504 {
5505 rtx neg_count = force_reg (SImode,
5506 gen_int_mode (- INTVAL (operands[2]), SImode));
5507 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5508 DONE;
5509 }
5510
5511 if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
5512 {
5513 rtx neg_count = gen_reg_rtx (SImode);
5514 emit_insn (gen_negsi2 (neg_count, operands[2]));
5515 emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
5516 DONE;
5517 }
5518
5519 /* If the lshrsi3_* insn is going to clobber the T_REG it must be
5520 expanded here. */
5521 if (CONST_INT_P (operands[2])
5522 && sh_lshrsi_clobbers_t_reg_p (operands[2])
5523 && ! sh_dynamicalize_shift_p (operands[2]))
5524 {
5525 emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
5526 operands[2]));
5527 DONE;
5528 }
5529
5530 /* Expand a library call for the dynamic shift. */
5531 if (!CONST_INT_P (operands[2]) && !TARGET_DYNSHIFT)
5532 {
5533 emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
5534 rtx funcaddr = gen_reg_rtx (Pmode);
5535 function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC);
5536 emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr));
5537 DONE;
5538 }
5539 })
5540
5541 (define_insn "lshrsi3_k"
5542 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5543 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5544 (match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
5545 "TARGET_SH1"
5546 "shlr%O2 %0"
5547 [(set_attr "type" "arith")])
5548
5549 (define_insn_and_split "lshrsi3_d"
5550 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5551 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5552 (neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
5553 "TARGET_DYNSHIFT"
5554 "shld %2,%0"
5555 "&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
5556 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5557 [(const_int 0)]
5558 {
5559 if (satisfies_constraint_P27 (operands[2]))
5560 {
5561 /* This will not be done for a shift amount of 1, because it would
5562 clobber the T_REG. */
5563 emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
5564 DONE;
5565 }
5566 else if (! satisfies_constraint_P27 (operands[2]))
5567 {
5568 /* This must happen before reload, otherwise the constant will be moved
5569 into a register due to the "r" constraint, after which this split
5570 cannot be done anymore.
5571 Unfortunately the move insn will not always be eliminated.
5572 Also, here we must not create a shift sequence that clobbers the
5573 T_REG. */
5574 emit_move_insn (operands[0], operands[1]);
5575 gen_shifty_op (LSHIFTRT, operands);
5576 DONE;
5577 }
5578
5579 FAIL;
5580 }
5581 [(set_attr "type" "dyn_shift")])
5582
5583 ;; If dynamic shifts are not available use a library function.
5584 ;; By specifying the pattern we reduce the number of call clobbered regs.
5585 ;; In order to make combine understand the truncation of the shift amount
5586 ;; operand we have to allow it to use pseudo regs for the shift operands.
5587 (define_insn "lshrsi3_d_call"
5588 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
5589 (lshiftrt:SI (reg:SI R4_REG)
5590 (and:SI (match_operand:SI 1 "arith_reg_operand" "z")
5591 (const_int 31))))
5592 (use (match_operand:SI 2 "arith_reg_operand" "r"))
5593 (clobber (reg:SI T_REG))
5594 (clobber (reg:SI PR_REG))]
5595 "TARGET_SH1 && !TARGET_DYNSHIFT"
5596 "jsr @%2%#"
5597 [(set_attr "type" "sfunc")
5598 (set_attr "needs_delay_slot" "yes")])
5599
5600 (define_insn_and_split "lshrsi3_n"
5601 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5602 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5603 (match_operand:SI 2 "not_p27_rshift_count_operand")))]
5604 "TARGET_SH1 && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
5605 "#"
5606 "&& (reload_completed
5607 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5608 [(const_int 0)]
5609 {
5610 if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5611 {
5612 /* If this pattern was picked and dynamic shifts are supported, switch
5613 to dynamic shift pattern before reload. */
5614 operands[2] = force_reg (SImode,
5615 gen_int_mode (- INTVAL (operands[2]), SImode));
5616 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5617 }
5618 else
5619 gen_shifty_op (LSHIFTRT, operands);
5620
5621 DONE;
5622 })
5623
5624 ;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
5625 ;; the shlr pattern.
5626 (define_insn_and_split "lshrsi3_n_clobbers_t"
5627 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5628 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5629 (match_operand:SI 2 "not_p27_rshift_count_operand")))
5630 (clobber (reg:SI T_REG))]
5631 "TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
5632 "#"
5633 "&& (reload_completed || INTVAL (operands[2]) == 31
5634 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
5635 [(const_int 0)]
5636 {
5637 if (INTVAL (operands[2]) == 31)
5638 {
5639 emit_insn (gen_shll (operands[0], operands[1]));
5640 emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
5641 }
5642 else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
5643 {
5644 /* If this pattern was picked and dynamic shifts are supported, switch
5645 to dynamic shift pattern before reload. */
5646 operands[2] = force_reg (SImode,
5647 gen_int_mode (- INTVAL (operands[2]), SImode));
5648 emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
5649 }
5650 else
5651 gen_shifty_op (LSHIFTRT, operands);
5652
5653 DONE;
5654 })
5655
5656 (define_insn "shlr"
5657 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5658 (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5659 (const_int 1)))
5660 (set (reg:SI T_REG)
5661 (and:SI (match_dup 1) (const_int 1)))]
5662 "TARGET_SH1"
5663 "shlr %0"
5664 [(set_attr "type" "arith")])
5665
5666 (define_insn "lshrsi3_media"
5667 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
5668 (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
5669 (match_operand:SI 2 "shift_count_operand" "r,n")))]
5670 "TARGET_SHMEDIA"
5671 "@
5672 shlrd.l %1, %2, %0
5673 shlri.l %1, %2, %0"
5674 [(set_attr "type" "arith_media")
5675 (set_attr "highpart" "ignore")])
5676
5677 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5678 ;; DImode logical shift right
5679
5680 (define_expand "lshrdi3"
5681 [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
5682 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
5683 (match_operand:DI 2 "immediate_operand" "")))
5684 (clobber (reg:SI T_REG))])]
5685 ""
5686 {
5687 if (TARGET_SHMEDIA)
5688 {
5689 if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
5690 {
5691 operands[2] = GEN_INT (-INTVAL (operands[2]));
5692 emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
5693 DONE;
5694 }
5695 emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
5696 DONE;
5697 }
5698 if (!CONST_INT_P (operands[2]) || INTVAL (operands[2]) != 1)
5699 FAIL;
5700 })
5701
5702 (define_insn_and_split "lshrdi3_k"
5703 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
5704 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
5705 (const_int 1)))
5706 (clobber (reg:SI T_REG))]
5707 "TARGET_SH1"
5708 "#"
5709 "&& reload_completed"
5710 [(const_int 0)]
5711 {
5712 rtx high = gen_highpart (SImode, operands[0]);
5713 rtx low = gen_lowpart (SImode, operands[0]);
5714 emit_insn (gen_shlr (high, high));
5715 emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
5716 DONE;
5717 })
5718
5719 (define_insn "lshrdi3_media"
5720 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
5721 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
5722 (match_operand:DI 2 "shift_count_operand" "r,n")))]
5723 "TARGET_SHMEDIA
5724 && (arith_reg_dest (operands[0], DImode)
5725 || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > 32))"
5726 "@
5727 shlrd %1, %2, %0
5728 shlri %1, %2, %0"
5729 [(set_attr "type" "arith_media")])
5730
5731 (define_insn "*lshrdisi3_media"
5732 [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0)
5733 (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
5734 (match_operand:DI 2 "const_int_operand" "n")))]
5735 "TARGET_SHMEDIA && INTVAL (operands[2]) < 32"
5736 "shlri.l %1, %2, %0"
5737 [(set_attr "type" "arith_media")
5738 (set_attr "highpart" "ignore")])
5739
5740 ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5741 ;; Combined left/right shifts
5742
5743 (define_split
5744 [(set (match_operand:SI 0 "register_operand" "")
5745 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5746 (match_operand:SI 2 "const_int_operand" ""))
5747 (match_operand:SI 3 "const_int_operand" "")))]
5748 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5749 [(use (reg:SI R0_REG))]
5750 {
5751 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5752 FAIL;
5753 DONE;
5754 })
5755
5756 (define_split
5757 [(set (match_operand:SI 0 "register_operand" "")
5758 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
5759 (match_operand:SI 2 "const_int_operand" ""))
5760 (match_operand:SI 3 "const_int_operand" "")))
5761 (clobber (reg:SI T_REG))]
5762 "TARGET_SH1 && reload_completed && (unsigned)INTVAL (operands[2]) < 32"
5763 [(use (reg:SI R0_REG))]
5764 {
5765 if (gen_shl_and (operands[0], operands[2], operands[3], operands[1]))
5766 FAIL;
5767 DONE;
5768 })
5769
5770 (define_insn ""
5771 [(set (match_operand:SI 0 "register_operand" "=r")
5772 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5773 (match_operand:SI 2 "const_int_operand" "n"))
5774 (match_operand:SI 3 "const_int_operand" "n")))
5775 (clobber (reg:SI T_REG))]
5776 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
5777 "#"
5778 [(set (attr "length")
5779 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5780 (const_string "4")
5781 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5782 (const_string "6")
5783 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5784 (const_string "8")
5785 (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
5786 (const_string "10")
5787 (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
5788 (const_string "12")
5789 (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
5790 (const_string "14")
5791 (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
5792 (const_string "16")]
5793 (const_string "18")))
5794 (set_attr "type" "arith")])
5795
5796 (define_insn ""
5797 [(set (match_operand:SI 0 "register_operand" "=z")
5798 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
5799 (match_operand:SI 2 "const_int_operand" "n"))
5800 (match_operand:SI 3 "const_int_operand" "n")))
5801 (clobber (reg:SI T_REG))]
5802 "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
5803 "#"
5804 [(set (attr "length")
5805 (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
5806 (const_string "4")
5807 (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
5808 (const_string "6")
5809 (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
5810 (const_string "8")]
5811 (const_string "10")))
5812 (set_attr "type" "arith")])
5813
5814 ;; shift left / and combination with a scratch register: The combine pass
5815 ;; does not accept the individual instructions, even though they are
5816 ;; cheap. But it needs a precise description so that it is usable after
5817 ;; reload.
5818 (define_insn "and_shl_scratch"
5819 [(set (match_operand:SI 0 "register_operand" "=r,&r")
5820 (lshiftrt:SI
5821 (ashift:SI
5822 (and:SI
5823 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
5824 (match_operand:SI 2 "const_int_operand" "N,n"))
5825 (match_operand:SI 3 "" "0,r"))
5826 (match_operand:SI 4 "const_int_operand" "n,n"))
5827 (match_operand:SI 5 "const_int_operand" "n,n")))
5828 (clobber (reg:SI T_REG))]
5829 "TARGET_SH1"
5830 "#"
5831 [(set (attr "length")
5832 (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
5833 (const_string "4")
5834 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
5835 (const_string "6")
5836 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
5837 (const_string "8")
5838 (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
5839 (const_string "10")]
5840 (const_string "12")))
5841 (set_attr "type" "arith")])
5842
5843 (define_split
5844 [(set (match_operand:SI 0 "register_operand" "")
5845 (lshiftrt:SI
5846 (ashift:SI
5847 (and:SI
5848 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
5849 (match_operand:SI 2 "const_int_operand" ""))
5850 (match_operand:SI 3 "register_operand" ""))
5851 (match_operand:SI 4 "const_int_operand" ""))
5852 (match_operand:SI 5 "const_int_operand" "")))
5853 (clobber (reg:SI T_REG))]
5854 "TARGET_SH1"
5855 [(use (reg:SI R0_REG))]
5856 {
5857 rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
5858
5859 if (INTVAL (operands[2]))
5860 {
5861 gen_shifty_op (LSHIFTRT, operands);
5862 }
5863 emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
5864 operands[2] = operands[4];
5865 gen_shifty_op (ASHIFT, operands);
5866 if (INTVAL (operands[5]))
5867 {
5868 operands[2] = operands[5];
5869 gen_shifty_op (LSHIFTRT, operands);
5870 }
5871 DONE;
5872 })
5873
5874 ;; signed left/right shift combination.
5875 (define_split
5876 [(set (match_operand:SI 0 "register_operand" "")
5877 (sign_extract:SI
5878 (ashift:SI (match_operand:SI 1 "register_operand" "")
5879 (match_operand:SI 2 "const_int_operand" ""))
5880 (match_operand:SI 3 "const_int_operand" "")
5881 (const_int 0)))
5882 (clobber (reg:SI T_REG))]
5883 "TARGET_SH1"
5884 [(use (reg:SI R0_REG))]
5885 {
5886 if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1]))
5887 FAIL;
5888 DONE;
5889 })
5890
5891 (define_insn "shl_sext_ext"
5892 [(set (match_operand:SI 0 "register_operand" "=r")
5893 (sign_extract:SI
5894 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5895 (match_operand:SI 2 "const_int_operand" "n"))
5896 (match_operand:SI 3 "const_int_operand" "n")
5897 (const_int 0)))
5898 (clobber (reg:SI T_REG))]
5899 "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
5900 "#"
5901 [(set (attr "length")
5902 (cond [(match_test "shl_sext_length (insn)")
5903 (const_string "2")
5904 (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
5905 (const_string "4")
5906 (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5907 (const_string "6")
5908 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5909 (const_string "8")
5910 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5911 (const_string "10")
5912 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5913 (const_string "12")
5914 (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
5915 (const_string "14")
5916 (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
5917 (const_string "16")]
5918 (const_string "18")))
5919 (set_attr "type" "arith")])
5920
5921 (define_insn "shl_sext_sub"
5922 [(set (match_operand:SI 0 "register_operand" "=z")
5923 (sign_extract:SI
5924 (ashift:SI (match_operand:SI 1 "register_operand" "0")
5925 (match_operand:SI 2 "const_int_operand" "n"))
5926 (match_operand:SI 3 "const_int_operand" "n")
5927 (const_int 0)))
5928 (clobber (reg:SI T_REG))]
5929 "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
5930 "#"
5931 [(set (attr "length")
5932 (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
5933 (const_string "6")
5934 (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
5935 (const_string "8")
5936 (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
5937 (const_string "10")
5938 (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
5939 (const_string "12")]
5940 (const_string "14")))
5941 (set_attr "type" "arith")])
5942
5943 ;; The xtrct_left and xtrct_right patterns are used in expansions of DImode
5944 ;; shifts by 16, and allow the xtrct instruction to be generated from C
5945 ;; source.
5946 (define_insn "xtrct_left"
5947 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5948 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
5949 (const_int 16))
5950 (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
5951 (const_int 16))))]
5952 "TARGET_SH1"
5953 "xtrct %1,%0"
5954 [(set_attr "type" "arith")])
5955
5956 (define_insn "xtrct_right"
5957 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5958 (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
5959 (const_int 16))
5960 (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
5961 (const_int 16))))]
5962 "TARGET_SH1"
5963 "xtrct %2,%0"
5964 [(set_attr "type" "arith")])
5965
5966 ;; -------------------------------------------------------------------------
5967 ;; Unary arithmetic
5968 ;; -------------------------------------------------------------------------
5969
5970 (define_insn "negc"
5971 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5972 (neg:SI (plus:SI (reg:SI T_REG)
5973 (match_operand:SI 1 "arith_reg_operand" "r"))))
5974 (set (reg:SI T_REG)
5975 (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
5976 (const_int 0)))]
5977 "TARGET_SH1"
5978 "negc %1,%0"
5979 [(set_attr "type" "arith")])
5980
5981 ;; A simplified version of the negc insn, where the exact value of the
5982 ;; T bit doesn't matter. This is easier for combine to pick up.
5983 ;; Notice that '0 - x - 1' is the same as '~x', thus we don't specify
5984 ;; extra patterns for this case.
5985 (define_insn_and_split "*negc"
5986 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
5987 (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
5988 (match_operand 2 "treg_set_expr")))
5989 (clobber (reg:SI T_REG))]
5990 "TARGET_SH1 && can_create_pseudo_p ()"
5991 "#"
5992 "&& 1"
5993 [(const_int 0)]
5994 {
5995 sh_split_treg_set_expr (operands[2], curr_insn);
5996 emit_insn (gen_negc (operands[0], operands[1]));
5997 DONE;
5998 });
5999
6000 (define_insn "*negdi_media"
6001 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
6002 (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
6003 "TARGET_SHMEDIA"
6004 "sub r63, %1, %0"
6005 [(set_attr "type" "arith_media")])
6006
6007 ;; Don't split into individual negc insns immediately so that neg:DI (abs:DI)
6008 ;; can be combined.
6009 (define_expand "negdi2"
6010 [(parallel [(set (match_operand:DI 0 "arith_reg_dest")
6011 (neg:DI (match_operand:DI 1 "arith_reg_operand")))
6012 (clobber (reg:SI T_REG))])]
6013 "TARGET_SH1")
6014
6015 (define_insn_and_split "*negdi2"
6016 [(set (match_operand:DI 0 "arith_reg_dest")
6017 (neg:DI (match_operand:DI 1 "arith_reg_operand")))
6018 (clobber (reg:SI T_REG))]
6019 "TARGET_SH1"
6020 "#"
6021 "&& can_create_pseudo_p ()"
6022 [(const_int 0)]
6023 {
6024 emit_insn (gen_clrt ());
6025 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
6026 gen_lowpart (SImode, operands[1])));
6027 emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
6028 gen_highpart (SImode, operands[1])));
6029 DONE;
6030 })
6031
6032 (define_insn "negsi2"
6033 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6034 (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
6035 "TARGET_SH1"
6036 "neg %1,%0"
6037 [(set_attr "type" "arith")])
6038
6039 (define_insn_and_split "one_cmplsi2"
6040 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6041 (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
6042 "TARGET_SH1"
6043 "not %1,%0"
6044 "&& can_create_pseudo_p ()"
6045 [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
6046 (set (match_dup 0) (reg:SI T_REG))]
6047 {
6048 /* PR 54685
6049 If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
6050 sequence:
6051
6052 (set (reg0) (not:SI (reg0) (reg1)))
6053 (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
6054 (clobber (reg:SI T_REG))])
6055
6056 ... match and combine the sequence manually in the split pass after the
6057 combine pass. Notice that combine does try the target pattern of this
6058 split, but if the pattern is added it interferes with other patterns, in
6059 particular with the div0s comparisons.
6060 This could also be done with a peephole but doing it here before register
6061 allocation can save one temporary.
6062 When we're here, the not:SI pattern obviously has been matched already
6063 and we only have to see whether the following insn is the left shift. */
6064
6065 rtx_insn *i = next_nonnote_insn_bb (curr_insn);
6066 if (i == NULL_RTX || !NONJUMP_INSN_P (i))
6067 FAIL;
6068
6069 rtx p = PATTERN (i);
6070 if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
6071 FAIL;
6072
6073 rtx p0 = XVECEXP (p, 0, 0);
6074 rtx p1 = XVECEXP (p, 0, 1);
6075
6076 if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */
6077 GET_CODE (p0) == SET
6078 && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
6079 && REG_P (XEXP (XEXP (p0, 1), 0))
6080 && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
6081 && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
6082 && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
6083
6084 /* (clobber (reg:SI T_REG)) */
6085 && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
6086 && REGNO (XEXP (p1, 0)) == T_REG)
6087 {
6088 operands[0] = XEXP (p0, 0);
6089 set_insn_deleted (i);
6090 }
6091 else
6092 FAIL;
6093 }
6094 [(set_attr "type" "arith")])
6095
6096 (define_expand "one_cmpldi2"
6097 [(set (match_operand:DI 0 "arith_reg_dest" "")
6098 (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
6099 (const_int -1)))]
6100 "TARGET_SHMEDIA" "")
6101
6102 (define_expand "abs<mode>2"
6103 [(parallel [(set (match_operand:SIDI 0 "arith_reg_dest")
6104 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
6105 (clobber (reg:SI T_REG))])]
6106 "TARGET_SH1")
6107
6108 (define_insn_and_split "*abs<mode>2"
6109 [(set (match_operand:SIDI 0 "arith_reg_dest")
6110 (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand")))
6111 (clobber (reg:SI T_REG))]
6112 "TARGET_SH1"
6113 "#"
6114 "&& can_create_pseudo_p ()"
6115 [(const_int 0)]
6116 {
6117 if (<MODE>mode == SImode)
6118 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
6119 else
6120 {
6121 rtx high_src = gen_highpart (SImode, operands[1]);
6122 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
6123 }
6124
6125 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
6126 const1_rtx));
6127 DONE;
6128 })
6129
6130 (define_insn_and_split "*negabs<mode>2"
6131 [(set (match_operand:SIDI 0 "arith_reg_dest")
6132 (neg:SIDI (abs:SIDI (match_operand:SIDI 1 "arith_reg_operand"))))
6133 (clobber (reg:SI T_REG))]
6134 "TARGET_SH1"
6135 "#"
6136 "&& can_create_pseudo_p ()"
6137 [(const_int 0)]
6138 {
6139 if (<MODE>mode == SImode)
6140 emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
6141 else
6142 {
6143 rtx high_src = gen_highpart (SImode, operands[1]);
6144 emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
6145 }
6146
6147 emit_insn (gen_neg<mode>_cond (operands[0], operands[1], operands[1],
6148 const0_rtx));
6149 DONE;
6150 })
6151
6152 ;; The SH4 202 can do zero-offset branches without pipeline stalls.
6153 ;; This can be used as some kind of conditional execution, which is useful
6154 ;; for abs.
6155 ;; Actually the instruction scheduling should decide whether to use a
6156 ;; zero-offset branch or not for any generic case involving a single
6157 ;; instruction on SH4 202.
6158 (define_insn_and_split "negsi_cond"
6159 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
6160 (if_then_else
6161 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand" "M,N"))
6162 (match_operand:SI 1 "arith_reg_operand" "0,0")
6163 (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
6164 "TARGET_SH1 && TARGET_ZDCBRANCH"
6165 {
6166 static const char* alt[] =
6167 {
6168 "bt 0f" "\n"
6169 " neg %2,%0" "\n"
6170 "0:",
6171
6172 "bf 0f" "\n"
6173 " neg %2,%0" "\n"
6174 "0:"
6175 };
6176 return alt[which_alternative];
6177 }
6178 "TARGET_SH1 && ! TARGET_ZDCBRANCH"
6179 [(const_int 0)]
6180 {
6181 rtx skip_neg_label = gen_label_rtx ();
6182
6183 emit_move_insn (operands[0], operands[1]);
6184
6185 emit_jump_insn (INTVAL (operands[3])
6186 ? gen_branch_true (skip_neg_label)
6187 : gen_branch_false (skip_neg_label));
6188
6189 emit_label_after (skip_neg_label,
6190 emit_insn (gen_negsi2 (operands[0], operands[1])));
6191 DONE;
6192 }
6193 [(set_attr "type" "arith") ;; poor approximation
6194 (set_attr "length" "4")])
6195
6196 (define_insn_and_split "negdi_cond"
6197 [(set (match_operand:DI 0 "arith_reg_dest")
6198 (if_then_else
6199 (eq:SI (reg:SI T_REG) (match_operand:SI 3 "const_int_operand"))
6200 (match_operand:DI 1 "arith_reg_operand")
6201 (neg:DI (match_operand:DI 2 "arith_reg_operand"))))
6202 (clobber (reg:SI T_REG))]
6203 "TARGET_SH1"
6204 "#"
6205 "&& can_create_pseudo_p ()"
6206 [(const_int 0)]
6207 {
6208 rtx skip_neg_label = gen_label_rtx ();
6209
6210 emit_move_insn (operands[0], operands[1]);
6211
6212 emit_jump_insn (INTVAL (operands[3])
6213 ? gen_branch_true (skip_neg_label)
6214 : gen_branch_false (skip_neg_label));
6215
6216 if (!INTVAL (operands[3]))
6217 emit_insn (gen_clrt ());
6218
6219 emit_insn (gen_negc (gen_lowpart (SImode, operands[0]),
6220 gen_lowpart (SImode, operands[1])));
6221 emit_label_after (skip_neg_label,
6222 emit_insn (gen_negc (gen_highpart (SImode, operands[0]),
6223 gen_highpart (SImode, operands[1]))));
6224 DONE;
6225 })
6226
6227 (define_expand "bswapsi2"
6228 [(set (match_operand:SI 0 "arith_reg_dest" "")
6229 (bswap:SI (match_operand:SI 1 "arith_reg_operand" "")))]
6230 "TARGET_SH1"
6231 {
6232 if (! can_create_pseudo_p ())
6233 FAIL;
6234 else
6235 {
6236 rtx tmp0 = gen_reg_rtx (SImode);
6237 rtx tmp1 = gen_reg_rtx (SImode);
6238
6239 emit_insn (gen_swapbsi2 (tmp0, operands[1]));
6240 emit_insn (gen_rotlsi3_16 (tmp1, tmp0));
6241 emit_insn (gen_swapbsi2 (operands[0], tmp1));
6242 DONE;
6243 }
6244 })
6245
6246 (define_insn "swapbsi2"
6247 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6248 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "r")
6249 (const_int -65536)) ;; 0xFFFF0000
6250 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
6251 (const_int 65280))
6252 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
6253 (const_int 255)))))]
6254 "TARGET_SH1"
6255 "swap.b %1,%0"
6256 [(set_attr "type" "arith")])
6257
6258 ;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
6259 ;; partial byte swap expressions such as...
6260 ;; ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
6261 ;; ...which are currently not handled by the tree optimizers.
6262 ;; The combine pass will not initially try to combine the full expression,
6263 ;; but only some sub-expressions. In such a case the *swapbisi2_and_shl8
6264 ;; pattern acts as an intermediate pattern that will eventually lead combine
6265 ;; to the swapbsi2 pattern above.
6266 ;; As a side effect this also improves code that does (x & 0xFF) << 8
6267 ;; or (x << 8) & 0xFF00.
6268 (define_insn_and_split "*swapbisi2_and_shl8"
6269 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6270 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
6271 (const_int 8))
6272 (const_int 65280))
6273 (match_operand:SI 2 "arith_reg_operand" "r")))]
6274 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
6275 "#"
6276 "&& can_create_pseudo_p ()"
6277 [(const_int 0)]
6278 {
6279 rtx tmp0 = gen_reg_rtx (SImode);
6280 rtx tmp1 = gen_reg_rtx (SImode);
6281
6282 emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
6283 emit_insn (gen_swapbsi2 (tmp1, tmp0));
6284 emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
6285 DONE;
6286 })
6287
6288 ;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
6289 ;; intermediate pattern that will help the combine pass arriving at swapbsi2.
6290 (define_insn_and_split "*swapbhisi2"
6291 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6292 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
6293 (const_int 8))
6294 (const_int 65280))
6295 (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
6296 "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
6297 "#"
6298 "&& can_create_pseudo_p ()"
6299 [(const_int 0)]
6300 {
6301 rtx tmp = gen_reg_rtx (SImode);
6302
6303 emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
6304 emit_insn (gen_swapbsi2 (operands[0], tmp));
6305 DONE;
6306 })
6307
6308 ;; In some cases the swapbsi2 pattern might leave a sequence such as...
6309 ;; swap.b r4,r4
6310 ;; mov r4,r0
6311 ;;
6312 ;; which can be simplified to...
6313 ;; swap.b r4,r0
6314 (define_peephole2
6315 [(set (match_operand:SI 0 "arith_reg_dest" "")
6316 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
6317 (const_int -65536)) ;; 0xFFFF0000
6318 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
6319 (const_int 65280))
6320 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
6321 (const_int 255)))))
6322 (set (match_operand:SI 2 "arith_reg_dest" "")
6323 (match_dup 0))]
6324 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
6325 [(set (match_dup 2)
6326 (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
6327 (const_int -65536)) ;; 0xFFFF0000
6328 (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
6329 (const_int 65280))
6330 (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
6331 (const_int 255)))))])
6332 \f
6333 ;; -------------------------------------------------------------------------
6334 ;; Zero extension instructions
6335 ;; -------------------------------------------------------------------------
6336
6337 (define_insn "zero_extendsidi2"
6338 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
6339 (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))]
6340 "TARGET_SHMEDIA"
6341 "addz.l %1, r63, %0"
6342 [(set_attr "type" "arith_media")
6343 (set_attr "highpart" "extend")])
6344
6345 (define_insn "zero_extendhidi2"
6346 [(set (match_operand:DI 0 "register_operand" "=r,r")
6347 (zero_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6348 "TARGET_SHMEDIA"
6349 "@
6350 #
6351 ld%M1.uw %m1, %0"
6352 [(set_attr "type" "*,load_media")
6353 (set (attr "highpart")
6354 (cond [(match_test "sh_contains_memref_p (insn)")
6355 (const_string "user")]
6356 (const_string "ignore")))])
6357
6358 (define_split
6359 [(set (match_operand:DI 0 "register_operand" "")
6360 (zero_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6361 "TARGET_SHMEDIA && reload_completed"
6362 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6363 (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
6364 {
6365 if (GET_CODE (operands[1]) == TRUNCATE)
6366 operands[1] = XEXP (operands[1], 0);
6367 })
6368
6369 ;; ??? when a truncated input to a zero_extend is reloaded, reload will
6370 ;; reload the entire truncate expression.
6371 (define_insn_and_split "*loaddi_trunc"
6372 [(set (match_operand 0 "any_register_operand" "=r")
6373 (truncate (match_operand:DI 1 "memory_operand" "m")))]
6374 "TARGET_SHMEDIA && reload_completed"
6375 "#"
6376 "TARGET_SHMEDIA && reload_completed"
6377 [(set (match_dup 0) (match_dup 1))]
6378 {
6379 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
6380 })
6381
6382 (define_insn "zero_extendqidi2"
6383 [(set (match_operand:DI 0 "register_operand" "=r,r")
6384 (zero_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6385 "TARGET_SHMEDIA"
6386 "@
6387 andi %1, 255, %0
6388 ld%M1.ub %m1, %0"
6389 [(set_attr "type" "arith_media,load_media")
6390 (set (attr "highpart")
6391 (cond [(match_test "sh_contains_memref_p (insn)")
6392 (const_string "user")]
6393 (const_string "ignore")))])
6394
6395 (define_expand "zero_extend<mode>si2"
6396 [(set (match_operand:SI 0 "arith_reg_dest")
6397 (zero_extend:SI (match_operand:QIHI 1 "zero_extend_operand")))])
6398
6399 (define_insn_and_split "*zero_extend<mode>si2_compact"
6400 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6401 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6402 "TARGET_SH1"
6403 "extu.<bw> %1,%0"
6404 "&& can_create_pseudo_p ()"
6405 [(set (match_dup 0) (match_dup 2))]
6406 {
6407 /* Sometimes combine fails to combine a T bit or negated T bit store to a
6408 reg with a following zero extension. In the split pass after combine,
6409 try to figure out how the extended reg was set. If it originated from
6410 the T bit we can replace the zero extension with a reg move, which will
6411 be eliminated. Notice that this also helps the *cbranch_t splitter when
6412 it tries to post-combine tests and conditional branches, as it does not
6413 check for zero extensions. */
6414 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6415 if (operands[2] == NULL_RTX)
6416 FAIL;
6417 }
6418 [(set_attr "type" "arith")])
6419
6420 (define_insn "*zero_extendhisi2_media"
6421 [(set (match_operand:SI 0 "register_operand" "=r,r")
6422 (zero_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6423 "TARGET_SHMEDIA"
6424 "@
6425 #
6426 ld%M1.uw %m1, %0"
6427 [(set_attr "type" "arith_media,load_media")
6428 (set (attr "highpart")
6429 (cond [(match_test "sh_contains_memref_p (insn)")
6430 (const_string "user")]
6431 (const_string "ignore")))])
6432
6433 (define_split
6434 [(set (match_operand:SI 0 "register_operand" "")
6435 (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6436 "TARGET_SHMEDIA && reload_completed"
6437 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6438 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
6439 {
6440 rtx op1 = operands[1];
6441
6442 if (GET_CODE (op1) == TRUNCATE)
6443 op1 = XEXP (op1, 0);
6444 operands[2]
6445 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6446 subreg_lowpart_offset (SImode, GET_MODE (op1)));
6447 })
6448
6449 (define_insn "*zero_extendqisi2_media"
6450 [(set (match_operand:SI 0 "register_operand" "=r,r")
6451 (zero_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6452 "TARGET_SHMEDIA"
6453 "@
6454 andi %1, 255, %0
6455 ld%M1.ub %m1, %0"
6456 [(set_attr "type" "arith_media,load_media")
6457 (set (attr "highpart")
6458 (cond [(match_test "sh_contains_memref_p (insn)")
6459 (const_string "user")]
6460 (const_string "ignore")))])
6461
6462 (define_insn "zero_extendqihi2"
6463 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6464 (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6465 "TARGET_SH1"
6466 "extu.b %1,%0"
6467 [(set_attr "type" "arith")])
6468
6469 ;; SH2A supports two zero extending load instructions: movu.b and movu.w.
6470 ;; They could also be used for simple memory addresses like @Rn by setting
6471 ;; the displacement value to zero. However, doing so too early results in
6472 ;; missed opportunities for other optimizations such as post-inc or index
6473 ;; addressing loads.
6474 ;; We don't allow the zero extending loads to match during RTL expansion
6475 ;; (see zero_extend_operand predicate), as this would pessimize other
6476 ;; optimization opportunities such as bit extractions of unsigned mems,
6477 ;; where the zero extraction is irrelevant. If the zero extracting mem
6478 ;; loads are emitted early it will be more difficult to change them back
6479 ;; to sign extending loads (which are preferred).
6480 ;; The combine pass will also try to combine mem loads and zero extends,
6481 ;; which is prevented by 'sh_legitimate_combined_insn'.
6482 (define_insn "*zero_extend<mode>si2_disp_mem"
6483 [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
6484 (zero_extend:SI
6485 (match_operand:QIHI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
6486 "TARGET_SH2A"
6487 "@
6488 movu.<bw> %1,%0
6489 movu.<bw> @(0,%t1),%0"
6490 [(set_attr "type" "load")
6491 (set_attr "length" "4")])
6492
6493 ;; Convert the zero extending loads in sequences such as:
6494 ;; movu.b @(1,r5),r0 movu.w @(2,r5),r0
6495 ;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
6496 ;;
6497 ;; back to sign extending loads like:
6498 ;; mov.b @(1,r5),r0 mov.w @(2,r5),r0
6499 ;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
6500 ;;
6501 ;; if the extension type is irrelevant. The sign extending mov.{b|w} insn
6502 ;; is only 2 bytes in size if the displacement is {K04|K05}.
6503 ;; If the displacement is greater it doesn't matter, so we convert anyways.
6504 (define_peephole2
6505 [(set (match_operand:SI 0 "arith_reg_dest" "")
6506 (zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
6507 (set (match_operand 2 "nonimmediate_operand" "")
6508 (match_operand 3 "arith_reg_operand" ""))]
6509 "TARGET_SH2A
6510 && REGNO (operands[0]) == REGNO (operands[3])
6511 && peep2_reg_dead_p (2, operands[0])
6512 && GET_MODE_SIZE (GET_MODE (operands[2]))
6513 <= GET_MODE_SIZE (GET_MODE (operands[1]))"
6514 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
6515 (set (match_dup 2) (match_dup 3))])
6516
6517 ;; Fold sequences such as
6518 ;; mov.b @r3,r7
6519 ;; extu.b r7,r7
6520 ;; into
6521 ;; movu.b @(0,r3),r7
6522 ;; This does not reduce the code size but the number of instructions is
6523 ;; halved, which results in faster code.
6524 (define_peephole2
6525 [(set (match_operand:SI 0 "arith_reg_dest" "")
6526 (sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
6527 (set (match_operand:SI 2 "arith_reg_dest" "")
6528 (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
6529 "TARGET_SH2A
6530 && GET_MODE (operands[1]) == GET_MODE (operands[3])
6531 && (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
6532 && REGNO (operands[0]) == REGNO (operands[3])
6533 && (REGNO (operands[2]) == REGNO (operands[0])
6534 || peep2_reg_dead_p (2, operands[0]))"
6535 [(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
6536 {
6537 operands[4]
6538 = replace_equiv_address (operands[1],
6539 gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
6540 const0_rtx));
6541 })
6542
6543 ;; -------------------------------------------------------------------------
6544 ;; Sign extension instructions
6545 ;; -------------------------------------------------------------------------
6546
6547 ;; ??? This should be a define expand.
6548 ;; ??? Or perhaps it should be dropped?
6549
6550 ;; convert_move generates good code for SH[1-4].
6551 (define_insn "extendsidi2"
6552 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
6553 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))]
6554 "TARGET_SHMEDIA"
6555 "@
6556 add.l %1, r63, %0
6557 ld%M1.l %m1, %0
6558 fmov.sl %1, %0"
6559 [(set_attr "type" "arith_media,load_media,fpconv_media")
6560 (set (attr "highpart")
6561 (cond [(match_test "sh_contains_memref_p (insn)")
6562 (const_string "user")]
6563 (const_string "extend")))])
6564
6565 (define_insn "extendhidi2"
6566 [(set (match_operand:DI 0 "register_operand" "=r,r")
6567 (sign_extend:DI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6568 "TARGET_SHMEDIA"
6569 "@
6570 #
6571 ld%M1.w %m1, %0"
6572 [(set_attr "type" "*,load_media")
6573 (set (attr "highpart")
6574 (cond [(match_test "sh_contains_memref_p (insn)")
6575 (const_string "user")]
6576 (const_string "ignore")))])
6577
6578 (define_split
6579 [(set (match_operand:DI 0 "register_operand" "")
6580 (sign_extend:DI (match_operand:HI 1 "extend_reg_operand" "")))]
6581 "TARGET_SHMEDIA && reload_completed"
6582 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
6583 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
6584 {
6585 if (GET_CODE (operands[1]) == TRUNCATE)
6586 operands[1] = XEXP (operands[1], 0);
6587 })
6588
6589 (define_insn "extendqidi2"
6590 [(set (match_operand:DI 0 "register_operand" "=r,r")
6591 (sign_extend:DI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6592 "TARGET_SHMEDIA"
6593 "@
6594 #
6595 ld%M1.b %m1, %0"
6596 [(set_attr "type" "*,load_media")
6597 (set (attr "highpart")
6598 (cond [(match_test "sh_contains_memref_p (insn)")
6599 (const_string "user")]
6600 (const_string "ignore")))])
6601
6602 (define_split
6603 [(set (match_operand:DI 0 "register_operand" "")
6604 (sign_extend:DI (match_operand:QI 1 "extend_reg_operand" "")))]
6605 "TARGET_SHMEDIA && reload_completed"
6606 [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
6607 (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
6608 {
6609 if (GET_CODE (operands[1]) == TRUNCATE)
6610 operands[1] = XEXP (operands[1], 0);
6611 })
6612
6613 (define_expand "extend<mode>si2"
6614 [(set (match_operand:SI 0 "arith_reg_dest")
6615 (sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
6616
6617 (define_insn "*extendhisi2_media"
6618 [(set (match_operand:SI 0 "register_operand" "=r,r")
6619 (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))]
6620 "TARGET_SHMEDIA"
6621 "@
6622 #
6623 ld%M1.w %m1, %0"
6624 [(set_attr "type" "arith_media,load_media")
6625 (set (attr "highpart")
6626 (cond [(match_test "sh_contains_memref_p (insn)")
6627 (const_string "user")]
6628 (const_string "ignore")))])
6629
6630 (define_split
6631 [(set (match_operand:SI 0 "register_operand" "")
6632 (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))]
6633 "TARGET_SHMEDIA && reload_completed"
6634 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
6635 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
6636 {
6637 rtx op1 = operands[1];
6638 if (GET_CODE (op1) == TRUNCATE)
6639 op1 = XEXP (op1, 0);
6640 operands[2]
6641 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6642 subreg_lowpart_offset (SImode, GET_MODE (op1)));
6643 })
6644
6645 (define_insn_and_split "*extend<mode>si2_compact_reg"
6646 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6647 (sign_extend:SI (match_operand:QIHI 1 "arith_reg_operand" "r")))]
6648 "TARGET_SH1"
6649 "exts.<bw> %1,%0"
6650 "&& can_create_pseudo_p ()"
6651 [(set (match_dup 0) (match_dup 2))]
6652 {
6653 /* Sometimes combine fails to combine a T bit or negated T bit store to a
6654 reg with a following sign extension. In the split pass after combine,
6655 try to figure the extended reg was set. If it originated from the T
6656 bit we can replace the sign extension with a reg move, which will be
6657 eliminated. */
6658 operands[2] = sh_try_omit_signzero_extend (operands[1], curr_insn);
6659 if (operands[2] == NULL_RTX)
6660 FAIL;
6661 }
6662 [(set_attr "type" "arith")])
6663
6664 ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
6665 ;; See movqi insns.
6666 (define_insn "*extend<mode>si2_compact_mem_disp"
6667 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
6668 (sign_extend:SI
6669 (mem:QIHI
6670 (plus:SI
6671 (match_operand:SI 1 "arith_reg_operand" "%r,r")
6672 (match_operand:SI 2 "const_int_operand" "<disp04>,N")))))]
6673 "TARGET_SH1 && ! TARGET_SH2A
6674 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
6675 "@
6676 mov.<bw> @(%O2,%1),%0
6677 mov.<bw> @%1,%0"
6678 [(set_attr "type" "load")])
6679
6680 (define_insn "*extend<mode>si2_compact_mem_disp"
6681 [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
6682 (sign_extend:SI
6683 (mem:QIHI
6684 (plus:SI
6685 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
6686 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>")))))]
6687 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
6688 "@
6689 mov.<bw> @(%O2,%1),%0
6690 mov.<bw> @%1,%0
6691 mov.<bw> @(%O2,%1),%0"
6692 [(set_attr "type" "load")
6693 (set_attr "length" "2,2,4")])
6694
6695 ;; The *_snd patterns will take care of other QImode/HImode addressing
6696 ;; modes than displacement addressing. They must be defined _after_ the
6697 ;; displacement addressing patterns. Otherwise the displacement addressing
6698 ;; patterns will not be picked.
6699 (define_insn "*extend<mode>si2_compact_snd"
6700 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6701 (sign_extend:SI
6702 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand" "Snd")))]
6703 "TARGET_SH1"
6704 "mov.<bw> %1,%0"
6705 [(set_attr "type" "load")])
6706
6707 (define_insn "*extendqisi2_media"
6708 [(set (match_operand:SI 0 "register_operand" "=r,r")
6709 (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
6710 "TARGET_SHMEDIA"
6711 "@
6712 #
6713 ld%M1.b %m1, %0"
6714 [(set_attr "type" "arith_media,load_media")
6715 (set (attr "highpart")
6716 (cond [(match_test "sh_contains_memref_p (insn)")
6717 (const_string "user")]
6718 (const_string "ignore")))])
6719
6720 (define_split
6721 [(set (match_operand:SI 0 "register_operand" "")
6722 (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))]
6723 "TARGET_SHMEDIA && reload_completed"
6724 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
6725 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
6726 {
6727 rtx op1 = operands[1];
6728 if (GET_CODE (op1) == TRUNCATE)
6729 op1 = XEXP (op1, 0);
6730 operands[2]
6731 = simplify_gen_subreg (SImode, op1, GET_MODE (op1),
6732 subreg_lowpart_offset (SImode, GET_MODE (op1)));
6733 })
6734
6735 (define_expand "extendqihi2"
6736 [(set (match_operand:HI 0 "arith_reg_dest")
6737 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))]
6738 "TARGET_SH1")
6739
6740 (define_insn "*extendqihi2_compact_reg"
6741 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
6742 (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
6743 "TARGET_SH1"
6744 "exts.b %1,%0"
6745 [(set_attr "type" "arith")])
6746
6747 ;; It would seem useful to combine the truncXi patterns into the movXi
6748 ;; patterns, but unary operators are ignored when matching constraints,
6749 ;; so we need separate patterns.
6750 (define_insn "truncdisi2"
6751 [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
6752 (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
6753 "TARGET_SHMEDIA"
6754 "@
6755 add.l %1, r63, %0
6756 st%M0.l %m0, %1
6757 fst%M0.s %m0, %T1
6758 fmov.ls %1, %0
6759 fmov.sl %T1, %0
6760 fmov.s %T1, %0"
6761 [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,
6762 fpconv_media,fmove_media")
6763 (set (attr "highpart")
6764 (cond [(match_test "sh_contains_memref_p (insn)")
6765 (const_string "user")]
6766 (const_string "extend")))])
6767
6768 (define_insn "truncdihi2"
6769 [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
6770 (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
6771 "TARGET_SHMEDIA"
6772 {
6773 static const char* alt[] =
6774 {
6775 "shlli %1,48,%0" "\n"
6776 " shlri %0,48,%0",
6777
6778 "st%M0.w %m0, %1"
6779 };
6780 return alt[which_alternative];
6781 }
6782 [(set_attr "type" "arith_media,store_media")
6783 (set_attr "length" "8,4")
6784 (set (attr "highpart")
6785 (cond [(match_test "sh_contains_memref_p (insn)")
6786 (const_string "user")]
6787 (const_string "extend")))])
6788
6789 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
6790 ; Because we use zero extension, we can't provide signed QImode compares
6791 ; using a simple compare or conditional branch insn.
6792 (define_insn "truncdiqi2"
6793 [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
6794 (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
6795 "TARGET_SHMEDIA"
6796 "@
6797 andi %1, 255, %0
6798 st%M0.b %m0, %1"
6799 [(set_attr "type" "arith_media,store")
6800 (set (attr "highpart")
6801 (cond [(match_test "sh_contains_memref_p (insn)")
6802 (const_string "user")]
6803 (const_string "extend")))])
6804
6805 ;; -------------------------------------------------------------------------
6806 ;; Move instructions
6807 ;; -------------------------------------------------------------------------
6808
6809 ;; define push and pop so it is easy for sh.c
6810 ;; We can't use push and pop on SHcompact because the stack must always
6811 ;; be 8-byte aligned.
6812 (define_expand "push"
6813 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
6814 (match_operand:SI 0 "register_operand" "r,l,x"))]
6815 "TARGET_SH1 && ! TARGET_SH5"
6816 "")
6817
6818 (define_expand "pop"
6819 [(set (match_operand:SI 0 "register_operand" "=r,l,x")
6820 (mem:SI (post_inc:SI (reg:SI SP_REG))))]
6821 "TARGET_SH1 && ! TARGET_SH5"
6822 "")
6823
6824 (define_expand "push_e"
6825 [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
6826 (match_operand:SF 0 "" ""))
6827 (use (reg:SI FPSCR_MODES_REG))
6828 (clobber (scratch:SI))])]
6829 "TARGET_SH1 && ! TARGET_SH5"
6830 "")
6831
6832 (define_insn "push_fpul"
6833 [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
6834 "TARGET_SH2E && ! TARGET_SH5"
6835 "sts.l fpul,@-r15"
6836 [(set_attr "type" "fstore")
6837 (set_attr "late_fp_use" "yes")
6838 (set_attr "hit_stack" "yes")])
6839
6840 ;; DFmode pushes for sh4 require a lot of what is defined for movdf_i4,
6841 ;; so use that.
6842 (define_expand "push_4"
6843 [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
6844 (match_operand:DF 0 "" ""))
6845 (use (reg:SI FPSCR_MODES_REG))
6846 (clobber (scratch:SI))])]
6847 "TARGET_SH1 && ! TARGET_SH5"
6848 "")
6849
6850 (define_expand "pop_e"
6851 [(parallel [(set (match_operand:SF 0 "" "")
6852 (mem:SF (post_inc:SI (reg:SI SP_REG))))
6853 (use (reg:SI FPSCR_MODES_REG))
6854 (clobber (scratch:SI))])]
6855 "TARGET_SH1 && ! TARGET_SH5"
6856 "")
6857
6858 (define_insn "pop_fpul"
6859 [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
6860 "TARGET_SH2E && ! TARGET_SH5"
6861 "lds.l @r15+,fpul"
6862 [(set_attr "type" "load")
6863 (set_attr "hit_stack" "yes")])
6864
6865 (define_expand "pop_4"
6866 [(parallel [(set (match_operand:DF 0 "" "")
6867 (mem:DF (post_inc:SI (reg:SI SP_REG))))
6868 (use (reg:SI FPSCR_MODES_REG))
6869 (clobber (scratch:SI))])]
6870 "TARGET_SH1 && ! TARGET_SH5"
6871 "")
6872
6873 (define_expand "push_fpscr"
6874 [(const_int 0)]
6875 "TARGET_SH2E"
6876 {
6877 add_reg_note (
6878 emit_insn (
6879 gen_sts_fpscr (
6880 gen_frame_mem (SImode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx)))),
6881 REG_INC, stack_pointer_rtx);
6882 DONE;
6883 })
6884
6885 (define_expand "pop_fpscr"
6886 [(const_int 0)]
6887 "TARGET_SH2E"
6888 {
6889 add_reg_note (
6890 emit_insn (
6891 gen_lds_fpscr (
6892 gen_frame_mem (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)))),
6893 REG_INC, stack_pointer_rtx);
6894 DONE;
6895 })
6896
6897 ;; The clrt and sett patterns can happen as the result of optimization and
6898 ;; insn expansion.
6899 ;; Comparisons might get simplified to a move of zero or 1 into the T reg.
6900 ;; In this case they might not disappear completely, because the T reg is
6901 ;; a fixed hard reg.
6902 ;; When DImode operations that use the T reg as carry/borrow are split into
6903 ;; individual SImode operations, the T reg is usually cleared before the
6904 ;; first SImode insn.
6905 (define_insn "clrt"
6906 [(set (reg:SI T_REG) (const_int 0))]
6907 "TARGET_SH1"
6908 "clrt"
6909 [(set_attr "type" "mt_group")])
6910
6911 (define_insn "sett"
6912 [(set (reg:SI T_REG) (const_int 1))]
6913 "TARGET_SH1"
6914 "sett"
6915 [(set_attr "type" "mt_group")])
6916
6917 ;; Use the combine pass to transform sequences such as
6918 ;; mov r5,r0
6919 ;; add #1,r0
6920 ;; shll2 r0
6921 ;; mov.l @(r0,r4),r0
6922 ;; into
6923 ;; shll2 r5
6924 ;; add r4,r5
6925 ;; mov.l @(4,r5),r0
6926 ;;
6927 ;; See also PR 39423.
6928 ;; Notice that these patterns have a T_REG clobber, because the shift
6929 ;; sequence that will be split out might clobber the T_REG. Ideally, the
6930 ;; clobber would be added conditionally, depending on the result of
6931 ;; sh_ashlsi_clobbers_t_reg_p. When splitting out the shifts we must go
6932 ;; through the ashlsi3 expander in order to get the right shift insn --
6933 ;; a T_REG clobbering or non-clobbering shift sequence or dynamic shift.
6934 ;; FIXME: Combine never tries this kind of patterns for DImode.
6935 (define_insn_and_split "*movsi_index_disp_load"
6936 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
6937 (match_operand:SI 1 "mem_index_disp_operand" "m"))
6938 (clobber (reg:SI T_REG))]
6939 "TARGET_SH1"
6940 "#"
6941 "&& can_create_pseudo_p ()"
6942 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
6943 (set (match_dup 0) (match_dup 7))]
6944 {
6945 rtx mem = operands[1];
6946 rtx plus0_rtx = XEXP (mem, 0);
6947 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6948 rtx mult_rtx = XEXP (plus1_rtx, 0);
6949
6950 operands[1] = XEXP (mult_rtx, 0);
6951 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6952 operands[3] = XEXP (plus1_rtx, 1);
6953 operands[4] = XEXP (plus0_rtx, 1);
6954 operands[5] = gen_reg_rtx (SImode);
6955 operands[6] = gen_reg_rtx (SImode);
6956 operands[7] =
6957 replace_equiv_address (mem,
6958 gen_rtx_PLUS (SImode, operands[6], operands[4]));
6959
6960 emit_insn (gen_ashlsi3 (operands[5], operands[1], operands[2]));
6961 })
6962
6963 (define_insn_and_split "*movhi_index_disp_load"
6964 [(set (match_operand:SI 0 "arith_reg_dest")
6965 (SZ_EXTEND:SI (match_operand:HI 1 "mem_index_disp_operand")))
6966 (clobber (reg:SI T_REG))]
6967 "TARGET_SH1"
6968 "#"
6969 "&& can_create_pseudo_p ()"
6970 [(const_int 0)]
6971 {
6972 rtx mem = operands[1];
6973 rtx plus0_rtx = XEXP (mem, 0);
6974 rtx plus1_rtx = XEXP (plus0_rtx, 0);
6975 rtx mult_rtx = XEXP (plus1_rtx, 0);
6976
6977 rtx op_1 = XEXP (mult_rtx, 0);
6978 rtx op_2 = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
6979 rtx op_3 = XEXP (plus1_rtx, 1);
6980 rtx op_4 = XEXP (plus0_rtx, 1);
6981 rtx op_5 = gen_reg_rtx (SImode);
6982 rtx op_6 = gen_reg_rtx (SImode);
6983 rtx op_7 = replace_equiv_address (mem, gen_rtx_PLUS (SImode, op_6, op_4));
6984
6985 emit_insn (gen_ashlsi3 (op_5, op_1, op_2));
6986 emit_insn (gen_addsi3 (op_6, op_5, op_3));
6987
6988 if (<CODE> == SIGN_EXTEND)
6989 {
6990 emit_insn (gen_extendhisi2 (operands[0], op_7));
6991 DONE;
6992 }
6993 else if (<CODE> == ZERO_EXTEND)
6994 {
6995 /* On SH2A the movu.w insn can be used for zero extending loads. */
6996 if (TARGET_SH2A)
6997 emit_insn (gen_zero_extendhisi2 (operands[0], op_7));
6998 else
6999 {
7000 emit_insn (gen_extendhisi2 (operands[0], op_7));
7001 emit_insn (gen_zero_extendhisi2 (operands[0],
7002 gen_lowpart (HImode, operands[0])));
7003 }
7004 DONE;
7005 }
7006 else
7007 FAIL;
7008 })
7009
7010 (define_insn_and_split "*mov<mode>_index_disp_store"
7011 [(set (match_operand:HISI 0 "mem_index_disp_operand" "=m")
7012 (match_operand:HISI 1 "arith_reg_operand" "r"))
7013 (clobber (reg:SI T_REG))]
7014 "TARGET_SH1"
7015 "#"
7016 "&& can_create_pseudo_p ()"
7017 [(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
7018 (set (match_dup 7) (match_dup 1))]
7019 {
7020 rtx mem = operands[0];
7021 rtx plus0_rtx = XEXP (mem, 0);
7022 rtx plus1_rtx = XEXP (plus0_rtx, 0);
7023 rtx mult_rtx = XEXP (plus1_rtx, 0);
7024
7025 operands[0] = XEXP (mult_rtx, 0);
7026 operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
7027 operands[3] = XEXP (plus1_rtx, 1);
7028 operands[4] = XEXP (plus0_rtx, 1);
7029 operands[5] = gen_reg_rtx (SImode);
7030 operands[6] = gen_reg_rtx (SImode);
7031 operands[7] =
7032 replace_equiv_address (mem,
7033 gen_rtx_PLUS (SImode, operands[6], operands[4]));
7034
7035 emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
7036 })
7037
7038 ;; t/r must come after r/r, lest reload will try to reload stuff like
7039 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
7040 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
7041 (define_insn "movsi_i"
7042 [(set (match_operand:SI 0 "general_movdst_operand"
7043 "=r,r,r,r,r,r,m,<,<,x,l,x,l,r")
7044 (match_operand:SI 1 "general_movsrc_operand"
7045 "Q,r,I08,mr,x,l,r,x,l,r,r,>,>,i"))]
7046 "TARGET_SH1
7047 && ! TARGET_SH2E
7048 && ! TARGET_SH2A
7049 && (register_operand (operands[0], SImode)
7050 || register_operand (operands[1], SImode))"
7051 "@
7052 mov.l %1,%0
7053 mov %1,%0
7054 mov %1,%0
7055 mov.l %1,%0
7056 sts %1,%0
7057 sts %1,%0
7058 mov.l %1,%0
7059 sts.l %1,%0
7060 sts.l %1,%0
7061 lds %1,%0
7062 lds %1,%0
7063 lds.l %1,%0
7064 lds.l %1,%0
7065 fake %1,%0"
7066 [(set_attr "type" "pcload_si,move,movi8,load_si,mac_gp,prget,store,mac_mem,
7067 pstore,gp_mac,prset,mem_mac,pload,pcload_si")
7068 (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
7069
7070 ;; t/r must come after r/r, lest reload will try to reload stuff like
7071 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
7072 ;; ??? This allows moves from macl to fpul to be recognized, but these moves
7073 ;; will require a reload.
7074 ;; ??? We can't include f/f because we need the proper FPSCR setting when
7075 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
7076 (define_insn "movsi_ie"
7077 [(set (match_operand:SI 0 "general_movdst_operand"
7078 "=r,r,r,r,r,r,r,r,mr,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
7079 (match_operand:SI 1 "general_movsrc_operand"
7080 "Q,r,I08,I20,I28,mr,x,l,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
7081 "(TARGET_SH2E || TARGET_SH2A)
7082 && ((register_operand (operands[0], SImode)
7083 && !fpscr_operand (operands[0], SImode))
7084 || (register_operand (operands[1], SImode)
7085 && !fpscr_operand (operands[1], SImode)))"
7086 "@
7087 mov.l %1,%0
7088 mov %1,%0
7089 mov %1,%0
7090 movi20 %1,%0
7091 movi20s %1,%0
7092 mov.l %1,%0
7093 sts %1,%0
7094 sts %1,%0
7095 mov.l %1,%0
7096 sts.l %1,%0
7097 sts.l %1,%0
7098 lds %1,%0
7099 lds %1,%0
7100 lds.l %1,%0
7101 lds.l %1,%0
7102 lds.l %1,%0
7103 sts.l %1,%0
7104 fake %1,%0
7105 lds %1,%0
7106 sts %1,%0
7107 fsts fpul,%0
7108 flds %1,fpul
7109 fmov %1,%0
7110 ! move optimized away"
7111 [(set_attr "type" "pcload_si,move,movi8,move,move,load_si,mac_gp,prget,store,
7112 mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,
7113 pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
7114 (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
7115 (set_attr_alternative "length"
7116 [(const_int 2)
7117 (const_int 2)
7118 (const_int 2)
7119 (const_int 4)
7120 (const_int 4)
7121 (if_then_else
7122 (match_test "TARGET_SH2A")
7123 (const_int 4) (const_int 2))
7124 (const_int 2)
7125 (const_int 2)
7126 (if_then_else
7127 (match_test "TARGET_SH2A")
7128 (const_int 4) (const_int 2))
7129 (const_int 2)
7130 (const_int 2)
7131 (const_int 2)
7132 (const_int 2)
7133 (const_int 2)
7134 (const_int 2)
7135 (const_int 2)
7136 (const_int 2)
7137 (const_int 2)
7138 (const_int 2)
7139 (const_int 2)
7140 (const_int 2)
7141 (const_int 2)
7142 (const_int 2)
7143 (const_int 0)])])
7144
7145 (define_insn "movsi_i_lowpart"
7146 [(set (strict_low_part
7147 (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
7148 (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,r,i"))]
7149 "TARGET_SH1
7150 && (register_operand (operands[0], SImode)
7151 || register_operand (operands[1], SImode))"
7152 "@
7153 mov.l %1,%0
7154 mov %1,%0
7155 mov %1,%0
7156 mov.l %1,%0
7157 sts %1,%0
7158 sts %1,%0
7159 mov.l %1,%0
7160 fake %1,%0"
7161 [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,store,pcload")])
7162
7163 (define_insn_and_split "load_ra"
7164 [(set (match_operand:SI 0 "general_movdst_operand" "")
7165 (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))]
7166 "TARGET_SH1"
7167 "#"
7168 "&& ! currently_expanding_to_rtl"
7169 [(set (match_dup 0) (match_dup 1))]
7170 {
7171 if (TARGET_SHCOMPACT && crtl->saves_all_registers)
7172 operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
7173 })
7174
7175 ;; The '?'s in the following constraints may not reflect the time taken
7176 ;; to perform the move. They are there to discourage the use of floating-
7177 ;; point registers for storing integer values.
7178 (define_insn "*movsi_media"
7179 [(set (match_operand:SI 0 "general_movdst_operand"
7180 "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b")
7181 (match_operand:SI 1 "general_movsrc_operand"
7182 "r,I16Css,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7183 "TARGET_SHMEDIA_FPU
7184 && (register_operand (operands[0], SImode)
7185 || sh_register_operand (operands[1], SImode)
7186 || GET_CODE (operands[1]) == TRUNCATE)"
7187 "@
7188 add.l %1, r63, %0
7189 movi %1, %0
7190 #
7191 ld%M1.l %m1, %0
7192 st%M0.l %m0, %N1
7193 fld%M1.s %m1, %0
7194 fst%M0.s %m0, %1
7195 fmov.ls %N1, %0
7196 fmov.sl %1, %0
7197 fmov.s %1, %0
7198 ptabs %1, %0
7199 gettr %1, %0
7200 pt %1, %0"
7201 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7202 fload_media,fstore_media,fload_media,fpconv_media,
7203 fmove_media,ptabs_media,gettr_media,pt_media")
7204 (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
7205 (set (attr "highpart")
7206 (cond [(match_test "sh_contains_memref_p (insn)")
7207 (const_string "user")]
7208 (const_string "ignore")))])
7209
7210 (define_insn "*movsi_media_nofpu"
7211 [(set (match_operand:SI 0 "general_movdst_operand"
7212 "=r,r,r,r,m,*b,r,*b")
7213 (match_operand:SI 1 "general_movsrc_operand"
7214 "r,I16Css,nCpg,m,rZ,r,*b,Csy"))]
7215 "TARGET_SHMEDIA
7216 && (register_operand (operands[0], SImode)
7217 || sh_register_operand (operands[1], SImode)
7218 || GET_CODE (operands[1]) == TRUNCATE)"
7219 "@
7220 add.l %1, r63, %0
7221 movi %1, %0
7222 #
7223 ld%M1.l %m1, %0
7224 st%M0.l %m0, %N1
7225 ptabs %1, %0
7226 gettr %1, %0
7227 pt %1, %0"
7228 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7229 ptabs_media,gettr_media,pt_media")
7230 (set_attr "length" "4,4,8,4,4,4,4,12")
7231 (set (attr "highpart")
7232 (cond [(match_test "sh_contains_memref_p (insn)")
7233 (const_string "user")]
7234 (const_string "ignore")))])
7235
7236 (define_expand "movsi_const"
7237 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7238 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
7239 (const_int 16)] UNSPEC_EXTRACT_S16)))
7240 (set (match_dup 0)
7241 (ior:SI (ashift:SI (match_dup 0) (const_int 16))
7242 (const:SI (unspec:SI [(match_dup 1)
7243 (const_int 0)] UNSPEC_EXTRACT_U16))))]
7244 "TARGET_SHMEDIA && reload_completed
7245 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7246 {
7247 if (GET_CODE (operands[1]) == LABEL_REF
7248 && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
7249 LABEL_NUSES (XEXP (operands[1], 0)) += 2;
7250 else if (GOTOFF_P (operands[1]))
7251 {
7252 rtx unspec = XEXP (operands[1], 0);
7253
7254 if (! UNSPEC_GOTOFF_P (unspec))
7255 {
7256 unspec = XEXP (unspec, 0);
7257 if (! UNSPEC_GOTOFF_P (unspec))
7258 abort ();
7259 }
7260 if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF
7261 && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL))
7262 LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2;
7263 }
7264 })
7265
7266 (define_expand "movsi_const_16bit"
7267 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
7268 (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
7269 (const_int 0)] UNSPEC_EXTRACT_S16)))]
7270 "TARGET_SHMEDIA && flag_pic && reload_completed
7271 && GET_CODE (operands[1]) == SYMBOL_REF"
7272 "")
7273
7274 (define_split
7275 [(set (match_operand:SI 0 "arith_reg_dest" "")
7276 (match_operand:SI 1 "immediate_operand" ""))]
7277 "TARGET_SHMEDIA && reload_completed
7278 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7279 [(const_int 0)]
7280 {
7281 rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
7282
7283 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7284
7285 DONE;
7286 })
7287
7288 (define_split
7289 [(set (match_operand:SI 0 "register_operand" "")
7290 (match_operand:SI 1 "immediate_operand" ""))]
7291 "TARGET_SHMEDIA && reload_completed
7292 && ((CONST_INT_P (operands[1])
7293 && ! satisfies_constraint_I16 (operands[1]))
7294 || GET_CODE (operands[1]) == CONST_DOUBLE)"
7295 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7296
7297 (define_expand "movsi"
7298 [(set (match_operand:SI 0 "general_movdst_operand" "")
7299 (match_operand:SI 1 "general_movsrc_operand" ""))]
7300 ""
7301 {
7302 prepare_move_operands (operands, SImode);
7303 })
7304
7305 (define_expand "ic_invalidate_line"
7306 [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
7307 (match_dup 1)] UNSPEC_ICACHE)
7308 (clobber (scratch:SI))])]
7309 "TARGET_HARD_SH4 || TARGET_SH5"
7310 {
7311 if (TARGET_SHMEDIA)
7312 {
7313 emit_insn (gen_ic_invalidate_line_media (operands[0]));
7314 DONE;
7315 }
7316 else if (TARGET_SHCOMPACT)
7317 {
7318 operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC);
7319 operands[1] = force_reg (Pmode, operands[1]);
7320 emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
7321 DONE;
7322 }
7323 else if (TARGET_SH4A || TARGET_SH4_300)
7324 {
7325 emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
7326 DONE;
7327 }
7328 operands[0] = force_reg (Pmode, operands[0]);
7329 operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
7330 Pmode)));
7331 })
7332
7333 ;; The address %0 is assumed to be 4-aligned at least. Thus, by ORing
7334 ;; 0xf0000008, we get the low-oder bits *1*00 (binary), which fits
7335 ;; the requirement *1*00 for associative address writes. The alignment of
7336 ;; %0 implies that its least significant bit is cleared,
7337 ;; thus we clear the V bit of a matching entry if there is one.
7338 (define_insn "ic_invalidate_line_i"
7339 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")
7340 (match_operand:SI 1 "register_operand" "r")]
7341 UNSPEC_ICACHE)
7342 (clobber (match_scratch:SI 2 "=&r"))]
7343 "TARGET_HARD_SH4"
7344 {
7345 return "ocbwb @%0" "\n"
7346 " extu.w %0,%2" "\n"
7347 " or %1,%2" "\n"
7348 " mov.l %0,@%2";
7349 }
7350 [(set_attr "length" "8")
7351 (set_attr "type" "cwb")])
7352
7353 (define_insn "ic_invalidate_line_sh4a"
7354 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
7355 UNSPEC_ICACHE)]
7356 "TARGET_SH4A || TARGET_SH4_300"
7357 {
7358 return "ocbwb @%0" "\n"
7359 " synco" "\n"
7360 " icbi @%0";
7361 }
7362 [(set_attr "length" "16") ;; FIXME: Why 16 and not 6? Looks like typo.
7363 (set_attr "type" "cwb")])
7364
7365 ;; ??? could make arg 0 an offsettable memory operand to allow to save
7366 ;; an add in the code that calculates the address.
7367 (define_insn "ic_invalidate_line_media"
7368 [(unspec_volatile [(match_operand 0 "any_register_operand" "r")]
7369 UNSPEC_ICACHE)]
7370 "TARGET_SHMEDIA"
7371 {
7372 return "ocbwb %0,0" "\n"
7373 " synco" "\n"
7374 " icbi %0,0" "\n"
7375 " synci";
7376 }
7377 [(set_attr "length" "16")
7378 (set_attr "type" "invalidate_line_media")])
7379
7380 (define_insn "ic_invalidate_line_compact"
7381 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
7382 (match_operand:SI 1 "register_operand" "r")]
7383 UNSPEC_ICACHE)
7384 (clobber (reg:SI PR_REG))]
7385 "TARGET_SHCOMPACT"
7386 "jsr @%1%#"
7387 [(set_attr "type" "sfunc")
7388 (set_attr "needs_delay_slot" "yes")])
7389
7390 (define_expand "initialize_trampoline"
7391 [(match_operand:SI 0 "" "")
7392 (match_operand:SI 1 "" "")
7393 (match_operand:SI 2 "" "")]
7394 "TARGET_SHCOMPACT"
7395 {
7396 rtx sfun, tramp;
7397
7398 tramp = force_reg (Pmode, operands[0]);
7399 sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline",
7400 SFUNC_STATIC));
7401 emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]);
7402 emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]);
7403
7404 emit_insn (gen_initialize_trampoline_compact (tramp, sfun));
7405 DONE;
7406 })
7407
7408 (define_insn "initialize_trampoline_compact"
7409 [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
7410 (match_operand:SI 1 "register_operand" "r")
7411 (reg:SI R2_REG) (reg:SI R3_REG)]
7412 UNSPEC_INIT_TRAMP)
7413
7414 (clobber (reg:SI PR_REG))]
7415 "TARGET_SHCOMPACT"
7416 "jsr @%1%#"
7417 [(set_attr "type" "sfunc")
7418 (set_attr "needs_delay_slot" "yes")])
7419
7420 (define_expand "mov<mode>"
7421 [(set (match_operand:QIHI 0 "general_movdst_operand")
7422 (match_operand:QIHI 1 "general_movsrc_operand"))]
7423 ""
7424 {
7425 if (can_create_pseudo_p () && CONST_INT_P (operands[1])
7426 && REG_P (operands[0]) && REGNO (operands[0]) != R0_REG)
7427 {
7428 rtx reg = gen_reg_rtx(SImode);
7429 emit_move_insn (reg, operands[1]);
7430 operands[1] = gen_lowpart (<MODE>mode, reg);
7431 }
7432
7433 prepare_move_operands (operands, <MODE>mode);
7434 })
7435
7436 ;; Specifying the displacement addressing load / store patterns separately
7437 ;; before the generic movqi / movhi pattern allows controlling the order
7438 ;; in which load / store insns are selected in a more fine grained way.
7439 ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
7440 ;; "enabled" attribute as it is done in other targets.
7441 (define_insn "*mov<mode>_store_mem_disp04"
7442 [(set (mem:QIHI
7443 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
7444 (match_operand:SI 1 "const_int_operand" "<disp04>,N")))
7445 (match_operand:QIHI 2 "arith_reg_operand" "z,r"))]
7446 "TARGET_SH1 && sh_legitimate_index_p (<MODE>mode, operands[1], false, true)"
7447 "@
7448 mov.<bw> %2,@(%O1,%0)
7449 mov.<bw> %2,@%0"
7450 [(set_attr "type" "store")])
7451
7452 (define_insn "*mov<mode>_store_mem_disp12"
7453 [(set (mem:QIHI
7454 (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
7455 (match_operand:SI 1 "const_int_operand" "<disp12>")))
7456 (match_operand:QIHI 2 "arith_reg_operand" "r"))]
7457 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[1], true, true)"
7458 "mov.<bw> %2,@(%O1,%0)"
7459 [(set_attr "type" "store")
7460 (set_attr "length" "4")])
7461
7462 (define_insn "*mov<mode>_load_mem_disp04"
7463 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r")
7464 (mem:QIHI
7465 (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
7466 (match_operand:SI 2 "const_int_operand" "<disp04>,N"))))]
7467 "TARGET_SH1 && ! TARGET_SH2A
7468 && sh_legitimate_index_p (<MODE>mode, operands[2], false, true)"
7469 "@
7470 mov.<bw> @(%O2,%1),%0
7471 mov.<bw> @%1,%0"
7472 [(set_attr "type" "load")])
7473
7474 (define_insn "*mov<mode>_load_mem_disp12"
7475 [(set (match_operand:QIHI 0 "arith_reg_dest" "=z,r,r")
7476 (mem:QIHI
7477 (plus:SI
7478 (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
7479 (match_operand:SI 2 "const_int_operand" "<disp04>,N,<disp12>"))))]
7480 "TARGET_SH2A && sh_legitimate_index_p (<MODE>mode, operands[2], true, true)"
7481 "@
7482 mov.<bw> @(%O2,%1),%0
7483 mov.<bw> @%1,%0
7484 mov.<bw> @(%O2,%1),%0"
7485 [(set_attr "type" "load")
7486 (set_attr "length" "2,2,4")])
7487
7488 ;; The order of the constraint alternatives is important here.
7489 ;; Q/r has to come first, otherwise PC relative loads might wrongly get
7490 ;; placed into delay slots. Since there is no QImode PC relative load, the
7491 ;; Q constraint and general_movsrc_operand will reject it for QImode.
7492 ;; The Sid/Ssd alternatives should come before Sdd in order to avoid
7493 ;; a preference of using r0 als the register operand for addressing modes
7494 ;; other than displacement addressing.
7495 ;; The Sdd alternatives allow only r0 as register operand, even though on
7496 ;; SH2A any register could be allowed by switching to a 32 bit insn.
7497 ;; Generally sticking to the r0 is preferrable, since it generates smaller
7498 ;; code. Obvious r0 reloads can then be eliminated with a peephole on SH2A.
7499 (define_insn "*mov<mode>"
7500 [(set (match_operand:QIHI 0 "general_movdst_operand"
7501 "=r,r,r,Sid,^zr,Ssd,r, Sdd,z, r,l")
7502 (match_operand:QIHI 1 "general_movsrc_operand"
7503 "Q,r,i,^zr,Sid,r, Ssd,z, Sdd,l,r"))]
7504 "TARGET_SH1
7505 && (arith_reg_operand (operands[0], <MODE>mode)
7506 || arith_reg_operand (operands[1], <MODE>mode))"
7507 "@
7508 mov.<bw> %1,%0
7509 mov %1,%0
7510 mov %1,%0
7511 mov.<bw> %1,%0
7512 mov.<bw> %1,%0
7513 mov.<bw> %1,%0
7514 mov.<bw> %1,%0
7515 mov.<bw> %1,%0
7516 mov.<bw> %1,%0
7517 sts %1,%0
7518 lds %1,%0"
7519 [(set_attr "type" "pcload,move,movi8,store,load,store,load,store,load,prget,prset")
7520 (set (attr "length")
7521 (cond [(and (match_operand 0 "displacement_mem_operand")
7522 (not (match_operand 0 "short_displacement_mem_operand")))
7523 (const_int 4)
7524 (and (match_operand 1 "displacement_mem_operand")
7525 (not (match_operand 1 "short_displacement_mem_operand")))
7526 (const_int 4)]
7527 (const_int 2)))])
7528
7529 (define_insn "*movqi_media"
7530 [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
7531 (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
7532 "TARGET_SHMEDIA
7533 && (arith_reg_operand (operands[0], QImode)
7534 || extend_reg_or_0_operand (operands[1], QImode))"
7535 "@
7536 add.l %1, r63, %0
7537 movi %1, %0
7538 ld%M1.ub %m1, %0
7539 st%M0.b %m0, %N1"
7540 [(set_attr "type" "arith_media,arith_media,load_media,store_media")
7541 (set (attr "highpart")
7542 (cond [(match_test "sh_contains_memref_p (insn)")
7543 (const_string "user")]
7544 (const_string "ignore")))])
7545
7546 (define_expand "reload_inqi"
7547 [(set (match_operand:SI 2 "" "=&r")
7548 (match_operand:QI 1 "inqhi_operand" ""))
7549 (set (match_operand:QI 0 "arith_reg_operand" "=r")
7550 (truncate:QI (match_dup 3)))]
7551 "TARGET_SHMEDIA"
7552 {
7553 rtx inner = XEXP (operands[1], 0);
7554 int regno = REGNO (inner);
7555
7556 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7557 operands[1] = gen_rtx_REG (SImode, regno);
7558 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7559 })
7560
7561 (define_insn "*movhi_media"
7562 [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
7563 (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
7564 "TARGET_SHMEDIA
7565 && (arith_reg_operand (operands[0], HImode)
7566 || arith_reg_or_0_operand (operands[1], HImode))"
7567 "@
7568 add.l %1, r63, %0
7569 movi %1, %0
7570 #
7571 ld%M1.w %m1, %0
7572 st%M0.w %m0, %N1"
7573 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
7574 (set (attr "highpart")
7575 (cond [(match_test "sh_contains_memref_p (insn)")
7576 (const_string "user")]
7577 (const_string "ignore")))])
7578
7579 (define_split
7580 [(set (match_operand:HI 0 "register_operand" "")
7581 (match_operand:HI 1 "immediate_operand" ""))]
7582 "TARGET_SHMEDIA && reload_completed
7583 && ! satisfies_constraint_I16 (operands[1])"
7584 [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
7585
7586 (define_expand "reload_inhi"
7587 [(set (match_operand:SI 2 "" "=&r")
7588 (match_operand:HI 1 "inqhi_operand" ""))
7589 (set (match_operand:HI 0 "arith_reg_operand" "=r")
7590 (truncate:HI (match_dup 3)))]
7591 "TARGET_SHMEDIA"
7592 {
7593 rtx inner = XEXP (operands[1], 0);
7594 int regno = REGNO (inner);
7595
7596 regno += HARD_REGNO_NREGS (regno, GET_MODE (inner)) - 1;
7597 operands[1] = gen_rtx_REG (SImode, regno);
7598 operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
7599 })
7600
7601 ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
7602 ;; compiled with -m2 -ml -O3 -funroll-loops
7603 (define_insn "*movdi_i"
7604 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
7605 (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I08,i,x,r"))]
7606 "TARGET_SH1
7607 && (arith_reg_operand (operands[0], DImode)
7608 || arith_reg_operand (operands[1], DImode))"
7609 {
7610 return output_movedouble (insn, operands, DImode);
7611 }
7612 [(set_attr "length" "4")
7613 (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
7614
7615 ;; If the output is a register and the input is memory or a register, we have
7616 ;; to be careful and see which word needs to be loaded first.
7617 (define_split
7618 [(set (match_operand:DI 0 "general_movdst_operand" "")
7619 (match_operand:DI 1 "general_movsrc_operand" ""))]
7620 "TARGET_SH1 && reload_completed"
7621 [(set (match_dup 2) (match_dup 3))
7622 (set (match_dup 4) (match_dup 5))]
7623 {
7624 int regno;
7625
7626 if ((MEM_P (operands[0])
7627 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
7628 || (MEM_P (operands[1])
7629 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
7630 FAIL;
7631
7632 switch (GET_CODE (operands[0]))
7633 {
7634 case REG:
7635 regno = REGNO (operands[0]);
7636 break;
7637 case SUBREG:
7638 regno = subreg_regno (operands[0]);
7639 break;
7640 case MEM:
7641 regno = -1;
7642 break;
7643 default:
7644 gcc_unreachable ();
7645 }
7646
7647 if (regno == -1 || ! refers_to_regno_p (regno, operands[1]))
7648 {
7649 operands[2] = operand_subword (operands[0], 0, 0, DImode);
7650 operands[3] = operand_subword (operands[1], 0, 0, DImode);
7651 operands[4] = operand_subword (operands[0], 1, 0, DImode);
7652 operands[5] = operand_subword (operands[1], 1, 0, DImode);
7653 }
7654 else
7655 {
7656 operands[2] = operand_subword (operands[0], 1, 0, DImode);
7657 operands[3] = operand_subword (operands[1], 1, 0, DImode);
7658 operands[4] = operand_subword (operands[0], 0, 0, DImode);
7659 operands[5] = operand_subword (operands[1], 0, 0, DImode);
7660 }
7661
7662 if (operands[2] == 0 || operands[3] == 0
7663 || operands[4] == 0 || operands[5] == 0)
7664 FAIL;
7665 })
7666
7667 ;; The '?'s in the following constraints may not reflect the time taken
7668 ;; to perform the move. They are there to discourage the use of floating-
7669 ;; point registers for storing integer values.
7670 (define_insn "*movdi_media"
7671 [(set (match_operand:DI 0 "general_movdst_operand"
7672 "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b")
7673 (match_operand:DI 1 "general_movsrc_operand"
7674 "r,I16Css,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))]
7675 "TARGET_SHMEDIA_FPU
7676 && (register_operand (operands[0], DImode)
7677 || sh_register_operand (operands[1], DImode))"
7678 "@
7679 add %1, r63, %0
7680 movi %1, %0
7681 #
7682 ld%M1.q %m1, %0
7683 st%M0.q %m0, %N1
7684 fld%M1.d %m1, %0
7685 fst%M0.d %m0, %1
7686 fmov.qd %N1, %0
7687 fmov.dq %1, %0
7688 fmov.d %1, %0
7689 ptabs %1, %0
7690 gettr %1, %0
7691 pt %1, %0"
7692 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7693 fload_media,fstore_media,fload_media,dfpconv_media,
7694 fmove_media,ptabs_media,gettr_media,pt_media")
7695 (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
7696
7697 (define_insn "*movdi_media_nofpu"
7698 [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b");
7699 (match_operand:DI 1 "general_movsrc_operand" "r,I16Css,nCpgF,m,rlZ,r,*b,Csy"))]
7700 "TARGET_SHMEDIA
7701 && (register_operand (operands[0], DImode)
7702 || sh_register_operand (operands[1], DImode))"
7703 "@
7704 add %1, r63, %0
7705 movi %1, %0
7706 #
7707 ld%M1.q %m1, %0
7708 st%M0.q %m0, %N1
7709 ptabs %1, %0
7710 gettr %1, %0
7711 pt %1, %0"
7712 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,
7713 ptabs_media,gettr_media,pt_media")
7714 (set_attr "length" "4,4,16,4,4,4,4,*")])
7715
7716 (define_insn "*movdi_media_I16"
7717 [(set (match_operand:DI 0 "ext_dest_operand" "=r")
7718 (match_operand:DI 1 "const_int_operand" "I16"))]
7719 "TARGET_SHMEDIA && reload_completed"
7720 "movi %1, %0"
7721 [(set_attr "type" "arith_media")
7722 (set_attr "length" "4")])
7723
7724 (define_split
7725 [(set (match_operand:DI 0 "arith_reg_dest" "")
7726 (match_operand:DI 1 "immediate_operand" ""))]
7727 "TARGET_SHMEDIA && reload_completed
7728 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7729 [(set (match_dup 0) (match_dup 1))]
7730 {
7731 rtx insn;
7732
7733 if (TARGET_SHMEDIA64)
7734 insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
7735 else
7736 insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
7737
7738 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
7739
7740 DONE;
7741 })
7742
7743 (define_expand "movdi_const"
7744 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7745 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7746 (const_int 48)] UNSPEC_EXTRACT_S16)))
7747 (set (match_dup 0)
7748 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7749 (const:DI (unspec:DI [(match_dup 1)
7750 (const_int 32)] UNSPEC_EXTRACT_U16))))
7751 (set (match_dup 0)
7752 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7753 (const:DI (unspec:DI [(match_dup 1)
7754 (const_int 16)] UNSPEC_EXTRACT_U16))))
7755 (set (match_dup 0)
7756 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7757 (const:DI (unspec:DI [(match_dup 1)
7758 (const_int 0)] UNSPEC_EXTRACT_U16))))]
7759 "TARGET_SHMEDIA64 && reload_completed
7760 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7761 {
7762 sh_mark_label (operands[1], 4);
7763 })
7764
7765 (define_expand "movdi_const_32bit"
7766 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7767 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7768 (const_int 16)] UNSPEC_EXTRACT_S16)))
7769 (set (match_dup 0)
7770 (ior:DI (ashift:DI (match_dup 0) (const_int 16))
7771 (const:DI (unspec:DI [(match_dup 1)
7772 (const_int 0)] UNSPEC_EXTRACT_U16))))]
7773 "TARGET_SHMEDIA32 && reload_completed
7774 && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
7775 {
7776 sh_mark_label (operands[1], 2);
7777 })
7778
7779 (define_expand "movdi_const_16bit"
7780 [(set (match_operand:DI 0 "arith_reg_operand" "=r")
7781 (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
7782 (const_int 0)] UNSPEC_EXTRACT_S16)))]
7783 "TARGET_SHMEDIA && flag_pic && reload_completed
7784 && GET_CODE (operands[1]) == SYMBOL_REF"
7785 "")
7786
7787 (define_split
7788 [(set (match_operand:DI 0 "ext_dest_operand" "")
7789 (match_operand:DI 1 "immediate_operand" ""))]
7790 "TARGET_SHMEDIA && reload_completed
7791 && CONST_INT_P (operands[1])
7792 && ! satisfies_constraint_I16 (operands[1])"
7793 [(set (match_dup 0) (match_dup 2))
7794 (match_dup 1)]
7795 {
7796 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
7797 unsigned HOST_WIDE_INT low = val;
7798 unsigned HOST_WIDE_INT high = val;
7799 unsigned HOST_WIDE_INT sign;
7800 unsigned HOST_WIDE_INT val2 = val ^ (val-1);
7801
7802 /* Zero-extend the 16 least-significant bits. */
7803 low &= 0xffff;
7804
7805 /* Arithmetic shift right the word by 16 bits. */
7806 high >>= 16;
7807 if (GET_CODE (operands[0]) == SUBREG
7808 && GET_MODE (SUBREG_REG (operands[0])) == SImode)
7809 {
7810 high &= 0xffff;
7811 high ^= 0x8000;
7812 high -= 0x8000;
7813 }
7814 else
7815 {
7816 sign = 1;
7817 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7818 high ^= sign;
7819 high -= sign;
7820 }
7821 do
7822 {
7823 /* If we can't generate the constant with a two-insn movi / shori
7824 sequence, try some other strategies. */
7825 if (! CONST_OK_FOR_I16 (high))
7826 {
7827 /* Try constant load / left shift. We know VAL != 0. */
7828 val2 = val ^ (val-1);
7829 if (val2 > 0x1ffff)
7830 {
7831 int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15;
7832
7833 if (CONST_OK_FOR_I16 (val >> trailing_zeroes)
7834 || (! CONST_OK_FOR_I16 (high >> 16)
7835 && CONST_OK_FOR_I16 (val >> (trailing_zeroes + 16))))
7836 {
7837 val2 = (HOST_WIDE_INT) val >> trailing_zeroes;
7838 operands[1] = gen_ashldi3_media (operands[0], operands[0],
7839 GEN_INT (trailing_zeroes));
7840 break;
7841 }
7842 }
7843 /* Try constant load / right shift. */
7844 val2 = (val >> 15) + 1;
7845 if (val2 == (val2 & -val2))
7846 {
7847 int shift = 49 - exact_log2 (val2);
7848
7849 val2 = trunc_int_for_mode (val << shift, DImode);
7850 if (CONST_OK_FOR_I16 (val2))
7851 {
7852 operands[1] = gen_lshrdi3_media (operands[0], operands[0],
7853 GEN_INT (shift));
7854 break;
7855 }
7856 }
7857 /* Try mperm.w . */
7858 val2 = val & 0xffff;
7859 if ((val >> 16 & 0xffff) == val2
7860 && (val >> 32 & 0xffff) == val2
7861 && (val >> 48 & 0xffff) == val2)
7862 {
7863 val2 = (HOST_WIDE_INT) val >> 48;
7864 operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
7865 operands[1] = gen_mperm_w0 (operands[1], operands[1]);
7866 break;
7867 }
7868 /* Try movi / mshflo.l */
7869 val2 = (HOST_WIDE_INT) val >> 32;
7870 if (val2 == ((unsigned HOST_WIDE_INT)
7871 trunc_int_for_mode (val, SImode)))
7872 {
7873 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7874 operands[0]);
7875 break;
7876 }
7877 /* Try movi / mshflo.l w/ r63. */
7878 val2 = val + ((HOST_WIDE_INT) (HOST_WIDE_INT_M1U << 32));
7879 if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_I16 (val2))
7880 {
7881 operands[1] = gen_mshflo_l_di (operands[0], operands[0],
7882 const0_rtx);
7883 break;
7884 }
7885 }
7886 val2 = high;
7887 operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low));
7888 }
7889 while (0);
7890 operands[2] = GEN_INT (val2);
7891 })
7892
7893 (define_split
7894 [(set (match_operand:DI 0 "ext_dest_operand" "")
7895 (match_operand:DI 1 "immediate_operand" ""))]
7896 "TARGET_SHMEDIA && reload_completed
7897 && GET_CODE (operands[1]) == CONST_DOUBLE"
7898 [(set (match_dup 0) (match_dup 2))
7899 (set (match_dup 0)
7900 (ior:DI (ashift:DI (match_dup 0) (const_int 16)) (match_dup 1)))]
7901 {
7902 unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
7903 unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
7904 unsigned HOST_WIDE_INT val = low;
7905 unsigned HOST_WIDE_INT sign;
7906
7907 /* Zero-extend the 16 least-significant bits. */
7908 val &= 0xffff;
7909 operands[1] = GEN_INT (val);
7910
7911 /* Arithmetic shift right the double-word by 16 bits. */
7912 low >>= 16;
7913 low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
7914 high >>= 16;
7915 sign = 1;
7916 sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
7917 high ^= sign;
7918 high -= sign;
7919
7920 /* This will only be true if high is a sign-extension of low, i.e.,
7921 it must be either 0 or (unsigned)-1, and be zero iff the
7922 most-significant bit of low is set. */
7923 if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
7924 operands[2] = GEN_INT (low);
7925 else
7926 operands[2] = immed_double_const (low, high, DImode);
7927 })
7928
7929 (define_insn "shori_media"
7930 [(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
7931 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
7932 (const_int 16))
7933 (match_operand:DI 2 "immediate_operand" "K16Csu,nF")))]
7934 "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))"
7935 "@
7936 shori %u2, %0
7937 #"
7938 [(set_attr "type" "arith_media,*")])
7939
7940 (define_insn "*shori_media_si"
7941 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
7942 (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
7943 (const_int 16))
7944 (match_operand:SI 2 "immediate_operand" "K16Csu")))]
7945 "TARGET_SHMEDIA"
7946 "shori %u2, %0")
7947
7948 (define_expand "movdi"
7949 [(set (match_operand:DI 0 "general_movdst_operand" "")
7950 (match_operand:DI 1 "general_movsrc_operand" ""))]
7951 ""
7952 {
7953 prepare_move_operands (operands, DImode);
7954 if (TARGET_SH1)
7955 {
7956 /* When the dest operand is (R0, R1) register pair, split it to
7957 two movsi of which dest is R1 and R0 so as to lower R0-register
7958 pressure on the first movsi. Apply only for simple source not
7959 to make complex rtl here. */
7960 if (REG_P (operands[0])
7961 && REGNO (operands[0]) == R0_REG
7962 && REG_P (operands[1])
7963 && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
7964 {
7965 emit_insn (gen_movsi (gen_rtx_REG (SImode, R1_REG),
7966 gen_rtx_SUBREG (SImode, operands[1], 4)));
7967 emit_insn (gen_movsi (gen_rtx_REG (SImode, R0_REG),
7968 gen_rtx_SUBREG (SImode, operands[1], 0)));
7969 DONE;
7970 }
7971 }
7972 })
7973
7974 (define_insn "movdf_media"
7975 [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
7976 (match_operand:DF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
7977 "TARGET_SHMEDIA_FPU
7978 && (register_operand (operands[0], DFmode)
7979 || sh_register_operand (operands[1], DFmode))"
7980 "@
7981 fmov.d %1, %0
7982 fmov.qd %N1, %0
7983 fmov.dq %1, %0
7984 add %1, r63, %0
7985 #
7986 fld%M1.d %m1, %0
7987 fst%M0.d %m0, %1
7988 ld%M1.q %m1, %0
7989 st%M0.q %m0, %N1"
7990 [(set_attr "type" "fmove_media,fload_media,dfpconv_media,arith_media,*,
7991 fload_media,fstore_media,load_media,store_media")])
7992
7993 (define_insn "movdf_media_nofpu"
7994 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
7995 (match_operand:DF 1 "general_movsrc_operand" "r,F,m,rZ"))]
7996 "TARGET_SHMEDIA
7997 && (register_operand (operands[0], DFmode)
7998 || sh_register_operand (operands[1], DFmode))"
7999 "@
8000 add %1, r63, %0
8001 #
8002 ld%M1.q %m1, %0
8003 st%M0.q %m0, %N1"
8004 [(set_attr "type" "arith_media,*,load_media,store_media")])
8005
8006 (define_split
8007 [(set (match_operand:DF 0 "arith_reg_dest" "")
8008 (match_operand:DF 1 "immediate_operand" ""))]
8009 "TARGET_SHMEDIA && reload_completed"
8010 [(set (match_dup 3) (match_dup 2))]
8011 {
8012 int endian = WORDS_BIG_ENDIAN ? 1 : 0;
8013 long values[2];
8014
8015 REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), values);
8016
8017 if (HOST_BITS_PER_WIDE_INT >= 64)
8018 operands[2] = immed_double_const ((unsigned long) values[endian]
8019 | ((HOST_WIDE_INT) values[1 - endian]
8020 << 32), 0, DImode);
8021 else
8022 {
8023 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
8024 operands[2] = immed_double_const (values[endian], values[1 - endian],
8025 DImode);
8026 }
8027
8028 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8029 })
8030
8031 ;; FIXME: This should be a define_insn_and_split.
8032 (define_insn "movdf_k"
8033 [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
8034 (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
8035 "TARGET_SH1
8036 && (! (TARGET_SH4 || TARGET_SH2A_DOUBLE) || reload_completed
8037 /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
8038 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8039 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8040 && (arith_reg_operand (operands[0], DFmode)
8041 || arith_reg_operand (operands[1], DFmode))"
8042 {
8043 return output_movedouble (insn, operands, DFmode);
8044 }
8045 [(set_attr "length" "4")
8046 (set_attr "type" "move,pcload,load,store")])
8047
8048 ;; All alternatives of movdf_i4 are split for ! TARGET_FMOVD.
8049 ;; However, the d/F/c/z alternative cannot be split directly; it is converted
8050 ;; with special code in machine_dependent_reorg into a load of the R0_REG and
8051 ;; the d/m/c/X alternative, which is split later into single-precision
8052 ;; instructions. And when not optimizing, no splits are done before fixing
8053 ;; up pcloads, so we need usable length information for that.
8054 (define_insn "movdf_i4"
8055 [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
8056 (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
8057 (use (reg:SI FPSCR_MODES_REG))
8058 (clobber (match_scratch:SI 2 "=X,X,&z,X,X,X,X,X,X,X"))]
8059 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
8060 && (arith_reg_operand (operands[0], DFmode)
8061 || arith_reg_operand (operands[1], DFmode))"
8062 {
8063 switch (which_alternative)
8064 {
8065 case 0:
8066 if (TARGET_FMOVD)
8067 return "fmov %1,%0";
8068 else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
8069 return "fmov %R1,%R0" "\n"
8070 " fmov %S1,%S0";
8071 else
8072 return "fmov %S1,%S0" "\n"
8073 " fmov %R1,%R0";
8074 case 3:
8075 case 4:
8076 return "fmov.d %1,%0";
8077 default:
8078 return "#";
8079 }
8080 }
8081 [(set_attr_alternative "length"
8082 [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
8083 (const_int 4)
8084 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
8085 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
8086 (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
8087 (const_int 4)
8088 (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
8089 ;; We can't use 4-byte push/pop on SHcompact, so we have to
8090 ;; increment or decrement r15 explicitly.
8091 (if_then_else
8092 (match_test "TARGET_SHCOMPACT")
8093 (const_int 10) (const_int 8))
8094 (if_then_else
8095 (match_test "TARGET_SHCOMPACT")
8096 (const_int 10) (const_int 8))])
8097 (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
8098 (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
8099 (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
8100 (const_string "double")
8101 (const_string "none")))])
8102
8103 ;; Moving DFmode between fp/general registers through memory
8104 ;; (the top of the stack) is faster than moving through fpul even for
8105 ;; little endian. Because the type of an instruction is important for its
8106 ;; scheduling, it is beneficial to split these operations, rather than
8107 ;; emitting them in one single chunk, even if this will expose a stack
8108 ;; use that will prevent scheduling of other stack accesses beyond this
8109 ;; instruction.
8110 (define_split
8111 [(set (match_operand:DF 0 "register_operand")
8112 (match_operand:DF 1 "register_operand"))
8113 (use (reg:SI FPSCR_MODES_REG))
8114 (clobber (match_scratch:SI 2))]
8115 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
8116 && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
8117 [(const_int 0)]
8118 {
8119 rtx insn, tos;
8120
8121 if (TARGET_SH5 && true_regnum (operands[1]) < 16)
8122 {
8123 emit_move_insn (stack_pointer_rtx,
8124 plus_constant (Pmode, stack_pointer_rtx, -8));
8125 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
8126 }
8127 else
8128 tos = gen_tmp_stack_mem (DFmode,
8129 gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
8130 insn = emit_insn (gen_movdf_i4 (tos, operands[1]));
8131 if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
8132 add_reg_note (insn, REG_INC, stack_pointer_rtx);
8133 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
8134 tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
8135 else
8136 tos = gen_tmp_stack_mem (DFmode,
8137 gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
8138 insn = emit_insn (gen_movdf_i4 (operands[0], tos));
8139 if (TARGET_SH5 && true_regnum (operands[0]) < 16)
8140 emit_move_insn (stack_pointer_rtx,
8141 plus_constant (Pmode, stack_pointer_rtx, 8));
8142 else
8143 add_reg_note (insn, REG_INC, stack_pointer_rtx);
8144 DONE;
8145 })
8146
8147 ;; local-alloc sometimes allocates scratch registers even when not required,
8148 ;; so we must be prepared to handle these.
8149
8150 ;; Remove the use and clobber from a movdf_i4 so that we can use movdf_k.
8151 (define_split
8152 [(set (match_operand:DF 0 "general_movdst_operand" "")
8153 (match_operand:DF 1 "general_movsrc_operand" ""))
8154 (use (reg:SI FPSCR_MODES_REG))
8155 (clobber (match_scratch:SI 2))]
8156 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
8157 && reload_completed
8158 && true_regnum (operands[0]) < 16
8159 && true_regnum (operands[1]) < 16"
8160 [(set (match_dup 0) (match_dup 1))]
8161 {
8162 /* If this was a reg <-> mem operation with base + index reg addressing,
8163 we have to handle this in a special way. */
8164 rtx mem = operands[0];
8165 int store_p = 1;
8166 if (! memory_operand (mem, DFmode))
8167 {
8168 mem = operands[1];
8169 store_p = 0;
8170 }
8171 if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
8172 mem = SUBREG_REG (mem);
8173 if (MEM_P (mem))
8174 {
8175 rtx addr = XEXP (mem, 0);
8176 if (GET_CODE (addr) == PLUS
8177 && REG_P (XEXP (addr, 0))
8178 && REG_P (XEXP (addr, 1)))
8179 {
8180 int offset;
8181 rtx reg0 = gen_rtx_REG (Pmode, 0);
8182 rtx regop = operands[store_p], word0 ,word1;
8183
8184 if (GET_CODE (regop) == SUBREG)
8185 alter_subreg (&regop, true);
8186 if (REGNO (XEXP (addr, 0)) == REGNO (XEXP (addr, 1)))
8187 offset = 2;
8188 else
8189 offset = 4;
8190 mem = copy_rtx (mem);
8191 PUT_MODE (mem, SImode);
8192 word0 = gen_rtx_SUBREG (SImode, regop, 0);
8193 alter_subreg (&word0, true);
8194 word1 = gen_rtx_SUBREG (SImode, regop, 4);
8195 alter_subreg (&word1, true);
8196 if (store_p || ! refers_to_regno_p (REGNO (word0), addr))
8197 {
8198 emit_insn (store_p
8199 ? gen_movsi_ie (mem, word0)
8200 : gen_movsi_ie (word0, mem));
8201 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
8202 mem = copy_rtx (mem);
8203 emit_insn (store_p
8204 ? gen_movsi_ie (mem, word1)
8205 : gen_movsi_ie (word1, mem));
8206 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
8207 }
8208 else
8209 {
8210 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
8211 emit_insn (gen_movsi_ie (word1, mem));
8212 emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
8213 mem = copy_rtx (mem);
8214 emit_insn (gen_movsi_ie (word0, mem));
8215 }
8216 DONE;
8217 }
8218 }
8219 })
8220
8221 ;; Split away the clobber of r0 after machine_dependent_reorg has fixed pcloads.
8222 (define_split
8223 [(set (match_operand:DF 0 "register_operand" "")
8224 (match_operand:DF 1 "memory_operand" ""))
8225 (use (reg:SI FPSCR_MODES_REG))
8226 (clobber (reg:SI R0_REG))]
8227 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
8228 [(parallel [(set (match_dup 0) (match_dup 1))
8229 (use (reg:SI FPSCR_MODES_REG))
8230 (clobber (scratch:SI))])]
8231 "")
8232
8233 (define_expand "reload_indf__frn"
8234 [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
8235 (match_operand:DF 1 "immediate_operand" "FQ"))
8236 (use (reg:SI FPSCR_MODES_REG))
8237 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8238 "TARGET_SH1"
8239 "")
8240
8241 (define_expand "reload_outdf__RnFRm"
8242 [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
8243 (match_operand:DF 1 "register_operand" "af,r"))
8244 (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
8245 "TARGET_SH1"
8246 "")
8247
8248 ;; Simplify no-op moves.
8249 (define_split
8250 [(set (match_operand:SF 0 "register_operand" "")
8251 (match_operand:SF 1 "register_operand" ""))
8252 (use (reg:SI FPSCR_MODES_REG))
8253 (clobber (match_scratch:SI 2))]
8254 "TARGET_SH2E && reload_completed
8255 && true_regnum (operands[0]) == true_regnum (operands[1])"
8256 [(set (match_dup 0) (match_dup 0))]
8257 "")
8258
8259 ;; fmovd substitute post-reload splits
8260 (define_split
8261 [(set (match_operand:DF 0 "register_operand" "")
8262 (match_operand:DF 1 "register_operand" ""))
8263 (use (reg:SI FPSCR_MODES_REG))
8264 (clobber (match_scratch:SI 2))]
8265 "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
8266 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
8267 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
8268 [(const_int 0)]
8269 {
8270 int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
8271 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
8272 gen_rtx_REG (SFmode, src)));
8273 emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
8274 gen_rtx_REG (SFmode, src + 1)));
8275 DONE;
8276 })
8277
8278 (define_split
8279 [(set (match_operand:DF 0 "register_operand" "")
8280 (mem:DF (match_operand:SI 1 "register_operand" "")))
8281 (use (reg:SI FPSCR_MODES_REG))
8282 (clobber (match_scratch:SI 2))]
8283 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
8284 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
8285 && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
8286 [(const_int 0)]
8287 {
8288 int regno = true_regnum (operands[0]);
8289 rtx insn;
8290 rtx mem = SET_SRC (XVECEXP (PATTERN (curr_insn), 0, 0));
8291 rtx mem2
8292 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
8293 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
8294 regno + SH_REG_MSW_OFFSET),
8295 mem2));
8296 add_reg_note (insn, REG_INC, operands[1]);
8297 insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
8298 regno + SH_REG_LSW_OFFSET),
8299 change_address (mem, SFmode, NULL_RTX)));
8300 DONE;
8301 })
8302
8303 (define_split
8304 [(set (match_operand:DF 0 "register_operand" "")
8305 (match_operand:DF 1 "memory_operand" ""))
8306 (use (reg:SI FPSCR_MODES_REG))
8307 (clobber (match_scratch:SI 2))]
8308 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
8309 && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
8310 [(const_int 0)]
8311 {
8312 int regno = true_regnum (operands[0]);
8313 rtx addr, insn;
8314 rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
8315 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
8316 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
8317
8318 operands[1] = copy_rtx (mem2);
8319 addr = XEXP (mem2, 0);
8320
8321 switch (GET_CODE (addr))
8322 {
8323 case REG:
8324 /* This is complicated. If the register is an arithmetic register
8325 we can just fall through to the REG+DISP case below. Otherwise
8326 we have to use a combination of POST_INC and REG addressing... */
8327 if (! arith_reg_operand (operands[1], SFmode))
8328 {
8329 XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
8330 insn = emit_insn (gen_movsf_ie (reg0, mem2));
8331 add_reg_note (insn, REG_INC, XEXP (addr, 0));
8332
8333 emit_insn (gen_movsf_ie (reg1, operands[1]));
8334
8335 /* If we have modified the stack pointer, the value that we have
8336 read with post-increment might be modified by an interrupt,
8337 so write it back. */
8338 if (REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
8339 emit_insn (gen_push_e (reg0));
8340 else
8341 emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0),
8342 GEN_INT (-4)));
8343 break;
8344 }
8345 /* Fall through. */
8346
8347 case PLUS:
8348 emit_insn (gen_movsf_ie (reg0, operands[1]));
8349 operands[1] = copy_rtx (operands[1]);
8350 XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
8351 emit_insn (gen_movsf_ie (reg1, operands[1]));
8352 break;
8353
8354 case POST_INC:
8355 insn = emit_insn (gen_movsf_ie (reg0, operands[1]));
8356 add_reg_note (insn, REG_INC, XEXP (addr, 0));
8357
8358 insn = emit_insn (gen_movsf_ie (reg1, operands[1]));
8359 add_reg_note (insn, REG_INC, XEXP (addr, 0));
8360 break;
8361
8362 default:
8363 debug_rtx (addr);
8364 gcc_unreachable ();
8365 }
8366
8367 DONE;
8368 })
8369
8370 (define_split
8371 [(set (match_operand:DF 0 "memory_operand" "")
8372 (match_operand:DF 1 "register_operand" ""))
8373 (use (reg:SI FPSCR_MODES_REG))
8374 (clobber (match_scratch:SI 2))]
8375 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
8376 && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
8377 [(const_int 0)]
8378 {
8379 int regno = true_regnum (operands[1]);
8380 rtx insn, addr;
8381 rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
8382 rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
8383
8384 operands[0] = copy_rtx (operands[0]);
8385 PUT_MODE (operands[0], SFmode);
8386 addr = XEXP (operands[0], 0);
8387
8388 switch (GET_CODE (addr))
8389 {
8390 case REG:
8391 /* This is complicated. If the register is an arithmetic register
8392 we can just fall through to the REG+DISP case below. Otherwise
8393 we have to use a combination of REG and PRE_DEC addressing... */
8394 if (! arith_reg_operand (operands[0], SFmode))
8395 {
8396 emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
8397 emit_insn (gen_movsf_ie (operands[0], reg1));
8398
8399 operands[0] = copy_rtx (operands[0]);
8400 XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
8401
8402 insn = emit_insn (gen_movsf_ie (operands[0], reg0));
8403 add_reg_note (insn, REG_INC, XEXP (addr, 0));
8404 break;
8405 }
8406 /* Fall through. */
8407
8408 case PLUS:
8409 /* Since REG+DISP addressing has already been decided upon by gcc
8410 we can rely upon it having chosen an arithmetic register as the
8411 register component of the address. Just emit the lower numbered
8412 register first, to the lower address, then the higher numbered
8413 register to the higher address. */
8414 emit_insn (gen_movsf_ie (operands[0], reg0));
8415
8416 operands[0] = copy_rtx (operands[0]);
8417 XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
8418
8419 emit_insn (gen_movsf_ie (operands[0], reg1));
8420 break;
8421
8422 case PRE_DEC:
8423 /* This is easy. Output the word to go to the higher address
8424 first (ie the word in the higher numbered register) then the
8425 word to go to the lower address. */
8426
8427 insn = emit_insn (gen_movsf_ie (operands[0], reg1));
8428 add_reg_note (insn, REG_INC, XEXP (addr, 0));
8429
8430 insn = emit_insn (gen_movsf_ie (operands[0], reg0));
8431 add_reg_note (insn, REG_INC, XEXP (addr, 0));
8432 break;
8433
8434 default:
8435 /* FAIL; */
8436 debug_rtx (addr);
8437 gcc_unreachable ();
8438 }
8439
8440 DONE;
8441 })
8442
8443 ;; If the output is a register and the input is memory or a register, we have
8444 ;; to be careful and see which word needs to be loaded first.
8445 (define_split
8446 [(set (match_operand:DF 0 "general_movdst_operand" "")
8447 (match_operand:DF 1 "general_movsrc_operand" ""))]
8448 "TARGET_SH1 && reload_completed"
8449 [(set (match_dup 2) (match_dup 3))
8450 (set (match_dup 4) (match_dup 5))]
8451 {
8452 int regno;
8453
8454 if ((MEM_P (operands[0])
8455 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
8456 || (MEM_P (operands[1])
8457 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
8458 FAIL;
8459
8460 switch (GET_CODE (operands[0]))
8461 {
8462 case REG:
8463 regno = REGNO (operands[0]);
8464 break;
8465 case SUBREG:
8466 regno = subreg_regno (operands[0]);
8467 break;
8468 case MEM:
8469 regno = -1;
8470 break;
8471 default:
8472 gcc_unreachable ();
8473 }
8474
8475 if (regno == -1 || ! refers_to_regno_p (regno, operands[1]))
8476 {
8477 operands[2] = operand_subword (operands[0], 0, 0, DFmode);
8478 operands[3] = operand_subword (operands[1], 0, 0, DFmode);
8479 operands[4] = operand_subword (operands[0], 1, 0, DFmode);
8480 operands[5] = operand_subword (operands[1], 1, 0, DFmode);
8481 }
8482 else
8483 {
8484 operands[2] = operand_subword (operands[0], 1, 0, DFmode);
8485 operands[3] = operand_subword (operands[1], 1, 0, DFmode);
8486 operands[4] = operand_subword (operands[0], 0, 0, DFmode);
8487 operands[5] = operand_subword (operands[1], 0, 0, DFmode);
8488 }
8489
8490 if (operands[2] == 0 || operands[3] == 0
8491 || operands[4] == 0 || operands[5] == 0)
8492 FAIL;
8493 })
8494
8495 (define_expand "movdf"
8496 [(set (match_operand:DF 0 "general_movdst_operand" "")
8497 (match_operand:DF 1 "general_movsrc_operand" ""))]
8498 ""
8499 {
8500 prepare_move_operands (operands, DFmode);
8501 if (TARGET_SHMEDIA)
8502 {
8503 if (TARGET_SHMEDIA_FPU)
8504 emit_insn (gen_movdf_media (operands[0], operands[1]));
8505 else
8506 emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
8507 DONE;
8508 }
8509 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
8510 {
8511 emit_insn (gen_movdf_i4 (operands[0], operands[1]));
8512 DONE;
8513 }
8514 })
8515
8516 ;;This is incompatible with the way gcc uses subregs.
8517 ;;(define_insn "movv2sf_i"
8518 ;; [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
8519 ;; (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
8520 ;; "TARGET_SHMEDIA_FPU
8521 ;; && (fp_arith_reg_operand (operands[0], V2SFmode)
8522 ;; || fp_arith_reg_operand (operands[1], V2SFmode))"
8523 ;; "@
8524 ;; #
8525 ;; fld%M1.p %m1, %0
8526 ;; fst%M0.p %m0, %1"
8527 ;; [(set_attr "type" "*,fload_media,fstore_media")])
8528 (define_insn_and_split "movv2sf_i"
8529 [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8530 (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8531 "TARGET_SHMEDIA_FPU"
8532 "#"
8533 "TARGET_SHMEDIA_FPU && reload_completed"
8534 [(set (match_dup 0) (match_dup 1))]
8535 {
8536 operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
8537 operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
8538 })
8539
8540 (define_expand "movv2sf"
8541 [(set (match_operand:V2SF 0 "general_movdst_operand" "")
8542 (match_operand:V2SF 1 "nonimmediate_operand" ""))]
8543 "TARGET_SHMEDIA_FPU"
8544 {
8545 prepare_move_operands (operands, V2SFmode);
8546 })
8547
8548 (define_expand "addv2sf3"
8549 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8550 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8551 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8552 "TARGET_SHMEDIA_FPU"
8553 {
8554 sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
8555 DONE;
8556 })
8557
8558 (define_expand "subv2sf3"
8559 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8560 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8561 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8562 "TARGET_SHMEDIA_FPU"
8563 {
8564 sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
8565 DONE;
8566 })
8567
8568 (define_expand "mulv2sf3"
8569 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8570 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8571 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8572 "TARGET_SHMEDIA_FPU"
8573 {
8574 sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
8575 DONE;
8576 })
8577
8578 (define_expand "divv2sf3"
8579 [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
8580 (match_operand:V2SF 1 "fp_arith_reg_operand" "")
8581 (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
8582 "TARGET_SHMEDIA_FPU"
8583 {
8584 sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
8585 DONE;
8586 })
8587
8588 (define_insn_and_split "*movv4sf_i"
8589 [(set (match_operand:V4SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
8590 (match_operand:V4SF 1 "general_operand" "fm,rfm?,F?,f,rfZ?"))]
8591 "TARGET_SHMEDIA_FPU"
8592 "#"
8593 "&& reload_completed"
8594 [(const_int 0)]
8595 {
8596 for (int i = 0; i < 4/2; i++)
8597 {
8598 rtx x, y;
8599
8600 if (MEM_P (operands[0]))
8601 x = adjust_address (operands[0], V2SFmode,
8602 i * GET_MODE_SIZE (V2SFmode));
8603 else
8604 x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
8605
8606 if (MEM_P (operands[1]))
8607 y = adjust_address (operands[1], V2SFmode,
8608 i * GET_MODE_SIZE (V2SFmode));
8609 else
8610 y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
8611
8612 emit_insn (gen_movv2sf_i (x, y));
8613 }
8614
8615 DONE;
8616 }
8617 [(set_attr "length" "8")])
8618
8619 (define_expand "movv4sf"
8620 [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
8621 (match_operand:V4SF 1 "general_operand" ""))]
8622 "TARGET_SHMEDIA_FPU"
8623 {
8624 prepare_move_operands (operands, V4SFmode);
8625 })
8626
8627 (define_insn_and_split "*movv16sf_i"
8628 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8629 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8630 "TARGET_SHMEDIA_FPU"
8631 "#"
8632 "&& reload_completed"
8633 [(const_int 0)]
8634 {
8635 for (int i = 0; i < 16/2; i++)
8636 {
8637 rtx x, y;
8638
8639 if (MEM_P (operands[0]))
8640 x = adjust_address (operands[0], V2SFmode,
8641 i * GET_MODE_SIZE (V2SFmode));
8642 else
8643 {
8644 x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 8);
8645 alter_subreg (&x, true);
8646 }
8647
8648 if (MEM_P (operands[1]))
8649 y = adjust_address (operands[1], V2SFmode,
8650 i * GET_MODE_SIZE (V2SFmode));
8651 else
8652 {
8653 y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 8);
8654 alter_subreg (&y, true);
8655 }
8656
8657 emit_insn (gen_movv2sf_i (x, y));
8658 }
8659
8660 DONE;
8661 }
8662 [(set_attr "length" "32")])
8663
8664 (define_expand "movv16sf"
8665 [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
8666 (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
8667 "TARGET_SHMEDIA_FPU"
8668 {
8669 prepare_move_operands (operands, V16SFmode);
8670 })
8671
8672 (define_insn "movsf_media"
8673 [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
8674 (match_operand:SF 1 "general_movsrc_operand" "f,rZ,f,r,F,m,f,m,rZ"))]
8675 "TARGET_SHMEDIA_FPU
8676 && (register_operand (operands[0], SFmode)
8677 || sh_register_operand (operands[1], SFmode))"
8678 "@
8679 fmov.s %1, %0
8680 fmov.ls %N1, %0
8681 fmov.sl %1, %0
8682 add.l %1, r63, %0
8683 #
8684 fld%M1.s %m1, %0
8685 fst%M0.s %m0, %1
8686 ld%M1.l %m1, %0
8687 st%M0.l %m0, %N1"
8688 [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
8689 (set (attr "highpart")
8690 (cond [(match_test "sh_contains_memref_p (insn)")
8691 (const_string "user")]
8692 (const_string "ignore")))])
8693
8694 (define_insn "movsf_media_nofpu"
8695 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
8696 (match_operand:SF 1 "general_movsrc_operand" "r,F,m,rZ"))]
8697 "TARGET_SHMEDIA
8698 && (register_operand (operands[0], SFmode)
8699 || sh_register_operand (operands[1], SFmode))"
8700 "@
8701 add.l %1, r63, %0
8702 #
8703 ld%M1.l %m1, %0
8704 st%M0.l %m0, %N1"
8705 [(set_attr "type" "arith_media,*,load_media,store_media")
8706 (set (attr "highpart")
8707 (cond [(match_test "sh_contains_memref_p (insn)")
8708 (const_string "user")]
8709 (const_string "ignore")))])
8710
8711 (define_split
8712 [(set (match_operand:SF 0 "arith_reg_dest" "")
8713 (match_operand:SF 1 "immediate_operand" ""))]
8714 "TARGET_SHMEDIA && reload_completed
8715 && ! FP_REGISTER_P (true_regnum (operands[0]))"
8716 [(set (match_dup 3) (match_dup 2))]
8717 {
8718 long values;
8719
8720 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), values);
8721 operands[2] = GEN_INT (values);
8722
8723 operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
8724 })
8725
8726 (define_insn "movsf_i"
8727 [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
8728 (match_operand:SF 1 "general_movsrc_operand" "r,G,FQ,mr,r,r,l"))]
8729 "TARGET_SH1
8730 && (! TARGET_SH2E
8731 /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
8732 || (REG_P (operands[0]) && REGNO (operands[0]) == 3)
8733 || (REG_P (operands[1]) && REGNO (operands[1]) == 3))
8734 && (arith_reg_operand (operands[0], SFmode)
8735 || arith_reg_operand (operands[1], SFmode))"
8736 "@
8737 mov %1,%0
8738 mov #0,%0
8739 mov.l %1,%0
8740 mov.l %1,%0
8741 mov.l %1,%0
8742 lds %1,%0
8743 sts %1,%0"
8744 [(set_attr "type" "move,move,pcload,load,store,move,move")])
8745
8746 ;; We may not split the ry/yr/XX alternatives to movsi_ie, since
8747 ;; update_flow_info would not know where to put REG_EQUAL notes
8748 ;; when the destination changes mode.
8749 (define_insn "movsf_ie"
8750 [(set (match_operand:SF 0 "general_movdst_operand"
8751 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8752 (match_operand:SF 1 "general_movsrc_operand"
8753 "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
8754 (use (reg:SI FPSCR_MODES_REG))
8755 (clobber (match_scratch:SI 2 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
8756 "TARGET_SH2E
8757 && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode)
8758 || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode)
8759 || arith_reg_operand (operands[2], SImode))"
8760 "@
8761 fmov %1,%0
8762 mov %1,%0
8763 fldi0 %0
8764 fldi1 %0
8765 #
8766 fmov.s %1,%0
8767 fmov.s %1,%0
8768 mov.l %1,%0
8769 mov.l %1,%0
8770 mov.l %1,%0
8771 fsts fpul,%0
8772 flds %1,fpul
8773 lds.l %1,%0
8774 #
8775 sts %1,%0
8776 lds %1,%0
8777 sts.l %1,%0
8778 lds.l %1,%0
8779 ! move optimized away"
8780 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8781 store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8782 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8783 (set_attr_alternative "length"
8784 [(const_int 2)
8785 (const_int 2)
8786 (const_int 2)
8787 (const_int 2)
8788 (const_int 4)
8789 (if_then_else
8790 (match_test "TARGET_SH2A")
8791 (const_int 4) (const_int 2))
8792 (if_then_else
8793 (match_test "TARGET_SH2A")
8794 (const_int 4) (const_int 2))
8795 (const_int 2)
8796 (if_then_else
8797 (match_test "TARGET_SH2A")
8798 (const_int 4) (const_int 2))
8799 (if_then_else
8800 (match_test "TARGET_SH2A")
8801 (const_int 4) (const_int 2))
8802 (const_int 2)
8803 (const_int 2)
8804 (const_int 2)
8805 (const_int 4)
8806 (const_int 2)
8807 (const_int 2)
8808 (const_int 2)
8809 (const_int 2)
8810 (const_int 0)])
8811 (set_attr_alternative "fp_mode"
8812 [(if_then_else (eq_attr "fmovd" "yes")
8813 (const_string "single") (const_string "none"))
8814 (const_string "none")
8815 (const_string "single")
8816 (const_string "single")
8817 (const_string "none")
8818 (if_then_else (eq_attr "fmovd" "yes")
8819 (const_string "single") (const_string "none"))
8820 (if_then_else (eq_attr "fmovd" "yes")
8821 (const_string "single") (const_string "none"))
8822 (const_string "none")
8823 (const_string "none")
8824 (const_string "none")
8825 (const_string "none")
8826 (const_string "none")
8827 (const_string "none")
8828 (const_string "none")
8829 (const_string "none")
8830 (const_string "none")
8831 (const_string "none")
8832 (const_string "none")
8833 (const_string "none")])])
8834
8835 (define_insn_and_split "movsf_ie_ra"
8836 [(set (match_operand:SF 0 "general_movdst_operand"
8837 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
8838 (match_operand:SF 1 "general_movsrc_operand"
8839 "f,r,G,H,FQ,m,f,FQ,m,r,y,f,>,fr,y,r,y,>,y"))
8840 (use (reg:SI FPSCR_MODES_REG))
8841 (clobber (match_scratch:SF 2 "=r,r,X,X,&z,r,r,X,r,r,r,r,r,y,r,r,r,r,r"))
8842 (const_int 0)]
8843 "TARGET_SH2E
8844 && (arith_reg_operand (operands[0], SFmode)
8845 || fpul_operand (operands[0], SFmode)
8846 || arith_reg_operand (operands[1], SFmode)
8847 || fpul_operand (operands[1], SFmode))"
8848 "@
8849 fmov %1,%0
8850 mov %1,%0
8851 fldi0 %0
8852 fldi1 %0
8853 #
8854 fmov.s %1,%0
8855 fmov.s %1,%0
8856 mov.l %1,%0
8857 mov.l %1,%0
8858 mov.l %1,%0
8859 fsts fpul,%0
8860 flds %1,fpul
8861 lds.l %1,%0
8862 #
8863 sts %1,%0
8864 lds %1,%0
8865 sts.l %1,%0
8866 lds.l %1,%0
8867 ! move optimized away"
8868 "reload_completed
8869 && sh_movsf_ie_ra_split_p (operands[0], operands[1], operands[2])"
8870 [(const_int 0)]
8871 {
8872 if (! rtx_equal_p (operands[0], operands[1]))
8873 {
8874 emit_insn (gen_movsf_ie (operands[2], operands[1]));
8875 emit_insn (gen_movsf_ie (operands[0], operands[2]));
8876 }
8877 }
8878 [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
8879 store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
8880 (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
8881 (set_attr_alternative "length"
8882 [(const_int 2)
8883 (const_int 2)
8884 (const_int 2)
8885 (const_int 2)
8886 (const_int 4)
8887 (if_then_else
8888 (match_test "TARGET_SH2A")
8889 (const_int 4) (const_int 2))
8890 (if_then_else
8891 (match_test "TARGET_SH2A")
8892 (const_int 4) (const_int 2))
8893 (const_int 2)
8894 (if_then_else
8895 (match_test "TARGET_SH2A")
8896 (const_int 4) (const_int 2))
8897 (if_then_else
8898 (match_test "TARGET_SH2A")
8899 (const_int 4) (const_int 2))
8900 (const_int 2)
8901 (const_int 2)
8902 (const_int 2)
8903 (const_int 4)
8904 (const_int 2)
8905 (const_int 2)
8906 (const_int 2)
8907 (const_int 2)
8908 (const_int 0)])
8909 (set_attr_alternative "fp_mode"
8910 [(if_then_else (eq_attr "fmovd" "yes")
8911 (const_string "single") (const_string "none"))
8912 (const_string "none")
8913 (const_string "single")
8914 (const_string "single")
8915 (const_string "none")
8916 (if_then_else (eq_attr "fmovd" "yes")
8917 (const_string "single") (const_string "none"))
8918 (if_then_else (eq_attr "fmovd" "yes")
8919 (const_string "single") (const_string "none"))
8920 (const_string "none")
8921 (const_string "none")
8922 (const_string "none")
8923 (const_string "none")
8924 (const_string "none")
8925 (const_string "none")
8926 (const_string "none")
8927 (const_string "none")
8928 (const_string "none")
8929 (const_string "none")
8930 (const_string "none")
8931 (const_string "none")])])
8932
8933 (define_split
8934 [(set (match_operand:SF 0 "register_operand" "")
8935 (match_operand:SF 1 "register_operand" ""))
8936 (use (reg:SI FPSCR_MODES_REG))
8937 (clobber (reg:SI FPUL_REG))]
8938 "TARGET_SH1"
8939 [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
8940 (use (reg:SI FPSCR_MODES_REG))
8941 (clobber (scratch:SI))])
8942 (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
8943 (use (reg:SI FPSCR_MODES_REG))
8944 (clobber (scratch:SI))])]
8945 "")
8946
8947 (define_expand "movsf"
8948 [(set (match_operand:SF 0 "general_movdst_operand" "")
8949 (match_operand:SF 1 "general_movsrc_operand" ""))]
8950 ""
8951 {
8952 prepare_move_operands (operands, SFmode);
8953 if (TARGET_SHMEDIA)
8954 {
8955 if (TARGET_SHMEDIA_FPU)
8956 emit_insn (gen_movsf_media (operands[0], operands[1]));
8957 else
8958 emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
8959 DONE;
8960 }
8961 if (TARGET_SH2E)
8962 {
8963 if (lra_in_progress)
8964 {
8965 if (GET_CODE (operands[0]) == SCRATCH)
8966 DONE;
8967 emit_insn (gen_movsf_ie_ra (operands[0], operands[1]));
8968 DONE;
8969 }
8970
8971 emit_insn (gen_movsf_ie (operands[0], operands[1]));
8972 DONE;
8973 }
8974 })
8975
8976 (define_insn "mov_nop"
8977 [(set (match_operand 0 "any_register_operand" "") (match_dup 0))]
8978 "TARGET_SH2E"
8979 ""
8980 [(set_attr "length" "0")
8981 (set_attr "type" "nil")])
8982
8983 (define_expand "reload_insf__frn"
8984 [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
8985 (match_operand:SF 1 "immediate_operand" "FQ"))
8986 (use (reg:SI FPSCR_MODES_REG))
8987 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8988 "TARGET_SH1"
8989 "")
8990
8991 (define_expand "reload_insi__i_fpul"
8992 [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
8993 (match_operand:SI 1 "immediate_operand" "i"))
8994 (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
8995 "TARGET_SH1"
8996 "")
8997
8998 (define_expand "ptabs"
8999 [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
9000 "TARGET_SHMEDIA"
9001 {
9002 if (!TARGET_PT_FIXED)
9003 {
9004 rtx eq = operands[1];
9005
9006 /* ??? For canonical RTL we really should remove any CONST from EQ
9007 before wrapping it in the AND, and finally wrap the EQ into a
9008 const if is constant. However, for reload we must expose the
9009 input register or symbolic constant, and we can't have
9010 different insn structures outside of the operands for different
9011 alternatives of the same pattern. */
9012 eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)),
9013 GEN_INT (3));
9014 operands[1]
9015 = (gen_rtx_IF_THEN_ELSE
9016 (PDImode,
9017 eq,
9018 gen_rtx_MEM (PDImode, operands[1]),
9019 gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE,
9020 PDImode, operands[1])));
9021 }
9022 })
9023
9024 ;; expanded by ptabs expander.
9025 (define_insn "*extendsipdi_media"
9026 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
9027 (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand"
9028 "r,Csy")
9029 (const_int 3))
9030 (const_int 3))
9031 (mem:PDI (match_dup 1))
9032 (sign_extend:PDI (match_dup 1))))]
9033 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
9034 "@
9035 ptabs %1, %0
9036 pt %1, %0"
9037 [(set_attr "type" "ptabs_media,pt_media")
9038 (set_attr "length" "4,*")])
9039
9040 (define_insn "*truncdipdi_media"
9041 [(set (match_operand:PDI 0 "target_reg_operand" "=b,b");
9042 (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand"
9043 "r,Csy")
9044 (const_int 3))
9045 (const_int 3))
9046 (mem:PDI (match_dup 1))
9047 (truncate:PDI (match_dup 1))))]
9048 "TARGET_SHMEDIA && !TARGET_PT_FIXED"
9049 "@
9050 ptabs %1, %0
9051 pt %1, %0"
9052 [(set_attr "type" "ptabs_media,pt_media")
9053 (set_attr "length" "4,*")])
9054
9055 (define_insn "*movsi_y"
9056 [(set (match_operand:SI 0 "register_operand" "=y,y")
9057 (match_operand:SI 1 "immediate_operand" "Qi,I08"))
9058 (clobber (match_scratch:SI 2 "=&z,r"))]
9059 "TARGET_SH2E
9060 && (reload_in_progress || reload_completed)"
9061 "#"
9062 [(set_attr "length" "4")
9063 (set_attr "type" "pcload,move")])
9064
9065 (define_split
9066 [(set (match_operand:SI 0 "register_operand" "")
9067 (match_operand:SI 1 "immediate_operand" ""))
9068 (clobber (match_operand:SI 2 "register_operand" ""))]
9069 "TARGET_SH1"
9070 [(set (match_dup 2) (match_dup 1))
9071 (set (match_dup 0) (match_dup 2))]
9072 "")
9073 \f
9074 ;; ------------------------------------------------------------------------
9075 ;; Define the real conditional branch instructions.
9076 ;; ------------------------------------------------------------------------
9077
9078 (define_expand "branch_true"
9079 [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
9080 (label_ref (match_operand 0))
9081 (pc)))]
9082 "TARGET_SH1")
9083
9084 (define_expand "branch_false"
9085 [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
9086 (label_ref (match_operand 0))
9087 (pc)))]
9088 "TARGET_SH1")
9089
9090 (define_insn_and_split "*cbranch_t"
9091 [(set (pc) (if_then_else (match_operand 1 "cbranch_treg_value")
9092 (label_ref (match_operand 0))
9093 (pc)))]
9094 "TARGET_SH1"
9095 {
9096 return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
9097 }
9098 "&& 1"
9099 [(const_int 0)]
9100 {
9101 /* Try to canonicalize the branch condition if it is not one of:
9102 (ne (reg:SI T_REG) (const_int 0))
9103 (eq (reg:SI T_REG) (const_int 0))
9104
9105 Instead of splitting out a new insn, we modify the current insn's
9106 operands as needed. This preserves things such as REG_DEAD notes. */
9107
9108 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
9109 && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG
9110 && XEXP (operands[1], 1) == const0_rtx)
9111 DONE;
9112
9113 int branch_cond = sh_eval_treg_value (operands[1]);
9114 rtx new_cond_rtx = NULL_RTX;
9115
9116 if (branch_cond == 0)
9117 new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx);
9118 else if (branch_cond == 1)
9119 new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx);
9120
9121 if (new_cond_rtx != NULL_RTX)
9122 validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0),
9123 new_cond_rtx, false);
9124 DONE;
9125 }
9126 [(set_attr "type" "cbranch")])
9127
9128 ;; Patterns to prevent reorg from re-combining a condbranch with a branch
9129 ;; which destination is too far away.
9130 ;; The const_int_operand is distinct for each branch target; it avoids
9131 ;; unwanted matches with redundant_insn.
9132 (define_insn "block_branch_redirect"
9133 [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
9134 "TARGET_SH1"
9135 ""
9136 [(set_attr "length" "0")])
9137
9138 ;; This one has the additional purpose to record a possible scratch register
9139 ;; for the following branch.
9140 ;; ??? Unfortunately, just setting the scratch register is not good enough,
9141 ;; because the insn then might be deemed dead and deleted. And we can't
9142 ;; make the use in the jump insn explicit because that would disable
9143 ;; delay slot scheduling from the target.
9144 (define_insn "indirect_jump_scratch"
9145 [(set (match_operand:SI 0 "register_operand" "=r")
9146 (unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))
9147 (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
9148 "TARGET_SH1"
9149 ""
9150 [(set_attr "length" "0")])
9151
9152 ;; This one is used to preemt an insn from beyond the bra / braf / jmp
9153 ;; being pulled into the delay slot of a condbranch that has been made to
9154 ;; jump around the unconditional jump because it was out of range.
9155 (define_insn "stuff_delay_slot"
9156 [(set (pc)
9157 (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)
9158 (match_operand:SI 1 "const_int_operand" "")] UNSPEC_BBR))]
9159 "TARGET_SH1"
9160 ""
9161 [(set_attr "length" "0")
9162 (set_attr "cond_delay_slot" "yes")])
9163 \f
9164 ;; Conditional branch insns
9165
9166 (define_expand "cbranchint4_media"
9167 [(set (pc)
9168 (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
9169 [(match_operand 1 "" "")
9170 (match_operand 2 "" "")])
9171 (match_operand 3 "" "")
9172 (pc)))]
9173 "TARGET_SHMEDIA"
9174 {
9175 machine_mode mode = GET_MODE (operands[1]);
9176 if (mode == VOIDmode)
9177 mode = GET_MODE (operands[2]);
9178 if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
9179 {
9180 operands[1] = force_reg (mode, operands[1]);
9181 if (CONSTANT_P (operands[2])
9182 && (! satisfies_constraint_I06 (operands[2])))
9183 operands[2] = force_reg (mode, operands[2]);
9184 }
9185 else
9186 {
9187 if (operands[1] != const0_rtx)
9188 operands[1] = force_reg (mode, operands[1]);
9189 if (operands[2] != const0_rtx)
9190 operands[2] = force_reg (mode, operands[2]);
9191 }
9192 switch (GET_CODE (operands[0]))
9193 {
9194 case LEU:
9195 case LE:
9196 case LTU:
9197 case LT:
9198 operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
9199 VOIDmode, operands[2], operands[1]);
9200 operands[1] = XEXP (operands[0], 0);
9201 operands[2] = XEXP (operands[0], 1);
9202 break;
9203 default:
9204 operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
9205 VOIDmode, operands[1], operands[2]);
9206 break;
9207 }
9208 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
9209 })
9210
9211 (define_expand "cbranchfp4_media"
9212 [(set (pc)
9213 (if_then_else (match_operator 0 "sh_float_comparison_operator"
9214 [(match_operand 1 "" "")
9215 (match_operand 2 "" "")])
9216 (match_operand 3 "" "")
9217 (pc)))]
9218 "TARGET_SHMEDIA"
9219 {
9220 rtx tmp = gen_reg_rtx (SImode);
9221 rtx cmp;
9222 if (GET_CODE (operands[0]) == NE)
9223 cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
9224 else
9225 cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
9226 operands[1], operands[2]);
9227
9228 emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
9229
9230 if (GET_CODE (cmp) == GET_CODE (operands[0]))
9231 operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
9232 else
9233 operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
9234 operands[1] = tmp;
9235 operands[2] = const0_rtx;
9236 operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
9237 })
9238
9239 (define_insn "*beq_media_i"
9240 [(set (pc)
9241 (if_then_else (match_operator 3 "equality_comparison_operator"
9242 [(match_operand:DI 1 "arith_reg_operand" "r,r")
9243 (match_operand:DI 2 "arith_operand" "r,I06")])
9244 (match_operand 0 "target_operand" "b,b")
9245 (pc)))]
9246 "TARGET_SHMEDIA"
9247 "@
9248 b%o3%' %1, %2, %0%>
9249 b%o3i%' %1, %2, %0%>"
9250 [(set_attr "type" "cbranch_media")])
9251
9252 (define_insn "*beq_media_i32"
9253 [(set (pc)
9254 (if_then_else (match_operator 3 "equality_comparison_operator"
9255 [(match_operand:SI 1 "arith_reg_operand" "r,r")
9256 (match_operand:SI 2 "arith_operand" "r,I06")])
9257 (match_operand 0 "target_operand" "b,b")
9258 (pc)))]
9259 "TARGET_SHMEDIA"
9260 "@
9261 b%o3%' %1, %2, %0%>
9262 b%o3i%' %1, %2, %0%>"
9263 [(set_attr "type" "cbranch_media")])
9264
9265 (define_insn "*bgt_media_i"
9266 [(set (pc)
9267 (if_then_else (match_operator 3 "greater_comparison_operator"
9268 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
9269 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
9270 (match_operand 0 "target_operand" "b")
9271 (pc)))]
9272 "TARGET_SHMEDIA"
9273 "b%o3%' %N1, %N2, %0%>"
9274 [(set_attr "type" "cbranch_media")])
9275
9276 (define_insn "*bgt_media_i32"
9277 [(set (pc)
9278 (if_then_else (match_operator 3 "greater_comparison_operator"
9279 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
9280 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
9281 (match_operand 0 "target_operand" "b")
9282 (pc)))]
9283 "TARGET_SHMEDIA"
9284 "b%o3%' %N1, %N2, %0%>"
9285 [(set_attr "type" "cbranch_media")])
9286
9287 ;; These are only needed to make invert_jump() happy - otherwise, jump
9288 ;; optimization will be silently disabled.
9289 (define_insn "*blt_media_i"
9290 [(set (pc)
9291 (if_then_else (match_operator 3 "less_comparison_operator"
9292 [(match_operand:DI 1 "arith_reg_or_0_operand" "rN")
9293 (match_operand:DI 2 "arith_reg_or_0_operand" "rN")])
9294 (match_operand 0 "target_operand" "b")
9295 (pc)))]
9296 "TARGET_SHMEDIA"
9297 "b%o3%' %N2, %N1, %0%>"
9298 [(set_attr "type" "cbranch_media")])
9299
9300 (define_insn "*blt_media_i32"
9301 [(set (pc)
9302 (if_then_else (match_operator 3 "less_comparison_operator"
9303 [(match_operand:SI 1 "arith_reg_or_0_operand" "rN")
9304 (match_operand:SI 2 "arith_reg_or_0_operand" "rN")])
9305 (match_operand 0 "target_operand" "b")
9306 (pc)))]
9307 "TARGET_SHMEDIA"
9308 "b%o3%' %N2, %N1, %0%>"
9309 [(set_attr "type" "cbranch_media")])
9310
9311 ;; combiner splitter for test-and-branch on single bit in register. This
9312 ;; is endian dependent because the non-paradoxical subreg looks different
9313 ;; on big endian.
9314 (define_split
9315 [(set (pc)
9316 (if_then_else
9317 (match_operator 3 "equality_comparison_operator"
9318 [(subreg:SI
9319 (zero_extract:DI
9320 (subreg:DI (match_operand:SI 1 "extend_reg_operand" "") 0)
9321 (const_int 1)
9322 (match_operand 2 "const_int_operand" "")) 0)
9323 (const_int 0)])
9324 (match_operand 0 "target_operand" "")
9325 (pc)))
9326 (clobber (match_operand:SI 4 "arith_reg_dest" ""))]
9327 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
9328 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5)))
9329 (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))]
9330 {
9331 operands[5] = GEN_INT (31 - INTVAL (operands[2]));
9332 operands[6] = (GET_CODE (operands[3]) == EQ
9333 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
9334 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
9335 })
9336
9337 ; operand 0 is the loop count pseudo register
9338 ; operand 1 is the label to jump to at the top of the loop
9339 (define_expand "doloop_end"
9340 [(parallel [(set (pc)
9341 (if_then_else (ne:SI (match_operand:SI 0 "" "")
9342 (const_int 1))
9343 (label_ref (match_operand 1 "" ""))
9344 (pc)))
9345 (set (match_dup 0)
9346 (plus:SI (match_dup 0) (const_int -1)))
9347 (clobber (reg:SI T_REG))])]
9348 "TARGET_SH2"
9349 {
9350 if (GET_MODE (operands[0]) != SImode)
9351 FAIL;
9352 emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0]));
9353 DONE;
9354 })
9355
9356 (define_insn_and_split "doloop_end_split"
9357 [(set (pc)
9358 (if_then_else (ne:SI (match_operand:SI 2 "arith_reg_dest" "0")
9359 (const_int 1))
9360 (label_ref (match_operand 1 "" ""))
9361 (pc)))
9362 (set (match_operand:SI 0 "arith_reg_dest" "=r")
9363 (plus:SI (match_dup 2) (const_int -1)))
9364 (clobber (reg:SI T_REG))]
9365 "TARGET_SH2"
9366 "#"
9367 ""
9368 [(parallel [(set (reg:SI T_REG)
9369 (eq:SI (match_dup 2) (const_int 1)))
9370 (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
9371 (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
9372 (label_ref (match_dup 1))
9373 (pc)))]
9374 ""
9375 [(set_attr "type" "cbranch")])
9376 \f
9377 ;; ------------------------------------------------------------------------
9378 ;; Jump and linkage insns
9379 ;; ------------------------------------------------------------------------
9380
9381 (define_insn "jump_compact"
9382 [(set (pc)
9383 (label_ref (match_operand 0 "" "")))]
9384 "TARGET_SH1 && !CROSSING_JUMP_P (insn)"
9385 {
9386 /* The length is 16 if the delay slot is unfilled. */
9387 if (get_attr_length(insn) > 4)
9388 return output_far_jump(insn, operands[0]);
9389 else
9390 return "bra %l0%#";
9391 }
9392 [(set_attr "type" "jump")
9393 (set_attr "needs_delay_slot" "yes")])
9394
9395 (define_insn "*jump_compact_crossing"
9396 [(set (pc)
9397 (label_ref (match_operand 0 "" "")))]
9398 "TARGET_SH1
9399 && flag_reorder_blocks_and_partition
9400 && CROSSING_JUMP_P (insn)"
9401 {
9402 /* The length is 16 if the delay slot is unfilled. */
9403 return output_far_jump(insn, operands[0]);
9404 }
9405 [(set_attr "type" "jump")
9406 (set_attr "length" "16")])
9407
9408 ;; ??? It would be much saner to explicitly use the scratch register
9409 ;; in the jump insn, and have indirect_jump_scratch only set it,
9410 ;; but fill_simple_delay_slots would refuse to do delay slot filling
9411 ;; from the target then, as it uses simplejump_p.
9412 ;;(define_insn "jump_compact_far"
9413 ;; [(set (pc)
9414 ;; (label_ref (match_operand 0 "" "")))
9415 ;; (use (match_operand 1 "register_operand" "r")]
9416 ;; "TARGET_SH1"
9417 ;; "* return output_far_jump(insn, operands[0], operands[1]);"
9418 ;; [(set_attr "type" "jump")
9419 ;; (set_attr "needs_delay_slot" "yes")])
9420
9421 (define_insn "jump_media"
9422 [(set (pc)
9423 (match_operand 0 "target_operand" "b"))]
9424 "TARGET_SHMEDIA"
9425 "blink %0, r63%>"
9426 [(set_attr "type" "jump_media")])
9427
9428 (define_expand "jump"
9429 [(set (pc)
9430 (label_ref (match_operand 0 "" "")))]
9431 ""
9432 {
9433 if (TARGET_SH1)
9434 emit_jump_insn (gen_jump_compact (operands[0]));
9435 else if (TARGET_SHMEDIA)
9436 {
9437 if (reload_in_progress || reload_completed)
9438 FAIL;
9439 emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0])));
9440 }
9441 DONE;
9442 })
9443
9444 (define_insn "force_mode_for_call"
9445 [(use (reg:SI FPSCR_MODES_REG))]
9446 "TARGET_SHCOMPACT"
9447 ""
9448 [(set_attr "length" "0")
9449 (set (attr "fp_mode")
9450 (if_then_else (eq_attr "fpu_single" "yes")
9451 (const_string "single") (const_string "double")))])
9452
9453 (define_insn "calli"
9454 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9455 (match_operand 1 "" ""))
9456 (use (reg:SI FPSCR_MODES_REG))
9457 (clobber (reg:SI PR_REG))]
9458 "TARGET_SH1"
9459 {
9460 if (TARGET_SH2A && (dbr_sequence_length () == 0))
9461 return "jsr/n @%0";
9462 else
9463 return "jsr @%0%#";
9464 }
9465 [(set_attr "type" "call")
9466 (set (attr "fp_mode")
9467 (if_then_else (eq_attr "fpu_single" "yes")
9468 (const_string "single") (const_string "double")))
9469 (set_attr "needs_delay_slot" "yes")
9470 (set_attr "fp_set" "unknown")])
9471
9472 ;; This is TBR relative jump instruction for SH2A architecture.
9473 ;; Its use is enabled by assigning an attribute "function_vector"
9474 ;; and the vector number to a function during its declaration.
9475 (define_insn "calli_tbr_rel"
9476 [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
9477 (match_operand 1 "" ""))
9478 (use (reg:SI FPSCR_MODES_REG))
9479 (clobber (reg:SI PR_REG))]
9480 "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
9481 {
9482 unsigned HOST_WIDE_INT vect_num;
9483 vect_num = sh2a_get_function_vector_number (operands[0]);
9484 operands[2] = GEN_INT (vect_num * 4);
9485
9486 return "jsr/n @@(%O2,tbr)";
9487 }
9488 [(set_attr "type" "call")
9489 (set (attr "fp_mode")
9490 (if_then_else (eq_attr "fpu_single" "yes")
9491 (const_string "single") (const_string "double")))
9492 (set_attr "needs_delay_slot" "no")
9493 (set_attr "fp_set" "unknown")])
9494
9495 ;; This is a pc-rel call, using bsrf, for use with PIC.
9496 (define_insn "calli_pcrel"
9497 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9498 (match_operand 1 "" ""))
9499 (use (reg:SI FPSCR_MODES_REG))
9500 (use (reg:SI PIC_REG))
9501 (use (match_operand 2 "" ""))
9502 (clobber (reg:SI PR_REG))]
9503 "TARGET_SH2"
9504 {
9505 return "bsrf %0" "\n"
9506 "%O2:%#";
9507 }
9508 [(set_attr "type" "call")
9509 (set (attr "fp_mode")
9510 (if_then_else (eq_attr "fpu_single" "yes")
9511 (const_string "single") (const_string "double")))
9512 (set_attr "needs_delay_slot" "yes")
9513 (set_attr "fp_set" "unknown")])
9514
9515 (define_insn_and_split "call_pcrel"
9516 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
9517 (match_operand 1 "" ""))
9518 (use (reg:SI FPSCR_MODES_REG))
9519 (use (reg:SI PIC_REG))
9520 (clobber (reg:SI PR_REG))
9521 (clobber (match_scratch:SI 2 "=&r"))]
9522 "TARGET_SH2"
9523 "#"
9524 "reload_completed"
9525 [(const_int 0)]
9526 {
9527 rtx lab = PATTERN (gen_call_site ());
9528
9529 sh_expand_sym_label2reg (operands[2], operands[0], lab, false);
9530 emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
9531 DONE;
9532 }
9533 [(set_attr "type" "call")
9534 (set (attr "fp_mode")
9535 (if_then_else (eq_attr "fpu_single" "yes")
9536 (const_string "single") (const_string "double")))
9537 (set_attr "needs_delay_slot" "yes")
9538 (set_attr "fp_set" "unknown")])
9539
9540 (define_insn "call_compact"
9541 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9542 (match_operand 1 "" ""))
9543 (match_operand 2 "immediate_operand" "n")
9544 (use (reg:SI R0_REG))
9545 (use (reg:SI R1_REG))
9546 (use (reg:SI FPSCR_MODES_REG))
9547 (clobber (reg:SI PR_REG))]
9548 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9549 "jsr @%0%#"
9550 [(set_attr "type" "call")
9551 (set (attr "fp_mode")
9552 (if_then_else (eq_attr "fpu_single" "yes")
9553 (const_string "single") (const_string "double")))
9554 (set_attr "needs_delay_slot" "yes")])
9555
9556 (define_insn "call_compact_rettramp"
9557 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9558 (match_operand 1 "" ""))
9559 (match_operand 2 "immediate_operand" "n")
9560 (use (reg:SI R0_REG))
9561 (use (reg:SI R1_REG))
9562 (use (reg:SI FPSCR_MODES_REG))
9563 (clobber (reg:SI R10_REG))
9564 (clobber (reg:SI PR_REG))]
9565 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9566 "jsr @%0%#"
9567 [(set_attr "type" "call")
9568 (set (attr "fp_mode")
9569 (if_then_else (eq_attr "fpu_single" "yes")
9570 (const_string "single") (const_string "double")))
9571 (set_attr "needs_delay_slot" "yes")])
9572
9573 (define_insn "call_media"
9574 [(call (mem:DI (match_operand 0 "target_reg_operand" "b"))
9575 (match_operand 1 "" ""))
9576 (clobber (reg:DI PR_MEDIA_REG))]
9577 "TARGET_SHMEDIA"
9578 "blink %0, r18"
9579 [(set_attr "type" "jump_media")])
9580
9581 (define_insn "call_valuei"
9582 [(set (match_operand 0 "" "=rf")
9583 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9584 (match_operand 2 "" "")))
9585 (use (reg:SI FPSCR_MODES_REG))
9586 (clobber (reg:SI PR_REG))]
9587 "TARGET_SH1"
9588 {
9589 if (TARGET_SH2A && (dbr_sequence_length () == 0))
9590 return "jsr/n @%1";
9591 else
9592 return "jsr @%1%#";
9593 }
9594 [(set_attr "type" "call")
9595 (set (attr "fp_mode")
9596 (if_then_else (eq_attr "fpu_single" "yes")
9597 (const_string "single") (const_string "double")))
9598 (set_attr "needs_delay_slot" "yes")
9599 (set_attr "fp_set" "unknown")])
9600
9601 ;; This is TBR relative jump instruction for SH2A architecture.
9602 ;; Its use is enabled by assigning an attribute "function_vector"
9603 ;; and the vector number to a function during its declaration.
9604 (define_insn "call_valuei_tbr_rel"
9605 [(set (match_operand 0 "" "=rf")
9606 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9607 (match_operand 2 "" "")))
9608 (use (reg:SI FPSCR_MODES_REG))
9609 (clobber (reg:SI PR_REG))]
9610 "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
9611 {
9612 unsigned HOST_WIDE_INT vect_num;
9613 vect_num = sh2a_get_function_vector_number (operands[1]);
9614 operands[3] = GEN_INT (vect_num * 4);
9615
9616 return "jsr/n @@(%O3,tbr)";
9617 }
9618 [(set_attr "type" "call")
9619 (set (attr "fp_mode")
9620 (if_then_else (eq_attr "fpu_single" "yes")
9621 (const_string "single") (const_string "double")))
9622 (set_attr "needs_delay_slot" "no")
9623 (set_attr "fp_set" "unknown")])
9624
9625 (define_insn "call_valuei_pcrel"
9626 [(set (match_operand 0 "" "=rf")
9627 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9628 (match_operand 2 "" "")))
9629 (use (reg:SI FPSCR_MODES_REG))
9630 (use (reg:SI PIC_REG))
9631 (use (match_operand 3 "" ""))
9632 (clobber (reg:SI PR_REG))]
9633 "TARGET_SH2"
9634 {
9635 return "bsrf %1" "\n"
9636 "%O3:%#";
9637 }
9638 [(set_attr "type" "call")
9639 (set (attr "fp_mode")
9640 (if_then_else (eq_attr "fpu_single" "yes")
9641 (const_string "single") (const_string "double")))
9642 (set_attr "needs_delay_slot" "yes")
9643 (set_attr "fp_set" "unknown")])
9644
9645 (define_insn_and_split "call_value_pcrel"
9646 [(set (match_operand 0 "" "=rf")
9647 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
9648 (match_operand 2 "" "")))
9649 (use (reg:SI FPSCR_MODES_REG))
9650 (use (reg:SI PIC_REG))
9651 (clobber (reg:SI PR_REG))
9652 (clobber (match_scratch:SI 3 "=&r"))]
9653 "TARGET_SH2"
9654 "#"
9655 "reload_completed"
9656 [(const_int 0)]
9657 {
9658 rtx lab = PATTERN (gen_call_site ());
9659
9660 sh_expand_sym_label2reg (operands[3], operands[1], lab, false);
9661 emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
9662 operands[2], copy_rtx (lab)));
9663 DONE;
9664 }
9665 [(set_attr "type" "call")
9666 (set (attr "fp_mode")
9667 (if_then_else (eq_attr "fpu_single" "yes")
9668 (const_string "single") (const_string "double")))
9669 (set_attr "needs_delay_slot" "yes")
9670 (set_attr "fp_set" "unknown")])
9671
9672 (define_insn "call_value_compact"
9673 [(set (match_operand 0 "" "=rf")
9674 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9675 (match_operand 2 "" "")))
9676 (match_operand 3 "immediate_operand" "n")
9677 (use (reg:SI R0_REG))
9678 (use (reg:SI R1_REG))
9679 (use (reg:SI FPSCR_MODES_REG))
9680 (clobber (reg:SI PR_REG))]
9681 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9682 "jsr @%1%#"
9683 [(set_attr "type" "call")
9684 (set (attr "fp_mode")
9685 (if_then_else (eq_attr "fpu_single" "yes")
9686 (const_string "single") (const_string "double")))
9687 (set_attr "needs_delay_slot" "yes")])
9688
9689 (define_insn "call_value_compact_rettramp"
9690 [(set (match_operand 0 "" "=rf")
9691 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
9692 (match_operand 2 "" "")))
9693 (match_operand 3 "immediate_operand" "n")
9694 (use (reg:SI R0_REG))
9695 (use (reg:SI R1_REG))
9696 (use (reg:SI FPSCR_MODES_REG))
9697 (clobber (reg:SI R10_REG))
9698 (clobber (reg:SI PR_REG))]
9699 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
9700 "jsr @%1%#"
9701 [(set_attr "type" "call")
9702 (set (attr "fp_mode")
9703 (if_then_else (eq_attr "fpu_single" "yes")
9704 (const_string "single") (const_string "double")))
9705 (set_attr "needs_delay_slot" "yes")])
9706
9707 (define_insn "call_value_media"
9708 [(set (match_operand 0 "" "=rf")
9709 (call (mem:DI (match_operand 1 "target_reg_operand" "b"))
9710 (match_operand 2 "" "")))
9711 (clobber (reg:DI PR_MEDIA_REG))]
9712 "TARGET_SHMEDIA"
9713 "blink %1, r18"
9714 [(set_attr "type" "jump_media")])
9715
9716 (define_expand "call"
9717 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9718 (match_operand 1 "" ""))
9719 (match_operand 2 "" "")
9720 (use (reg:SI FPSCR_MODES_REG))
9721 (clobber (reg:SI PR_REG))])]
9722 ""
9723 {
9724 if (TARGET_SHMEDIA)
9725 {
9726 operands[0] = shmedia_prepare_call_address (operands[0], 0);
9727 emit_call_insn (gen_call_media (operands[0], operands[1]));
9728 DONE;
9729 }
9730 else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
9731 {
9732 rtx cookie_rtx = operands[2];
9733 long cookie = INTVAL (cookie_rtx);
9734 rtx func = XEXP (operands[0], 0);
9735 rtx r0, r1;
9736
9737 if (flag_pic)
9738 {
9739 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9740 {
9741 rtx reg = gen_reg_rtx (Pmode);
9742
9743 emit_insn (gen_symGOTPLT2reg (reg, func));
9744 func = reg;
9745 }
9746 else
9747 func = legitimize_pic_address (func, Pmode, 0);
9748 }
9749
9750 r0 = gen_rtx_REG (SImode, R0_REG);
9751 r1 = gen_rtx_REG (SImode, R1_REG);
9752
9753 /* Since such a call function may use all call-clobbered
9754 registers, we force a mode switch earlier, so that we don't
9755 run out of registers when adjusting fpscr for the call. */
9756 emit_insn (gen_force_mode_for_call ());
9757
9758 operands[0]
9759 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9760 operands[0] = force_reg (SImode, operands[0]);
9761
9762 emit_move_insn (r0, func);
9763 emit_move_insn (r1, cookie_rtx);
9764
9765 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9766 emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
9767 operands[2]));
9768 else
9769 emit_call_insn (gen_call_compact (operands[0], operands[1],
9770 operands[2]));
9771
9772 DONE;
9773 }
9774 else if (TARGET_SHCOMPACT && flag_pic
9775 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9776 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
9777 {
9778 rtx reg = gen_reg_rtx (Pmode);
9779
9780 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
9781 XEXP (operands[0], 0) = reg;
9782 }
9783 if (!flag_pic && TARGET_SH2A
9784 && MEM_P (operands[0])
9785 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9786 {
9787 if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
9788 {
9789 emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
9790 operands[1]));
9791 DONE;
9792 }
9793 }
9794 if (flag_pic && TARGET_SH2
9795 && MEM_P (operands[0])
9796 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
9797 {
9798 emit_call_insn (gen_call_pcrel (XEXP (operands[0], 0), operands[1]));
9799 DONE;
9800 }
9801 else
9802 {
9803 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
9804 operands[1] = operands[2];
9805 }
9806
9807 emit_call_insn (gen_calli (operands[0], operands[1]));
9808 DONE;
9809 })
9810
9811 (define_insn "call_pop_compact"
9812 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9813 (match_operand 1 "" ""))
9814 (match_operand 2 "immediate_operand" "n")
9815 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9816 (match_operand 3 "immediate_operand" "n")))
9817 (use (reg:SI R0_REG))
9818 (use (reg:SI R1_REG))
9819 (use (reg:SI FPSCR_MODES_REG))
9820 (clobber (reg:SI PR_REG))]
9821 "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9822 "jsr @%0%#"
9823 [(set_attr "type" "call")
9824 (set (attr "fp_mode")
9825 (if_then_else (eq_attr "fpu_single" "yes")
9826 (const_string "single") (const_string "double")))
9827 (set_attr "needs_delay_slot" "yes")])
9828
9829 (define_insn "call_pop_compact_rettramp"
9830 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
9831 (match_operand 1 "" ""))
9832 (match_operand 2 "immediate_operand" "n")
9833 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9834 (match_operand 3 "immediate_operand" "n")))
9835 (use (reg:SI R0_REG))
9836 (use (reg:SI R1_REG))
9837 (use (reg:SI FPSCR_MODES_REG))
9838 (clobber (reg:SI R10_REG))
9839 (clobber (reg:SI PR_REG))]
9840 "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
9841 "jsr @%0%#"
9842 [(set_attr "type" "call")
9843 (set (attr "fp_mode")
9844 (if_then_else (eq_attr "fpu_single" "yes")
9845 (const_string "single") (const_string "double")))
9846 (set_attr "needs_delay_slot" "yes")])
9847
9848 (define_expand "call_pop"
9849 [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
9850 (match_operand 1 "" ""))
9851 (match_operand 2 "" "")
9852 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
9853 (match_operand 3 "" "")))])]
9854 "TARGET_SHCOMPACT"
9855 {
9856 rtx cookie_rtx;
9857 long cookie;
9858 rtx func;
9859 rtx r0, r1;
9860
9861 gcc_assert (operands[2] && INTVAL (operands[2]));
9862 cookie_rtx = operands[2];
9863 cookie = INTVAL (cookie_rtx);
9864 func = XEXP (operands[0], 0);
9865
9866 if (flag_pic)
9867 {
9868 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9869 {
9870 rtx reg = gen_reg_rtx (Pmode);
9871 emit_insn (gen_symGOTPLT2reg (reg, func));
9872 func = reg;
9873 }
9874 else
9875 func = legitimize_pic_address (func, Pmode, 0);
9876 }
9877
9878 r0 = gen_rtx_REG (SImode, R0_REG);
9879 r1 = gen_rtx_REG (SImode, R1_REG);
9880
9881 /* Since such a call function may use all call-clobbered
9882 registers, we force a mode switch earlier, so that we don't
9883 run out of registers when adjusting fpscr for the call. */
9884 emit_insn (gen_force_mode_for_call ());
9885
9886 operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
9887 SFUNC_GOT);
9888 operands[0] = force_reg (SImode, operands[0]);
9889
9890 emit_move_insn (r0, func);
9891 emit_move_insn (r1, cookie_rtx);
9892
9893 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9894 emit_call_insn (gen_call_pop_compact_rettramp
9895 (operands[0], operands[1], operands[2], operands[3]));
9896 else
9897 emit_call_insn (gen_call_pop_compact
9898 (operands[0], operands[1], operands[2], operands[3]));
9899
9900 DONE;
9901 })
9902
9903 (define_expand "call_value"
9904 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
9905 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
9906 (match_operand 2 "" "")))
9907 (match_operand 3 "" "")
9908 (use (reg:SI FPSCR_MODES_REG))
9909 (clobber (reg:SI PR_REG))])]
9910 ""
9911 {
9912 if (TARGET_SHMEDIA)
9913 {
9914 operands[1] = shmedia_prepare_call_address (operands[1], 0);
9915 emit_call_insn (gen_call_value_media (operands[0], operands[1],
9916 operands[2]));
9917 DONE;
9918 }
9919 else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
9920 {
9921 rtx cookie_rtx = operands[3];
9922 long cookie = INTVAL (cookie_rtx);
9923 rtx func = XEXP (operands[1], 0);
9924 rtx r0, r1;
9925
9926 if (flag_pic)
9927 {
9928 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
9929 {
9930 rtx reg = gen_reg_rtx (Pmode);
9931
9932 emit_insn (gen_symGOTPLT2reg (reg, func));
9933 func = reg;
9934 }
9935 else
9936 func = legitimize_pic_address (func, Pmode, 0);
9937 }
9938
9939 r0 = gen_rtx_REG (SImode, R0_REG);
9940 r1 = gen_rtx_REG (SImode, R1_REG);
9941
9942 /* Since such a call function may use all call-clobbered
9943 registers, we force a mode switch earlier, so that we don't
9944 run out of registers when adjusting fpscr for the call. */
9945 emit_insn (gen_force_mode_for_call ());
9946
9947 operands[1]
9948 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
9949 operands[1] = force_reg (SImode, operands[1]);
9950
9951 emit_move_insn (r0, func);
9952 emit_move_insn (r1, cookie_rtx);
9953
9954 if (cookie & CALL_COOKIE_RET_TRAMP (1))
9955 emit_call_insn (gen_call_value_compact_rettramp (operands[0],
9956 operands[1],
9957 operands[2],
9958 operands[3]));
9959 else
9960 emit_call_insn (gen_call_value_compact (operands[0], operands[1],
9961 operands[2], operands[3]));
9962
9963 DONE;
9964 }
9965 else if (TARGET_SHCOMPACT && flag_pic
9966 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9967 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
9968 {
9969 rtx reg = gen_reg_rtx (Pmode);
9970
9971 emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
9972 XEXP (operands[1], 0) = reg;
9973 }
9974 if (!flag_pic && TARGET_SH2A
9975 && MEM_P (operands[1])
9976 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9977 {
9978 if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
9979 {
9980 emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
9981 XEXP (operands[1], 0), operands[2]));
9982 DONE;
9983 }
9984 }
9985 if (flag_pic && TARGET_SH2
9986 && MEM_P (operands[1])
9987 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
9988 {
9989 emit_call_insn (gen_call_value_pcrel (operands[0], XEXP (operands[1], 0),
9990 operands[2]));
9991 DONE;
9992 }
9993 else
9994 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
9995
9996 emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
9997 DONE;
9998 })
9999
10000 (define_insn "sibcalli"
10001 [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
10002 (match_operand 1 "" ""))
10003 (use (reg:SI FPSCR_MODES_REG))
10004 (return)]
10005 "TARGET_SH1"
10006 "jmp @%0%#"
10007 [(set_attr "needs_delay_slot" "yes")
10008 (set (attr "fp_mode")
10009 (if_then_else (eq_attr "fpu_single" "yes")
10010 (const_string "single") (const_string "double")))
10011 (set_attr "type" "jump_ind")])
10012
10013 (define_insn "sibcalli_pcrel"
10014 [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
10015 (match_operand 1 "" ""))
10016 (use (match_operand 2 "" ""))
10017 (use (reg:SI FPSCR_MODES_REG))
10018 (return)]
10019 "TARGET_SH2"
10020 {
10021 return "braf %0" "\n"
10022 "%O2:%#";
10023 }
10024 [(set_attr "needs_delay_slot" "yes")
10025 (set (attr "fp_mode")
10026 (if_then_else (eq_attr "fpu_single" "yes")
10027 (const_string "single") (const_string "double")))
10028 (set_attr "type" "jump_ind")])
10029
10030 ;; This uses an unspec to describe that the symbol_ref is very close.
10031 (define_insn "sibcalli_thunk"
10032 [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
10033 UNSPEC_THUNK))
10034 (match_operand 1 "" ""))
10035 (use (reg:SI FPSCR_MODES_REG))
10036 (return)]
10037 "TARGET_SH1"
10038 "bra %O0"
10039 [(set_attr "needs_delay_slot" "yes")
10040 (set (attr "fp_mode")
10041 (if_then_else (eq_attr "fpu_single" "yes")
10042 (const_string "single") (const_string "double")))
10043 (set_attr "type" "jump")
10044 (set_attr "length" "2")])
10045
10046 (define_insn_and_split "sibcall_pcrel"
10047 [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
10048 (match_operand 1 "" ""))
10049 (use (reg:SI FPSCR_MODES_REG))
10050 (clobber (match_scratch:SI 2 "=&k"))
10051 (return)]
10052 "TARGET_SH2"
10053 "#"
10054 "reload_completed"
10055 [(const_int 0)]
10056 {
10057 rtx lab = PATTERN (gen_call_site ());
10058 rtx call_insn;
10059
10060 sh_expand_sym_label2reg (operands[2], operands[0], lab, true);
10061 call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
10062 copy_rtx (lab)));
10063 SIBLING_CALL_P (call_insn) = 1;
10064 DONE;
10065 }
10066 [(set_attr "needs_delay_slot" "yes")
10067 (set (attr "fp_mode")
10068 (if_then_else (eq_attr "fpu_single" "yes")
10069 (const_string "single") (const_string "double")))
10070 (set_attr "type" "jump_ind")])
10071
10072 (define_insn "sibcall_compact"
10073 [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
10074 (match_operand 1 "" ""))
10075 (return)
10076 (use (match_operand:SI 2 "register_operand" "z,x"))
10077 (use (reg:SI R1_REG))
10078 (use (reg:SI FPSCR_MODES_REG))
10079 ;; We want to make sure the `x' above will only match MACH_REG
10080 ;; because sibcall_epilogue may clobber MACL_REG.
10081 (clobber (reg:SI MACL_REG))]
10082 "TARGET_SHCOMPACT"
10083 {
10084 static const char* alt[] =
10085 {
10086 "jmp @%0%#",
10087
10088 "jmp @%0" "\n"
10089 " sts %2,r0"
10090 };
10091 return alt[which_alternative];
10092 }
10093 [(set_attr "needs_delay_slot" "yes,no")
10094 (set_attr "length" "2,4")
10095 (set (attr "fp_mode") (const_string "single"))
10096 (set_attr "type" "jump_ind")])
10097
10098 (define_insn "sibcall_media"
10099 [(call (mem:DI (match_operand 0 "target_reg_operand" "k"))
10100 (match_operand 1 "" ""))
10101 (use (reg:SI PR_MEDIA_REG))
10102 (return)]
10103 "TARGET_SHMEDIA"
10104 "blink %0, r63"
10105 [(set_attr "type" "jump_media")])
10106
10107 (define_expand "sibcall"
10108 [(parallel
10109 [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
10110 (match_operand 1 "" ""))
10111 (match_operand 2 "" "")
10112 (use (reg:SI FPSCR_MODES_REG))
10113 (return)])]
10114 ""
10115 {
10116 if (TARGET_SHMEDIA)
10117 {
10118 operands[0] = shmedia_prepare_call_address (operands[0], 1);
10119 emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
10120 DONE;
10121 }
10122 else if (TARGET_SHCOMPACT && operands[2]
10123 && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
10124 {
10125 rtx cookie_rtx = operands[2];
10126 long cookie = INTVAL (cookie_rtx);
10127 rtx func = XEXP (operands[0], 0);
10128 rtx mach, r1;
10129
10130 if (flag_pic)
10131 {
10132 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10133 {
10134 rtx reg = gen_reg_rtx (Pmode);
10135
10136 emit_insn (gen_symGOT2reg (reg, func));
10137 func = reg;
10138 }
10139 else
10140 func = legitimize_pic_address (func, Pmode, 0);
10141 }
10142
10143 /* FIXME: if we could tell whether all argument registers are
10144 already taken, we could decide whether to force the use of
10145 MACH_REG or to stick to R0_REG. Unfortunately, there's no
10146 simple way to tell. We could use the CALL_COOKIE, but we
10147 can't currently tell a register used for regular argument
10148 passing from one that is unused. If we leave it up to reload
10149 to decide which register to use, it seems to always choose
10150 R0_REG, which leaves no available registers in SIBCALL_REGS
10151 to hold the address of the trampoline. */
10152 mach = gen_rtx_REG (SImode, MACH_REG);
10153 r1 = gen_rtx_REG (SImode, R1_REG);
10154
10155 /* Since such a call function may use all call-clobbered
10156 registers, we force a mode switch earlier, so that we don't
10157 run out of registers when adjusting fpscr for the call. */
10158 emit_insn (gen_force_mode_for_call ());
10159
10160 operands[0]
10161 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
10162 operands[0] = force_reg (SImode, operands[0]);
10163
10164 /* We don't need a return trampoline, since the callee will
10165 return directly to the upper caller. */
10166 if (cookie & CALL_COOKIE_RET_TRAMP (1))
10167 {
10168 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
10169 cookie_rtx = GEN_INT (cookie);
10170 }
10171
10172 emit_move_insn (mach, func);
10173 emit_move_insn (r1, cookie_rtx);
10174
10175 emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
10176 DONE;
10177 }
10178 else if (TARGET_SHCOMPACT && flag_pic
10179 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
10180 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
10181 {
10182 rtx reg = gen_reg_rtx (Pmode);
10183
10184 emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
10185 XEXP (operands[0], 0) = reg;
10186 }
10187 if (flag_pic && TARGET_SH2
10188 && MEM_P (operands[0])
10189 && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
10190 /* The PLT needs the PIC register, but the epilogue would have
10191 to restore it, so we can only use PC-relative PIC calls for
10192 static functions. */
10193 && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0)))
10194 {
10195 emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1]));
10196 DONE;
10197 }
10198 else
10199 operands[0] = force_reg (SImode, XEXP (operands[0], 0));
10200
10201 emit_call_insn (gen_sibcalli (operands[0], operands[1]));
10202 DONE;
10203 })
10204
10205 (define_insn "sibcall_valuei"
10206 [(set (match_operand 0 "" "=rf")
10207 (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
10208 (match_operand 2 "" "")))
10209 (use (reg:SI FPSCR_MODES_REG))
10210 (return)]
10211 "TARGET_SH1"
10212 "jmp @%1%#"
10213 [(set_attr "needs_delay_slot" "yes")
10214 (set (attr "fp_mode")
10215 (if_then_else (eq_attr "fpu_single" "yes")
10216 (const_string "single") (const_string "double")))
10217 (set_attr "type" "jump_ind")])
10218
10219 (define_insn "sibcall_valuei_pcrel"
10220 [(set (match_operand 0 "" "=rf")
10221 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
10222 (match_operand 2 "" "")))
10223 (use (match_operand 3 "" ""))
10224 (use (reg:SI FPSCR_MODES_REG))
10225 (return)]
10226 "TARGET_SH2"
10227 {
10228 return "braf %1" "\n"
10229 "%O3:%#";
10230 }
10231 [(set_attr "needs_delay_slot" "yes")
10232 (set (attr "fp_mode")
10233 (if_then_else (eq_attr "fpu_single" "yes")
10234 (const_string "single") (const_string "double")))
10235 (set_attr "type" "jump_ind")])
10236
10237 (define_insn_and_split "sibcall_value_pcrel"
10238 [(set (match_operand 0 "" "=rf")
10239 (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
10240 (match_operand 2 "" "")))
10241 (use (reg:SI FPSCR_MODES_REG))
10242 (clobber (match_scratch:SI 3 "=&k"))
10243 (return)]
10244 "TARGET_SH2"
10245 "#"
10246 "reload_completed"
10247 [(const_int 0)]
10248 {
10249 rtx lab = PATTERN (gen_call_site ());
10250 rtx call_insn;
10251
10252 sh_expand_sym_label2reg (operands[3], operands[1], lab, true);
10253 call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
10254 operands[3],
10255 operands[2],
10256 copy_rtx (lab)));
10257 SIBLING_CALL_P (call_insn) = 1;
10258 DONE;
10259 }
10260 [(set_attr "needs_delay_slot" "yes")
10261 (set (attr "fp_mode")
10262 (if_then_else (eq_attr "fpu_single" "yes")
10263 (const_string "single") (const_string "double")))
10264 (set_attr "type" "jump_ind")])
10265
10266 (define_insn "sibcall_value_compact"
10267 [(set (match_operand 0 "" "=rf,rf")
10268 (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
10269 (match_operand 2 "" "")))
10270 (return)
10271 (use (match_operand:SI 3 "register_operand" "z,x"))
10272 (use (reg:SI R1_REG))
10273 (use (reg:SI FPSCR_MODES_REG))
10274 ;; We want to make sure the `x' above will only match MACH_REG
10275 ;; because sibcall_epilogue may clobber MACL_REG.
10276 (clobber (reg:SI MACL_REG))]
10277 "TARGET_SHCOMPACT"
10278 {
10279 static const char* alt[] =
10280 {
10281 "jmp @%1%#",
10282
10283 "jmp @%1" "\n"
10284 " sts %3,r0"
10285 };
10286 return alt[which_alternative];
10287 }
10288 [(set_attr "needs_delay_slot" "yes,no")
10289 (set_attr "length" "2,4")
10290 (set (attr "fp_mode") (const_string "single"))
10291 (set_attr "type" "jump_ind")])
10292
10293 (define_insn "sibcall_value_media"
10294 [(set (match_operand 0 "" "=rf")
10295 (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
10296 (match_operand 2 "" "")))
10297 (use (reg:SI PR_MEDIA_REG))
10298 (return)]
10299 "TARGET_SHMEDIA"
10300 "blink %1, r63"
10301 [(set_attr "type" "jump_media")])
10302
10303 (define_expand "sibcall_value"
10304 [(parallel
10305 [(set (match_operand 0 "arith_reg_operand" "")
10306 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
10307 (match_operand 2 "" "")))
10308 (match_operand 3 "" "")
10309 (use (reg:SI FPSCR_MODES_REG))
10310 (return)])]
10311 ""
10312 {
10313 if (TARGET_SHMEDIA)
10314 {
10315 operands[1] = shmedia_prepare_call_address (operands[1], 1);
10316 emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
10317 operands[2]));
10318 DONE;
10319 }
10320 else if (TARGET_SHCOMPACT && operands[3]
10321 && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
10322 {
10323 rtx cookie_rtx = operands[3];
10324 long cookie = INTVAL (cookie_rtx);
10325 rtx func = XEXP (operands[1], 0);
10326 rtx mach, r1;
10327
10328 if (flag_pic)
10329 {
10330 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10331 {
10332 rtx reg = gen_reg_rtx (Pmode);
10333
10334 emit_insn (gen_symGOT2reg (reg, func));
10335 func = reg;
10336 }
10337 else
10338 func = legitimize_pic_address (func, Pmode, 0);
10339 }
10340
10341 /* FIXME: if we could tell whether all argument registers are
10342 already taken, we could decide whether to force the use of
10343 MACH_REG or to stick to R0_REG. Unfortunately, there's no
10344 simple way to tell. We could use the CALL_COOKIE, but we
10345 can't currently tell a register used for regular argument
10346 passing from one that is unused. If we leave it up to reload
10347 to decide which register to use, it seems to always choose
10348 R0_REG, which leaves no available registers in SIBCALL_REGS
10349 to hold the address of the trampoline. */
10350 mach = gen_rtx_REG (SImode, MACH_REG);
10351 r1 = gen_rtx_REG (SImode, R1_REG);
10352
10353 /* Since such a call function may use all call-clobbered
10354 registers, we force a mode switch earlier, so that we don't
10355 run out of registers when adjusting fpscr for the call. */
10356 emit_insn (gen_force_mode_for_call ());
10357
10358 operands[1]
10359 = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT);
10360 operands[1] = force_reg (SImode, operands[1]);
10361
10362 /* We don't need a return trampoline, since the callee will
10363 return directly to the upper caller. */
10364 if (cookie & CALL_COOKIE_RET_TRAMP (1))
10365 {
10366 cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
10367 cookie_rtx = GEN_INT (cookie);
10368 }
10369
10370 emit_move_insn (mach, func);
10371 emit_move_insn (r1, cookie_rtx);
10372
10373 emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
10374 operands[2], mach));
10375 DONE;
10376 }
10377 else if (TARGET_SHCOMPACT && flag_pic
10378 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
10379 && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
10380 {
10381 rtx reg = gen_reg_rtx (Pmode);
10382
10383 emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
10384 XEXP (operands[1], 0) = reg;
10385 }
10386 if (flag_pic && TARGET_SH2
10387 && MEM_P (operands[1])
10388 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
10389 /* The PLT needs the PIC register, but the epilogue would have
10390 to restore it, so we can only use PC-relative PIC calls for
10391 static functions. */
10392 && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
10393 {
10394 emit_call_insn (gen_sibcall_value_pcrel (operands[0],
10395 XEXP (operands[1], 0),
10396 operands[2]));
10397 DONE;
10398 }
10399 else
10400 operands[1] = force_reg (SImode, XEXP (operands[1], 0));
10401
10402 emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
10403 DONE;
10404 })
10405
10406 (define_insn "call_value_pop_compact"
10407 [(set (match_operand 0 "" "=rf")
10408 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
10409 (match_operand 2 "" "")))
10410 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
10411 (match_operand 4 "immediate_operand" "n")))
10412 (match_operand 3 "immediate_operand" "n")
10413 (use (reg:SI R0_REG))
10414 (use (reg:SI R1_REG))
10415 (use (reg:SI FPSCR_MODES_REG))
10416 (clobber (reg:SI PR_REG))]
10417 "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
10418 "jsr @%1%#"
10419 [(set_attr "type" "call")
10420 (set (attr "fp_mode")
10421 (if_then_else (eq_attr "fpu_single" "yes")
10422 (const_string "single") (const_string "double")))
10423 (set_attr "needs_delay_slot" "yes")])
10424
10425 (define_insn "call_value_pop_compact_rettramp"
10426 [(set (match_operand 0 "" "=rf")
10427 (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
10428 (match_operand 2 "" "")))
10429 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
10430 (match_operand 4 "immediate_operand" "n")))
10431 (match_operand 3 "immediate_operand" "n")
10432 (use (reg:SI R0_REG))
10433 (use (reg:SI R1_REG))
10434 (use (reg:SI FPSCR_MODES_REG))
10435 (clobber (reg:SI R10_REG))
10436 (clobber (reg:SI PR_REG))]
10437 "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
10438 "jsr @%1%#"
10439 [(set_attr "type" "call")
10440 (set (attr "fp_mode")
10441 (if_then_else (eq_attr "fpu_single" "yes")
10442 (const_string "single") (const_string "double")))
10443 (set_attr "needs_delay_slot" "yes")])
10444
10445 (define_expand "call_value_pop"
10446 [(parallel [(set (match_operand 0 "arith_reg_operand" "")
10447 (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
10448 (match_operand 2 "" "")))
10449 (match_operand 3 "" "")
10450 (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
10451 (match_operand 4 "" "")))])]
10452 "TARGET_SHCOMPACT"
10453 {
10454 rtx cookie_rtx;
10455 long cookie;
10456 rtx func;
10457 rtx r0, r1;
10458
10459 gcc_assert (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]));
10460 cookie_rtx = operands[3];
10461 cookie = INTVAL (cookie_rtx);
10462 func = XEXP (operands[1], 0);
10463
10464 if (flag_pic)
10465 {
10466 if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
10467 {
10468 rtx reg = gen_reg_rtx (Pmode);
10469
10470 emit_insn (gen_symGOTPLT2reg (reg, func));
10471 func = reg;
10472 }
10473 else
10474 func = legitimize_pic_address (func, Pmode, 0);
10475 }
10476
10477 r0 = gen_rtx_REG (SImode, R0_REG);
10478 r1 = gen_rtx_REG (SImode, R1_REG);
10479
10480 /* Since such a call function may use all call-clobbered
10481 registers, we force a mode switch earlier, so that we don't
10482 run out of registers when adjusting fpscr for the call. */
10483 emit_insn (gen_force_mode_for_call ());
10484
10485 operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline",
10486 SFUNC_GOT);
10487 operands[1] = force_reg (SImode, operands[1]);
10488
10489 emit_move_insn (r0, func);
10490 emit_move_insn (r1, cookie_rtx);
10491
10492 if (cookie & CALL_COOKIE_RET_TRAMP (1))
10493 emit_call_insn (gen_call_value_pop_compact_rettramp
10494 (operands[0], operands[1], operands[2],
10495 operands[3], operands[4]));
10496 else
10497 emit_call_insn (gen_call_value_pop_compact
10498 (operands[0], operands[1], operands[2],
10499 operands[3], operands[4]));
10500
10501 DONE;
10502 })
10503
10504 (define_expand "sibcall_epilogue"
10505 [(return)]
10506 ""
10507 {
10508 sh_expand_epilogue (true);
10509 if (TARGET_SHCOMPACT)
10510 {
10511 rtx_insn *insn;
10512 rtx set;
10513
10514 /* If epilogue clobbers r0, preserve it in macl. */
10515 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
10516 if ((set = single_set (insn))
10517 && REG_P (SET_DEST (set))
10518 && REGNO (SET_DEST (set)) == R0_REG)
10519 {
10520 rtx r0 = gen_rtx_REG (SImode, R0_REG);
10521 rtx tmp = gen_rtx_REG (SImode, MACL_REG);
10522
10523 /* We can't tell at this point whether the sibcall is a
10524 sibcall_compact and, if it is, whether it uses r0 or
10525 mach as operand 2, so let the instructions that
10526 preserve r0 be optimized away if r0 turns out to be
10527 dead. */
10528 emit_insn_before (gen_rtx_SET (tmp, r0), insn);
10529 emit_move_insn (r0, tmp);
10530 break;
10531 }
10532 }
10533 DONE;
10534 })
10535
10536 (define_insn "indirect_jump_compact"
10537 [(set (pc)
10538 (match_operand:SI 0 "arith_reg_operand" "r"))]
10539 "TARGET_SH1"
10540 "jmp @%0%#"
10541 [(set_attr "needs_delay_slot" "yes")
10542 (set_attr "type" "jump_ind")])
10543
10544 (define_expand "indirect_jump"
10545 [(set (pc)
10546 (match_operand 0 "register_operand" ""))]
10547 ""
10548 {
10549 if (GET_MODE (operands[0]) != Pmode)
10550 operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0);
10551 })
10552
10553 ;; The use of operand 1 / 2 helps us distinguish case table jumps
10554 ;; which can be present in structured code from indirect jumps which can not
10555 ;; be present in structured code. This allows -fprofile-arcs to work.
10556
10557 ;; For SH1 processors.
10558 (define_insn "casesi_jump_1"
10559 [(set (pc)
10560 (match_operand:SI 0 "register_operand" "r"))
10561 (use (label_ref (match_operand 1 "" "")))]
10562 "TARGET_SH1"
10563 "jmp @%0%#"
10564 [(set_attr "needs_delay_slot" "yes")
10565 (set_attr "type" "jump_ind")])
10566
10567 ;; For all later processors.
10568 (define_insn "casesi_jump_2"
10569 [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
10570 (label_ref (match_operand 1 "" ""))))
10571 (use (label_ref (match_operand 2 "" "")))]
10572 "TARGET_SH2
10573 && (! INSN_UID (operands[1]) || prev_real_insn (operands[1]) == insn)"
10574 "braf %0%#"
10575 [(set_attr "needs_delay_slot" "yes")
10576 (set_attr "type" "jump_ind")])
10577
10578 (define_insn "casesi_jump_media"
10579 [(set (pc) (match_operand 0 "target_reg_operand" "b"))
10580 (use (label_ref (match_operand 1 "" "")))]
10581 "TARGET_SHMEDIA"
10582 "blink %0, r63"
10583 [(set_attr "type" "jump_media")])
10584
10585 ;; Call subroutine returning any type.
10586 ;; ??? This probably doesn't work.
10587 (define_expand "untyped_call"
10588 [(parallel [(call (match_operand 0 "" "")
10589 (const_int 0))
10590 (match_operand 1 "" "")
10591 (match_operand 2 "" "")])]
10592 "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
10593 {
10594 if (! TARGET_SHMEDIA)
10595 {
10596 /* RA does not know that the call sets the function value registers.
10597 We avoid problems by claiming that those registers are clobbered
10598 at this point. */
10599 for (int i = 0; i < XVECLEN (operands[2], 0); i++)
10600 {
10601 rtx set = XVECEXP (operands[2], 0, i);
10602 emit_clobber (SET_SRC (set));
10603 }
10604 }
10605
10606 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
10607
10608 for (int i = 0; i < XVECLEN (operands[2], 0); i++)
10609 {
10610 rtx set = XVECEXP (operands[2], 0, i);
10611 emit_move_insn (SET_DEST (set), SET_SRC (set));
10612 }
10613
10614 /* The optimizer does not know that the call sets the function value
10615 registers we stored in the result block. We avoid problems by
10616 claiming that all hard registers are used and clobbered at this
10617 point. */
10618 emit_insn (gen_blockage ());
10619
10620 DONE;
10621 })
10622 \f
10623 ;; ------------------------------------------------------------------------
10624 ;; Misc insns
10625 ;; ------------------------------------------------------------------------
10626
10627 (define_insn "dect"
10628 [(set (reg:SI T_REG)
10629 (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
10630 (set (match_operand:SI 0 "arith_reg_dest" "=r")
10631 (plus:SI (match_dup 1) (const_int -1)))]
10632 "TARGET_SH2"
10633 "dt %0"
10634 [(set_attr "type" "arith")])
10635
10636 (define_insn "nop"
10637 [(const_int 0)]
10638 ""
10639 "nop")
10640
10641 ;; Load address of a label. This is only generated by the casesi expand,
10642 ;; and by machine_dependent_reorg (fixing up fp moves).
10643 ;; This must use unspec, because this only works for labels that are
10644 ;; within range.
10645 (define_insn "mova"
10646 [(set (reg:SI R0_REG)
10647 (unspec:SI [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
10648 "TARGET_SH1"
10649 "mova %O0,r0"
10650 [(set_attr "in_delay_slot" "no")
10651 (set_attr "type" "arith")])
10652
10653 ;; machine_dependent_reorg will make this a `mova'.
10654 (define_insn "mova_const"
10655 [(set (reg:SI R0_REG)
10656 (unspec:SI [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
10657 "TARGET_SH1"
10658 "#"
10659 [(set_attr "in_delay_slot" "no")
10660 (set_attr "type" "arith")])
10661
10662 ;; Loads of the GOTPC relocation values must not be optimized away
10663 ;; by e.g. any kind of CSE and must stay as they are. Although there
10664 ;; are other various ways to ensure this, we use an artificial counter
10665 ;; operand to generate unique symbols.
10666 (define_expand "GOTaddr2picreg"
10667 [(set (reg:SI R0_REG)
10668 (unspec:SI [(const:SI (unspec:SI [(match_dup 2)
10669 (match_operand:SI 0 "" "")]
10670 UNSPEC_PIC))] UNSPEC_MOVA))
10671 (set (match_dup 1)
10672 (const:SI (unspec:SI [(match_dup 2) (match_dup 0)] UNSPEC_PIC)))
10673 (set (match_dup 1) (plus:SI (match_dup 1) (reg:SI R0_REG)))]
10674 ""
10675 {
10676 if (TARGET_VXWORKS_RTP)
10677 {
10678 rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
10679 rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
10680 emit_insn (gen_vxworks_picreg (gott_base, gott_index));
10681 DONE;
10682 }
10683
10684 operands[1] = gen_rtx_REG (Pmode, PIC_REG);
10685 operands[2] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
10686
10687 if (TARGET_SHMEDIA)
10688 {
10689 rtx tr = gen_rtx_REG (Pmode, TR0_REG);
10690 rtx pic = operands[1];
10691 rtx lab = PATTERN (gen_call_site ());
10692 rtx insn, equiv;
10693
10694 equiv = operands[2];
10695 operands[2] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], lab),
10696 UNSPEC_PCREL_SYMOFF);
10697 operands[2] = gen_rtx_CONST (Pmode, operands[2]);
10698
10699 if (Pmode == SImode)
10700 {
10701 emit_insn (gen_movsi_const (pic, operands[2]));
10702 emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
10703 }
10704 else
10705 {
10706 emit_insn (gen_movdi_const (pic, operands[2]));
10707 emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
10708 }
10709
10710 insn = emit_move_insn (operands[1], tr);
10711
10712 set_unique_reg_note (insn, REG_EQUAL, equiv);
10713
10714 DONE;
10715 }
10716 })
10717
10718 ;; A helper for GOTaddr2picreg to finish up the initialization of the
10719 ;; PIC register.
10720 (define_expand "vxworks_picreg"
10721 [(set (reg:SI PIC_REG)
10722 (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
10723 (set (reg:SI R0_REG)
10724 (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
10725 (set (reg:SI PIC_REG)
10726 (mem:SI (reg:SI PIC_REG)))
10727 (set (reg:SI PIC_REG)
10728 (mem:SI (plus:SI (reg:SI PIC_REG)
10729 (reg:SI R0_REG))))]
10730 "TARGET_VXWORKS_RTP")
10731
10732 (define_insn "*ptb"
10733 [(set (match_operand 0 "target_reg_operand" "=b")
10734 (const (unspec [(match_operand 1 "" "Csy")]
10735 UNSPEC_DATALABEL)))]
10736 "TARGET_SHMEDIA && flag_pic
10737 && satisfies_constraint_Csy (operands[1])"
10738 "ptb/u datalabel %1, %0"
10739 [(set_attr "type" "ptabs_media")
10740 (set_attr "length" "*")])
10741
10742 (define_insn "ptrel_si"
10743 [(set (match_operand:SI 0 "target_reg_operand" "=b")
10744 (plus:SI (match_operand:SI 1 "register_operand" "r")
10745 (pc)))
10746 (match_operand:SI 2 "" "")]
10747 "TARGET_SHMEDIA"
10748 "%O2: ptrel/u %1, %0"
10749 [(set_attr "type" "ptabs_media")])
10750
10751 (define_insn "ptrel_di"
10752 [(set (match_operand:DI 0 "target_reg_operand" "=b")
10753 (plus:DI (match_operand:DI 1 "register_operand" "r")
10754 (pc)))
10755 (match_operand:DI 2 "" "")]
10756 "TARGET_SHMEDIA"
10757 "%O2: ptrel/u %1, %0"
10758 [(set_attr "type" "ptabs_media")])
10759
10760 (define_expand "builtin_setjmp_receiver"
10761 [(match_operand 0 "" "")]
10762 "flag_pic"
10763 {
10764 emit_insn (gen_GOTaddr2picreg (const0_rtx));
10765 DONE;
10766 })
10767
10768 (define_expand "call_site"
10769 [(unspec [(match_dup 0)] UNSPEC_CALLER)]
10770 "TARGET_SH1"
10771 {
10772 static HOST_WIDE_INT i = 0;
10773 operands[0] = GEN_INT (i);
10774 i++;
10775 })
10776
10777 ;; op0 = op1 + r12 but hide it before reload completed. See the comment
10778 ;; in symGOT_load expand.
10779 (define_insn_and_split "chk_guard_add"
10780 [(set (match_operand:SI 0 "register_operand" "=&r")
10781 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
10782 (reg:SI PIC_REG)]
10783 UNSPEC_CHKADD))]
10784 "TARGET_SH1"
10785 "#"
10786 "TARGET_SH1 && reload_completed"
10787 [(set (match_dup 0) (reg:SI PIC_REG))
10788 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
10789 ""
10790 [(set_attr "type" "arith")])
10791
10792 (define_expand "sym_label2reg"
10793 [(set (match_operand:SI 0 "" "")
10794 (const:SI (unspec:SI [(match_operand:SI 1 "" "")
10795 (const (plus:SI (match_operand:SI 2 "" "")
10796 (const_int 2)))]
10797 UNSPEC_SYMOFF)))]
10798 "TARGET_SH1" "")
10799
10800 (define_expand "symPCREL_label2reg"
10801 [(set (match_operand:SI 0 "" "")
10802 (const:SI
10803 (unspec:SI
10804 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PCREL))
10805 (const:SI (plus:SI (match_operand:SI 2 "" "")
10806 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))]
10807 "TARGET_SH1"
10808 "")
10809
10810 (define_expand "symGOT_load"
10811 [(set (match_dup 2) (match_operand 1 "" ""))
10812 (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG)))
10813 (set (match_operand 0 "" "") (mem (match_dup 3)))]
10814 ""
10815 {
10816 rtx mem;
10817 bool stack_chk_guard_p = false;
10818
10819 operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10820 operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
10821
10822 if (!TARGET_SHMEDIA
10823 && flag_stack_protect
10824 && GET_CODE (operands[1]) == CONST
10825 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
10826 && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
10827 && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
10828 "__stack_chk_guard") == 0)
10829 stack_chk_guard_p = true;
10830
10831 if (TARGET_SHMEDIA)
10832 {
10833 rtx reg = operands[2];
10834
10835 if (Pmode == DImode)
10836 {
10837 if (flag_pic > 1)
10838 emit_insn (gen_movdi_const_32bit (reg, operands[1]));
10839 else
10840 emit_insn (gen_movdi_const_16bit (reg, operands[1]));
10841 }
10842 else
10843 {
10844 if (flag_pic > 1)
10845 emit_insn (gen_movsi_const (reg, operands[1]));
10846 else
10847 emit_insn (gen_movsi_const_16bit (reg, operands[1]));
10848 }
10849 }
10850 else
10851 emit_move_insn (operands[2], operands[1]);
10852
10853 /* When stack protector inserts codes after the result is set to
10854 R0, @(rX, r12) will cause a spill failure for R0. Use a unspec
10855 insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
10856 when rX is a GOT address for the guard symbol. Ugly but doesn't
10857 matter because this is a rare situation. */
10858 if (stack_chk_guard_p)
10859 emit_insn (gen_chk_guard_add (operands[3], operands[2]));
10860 else
10861 emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
10862 gen_rtx_REG (Pmode, PIC_REG)));
10863
10864 /* N.B. This is not constant for a GOTPLT relocation. */
10865 mem = gen_rtx_MEM (Pmode, operands[3]);
10866 MEM_NOTRAP_P (mem) = 1;
10867 /* ??? Should we have a special alias set for the GOT? */
10868 emit_move_insn (operands[0], mem);
10869
10870 DONE;
10871 })
10872
10873 (define_expand "sym2GOT"
10874 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
10875 ""
10876 "")
10877
10878 (define_expand "symGOT2reg"
10879 [(match_operand 0 "" "") (match_operand 1 "" "")]
10880 ""
10881 {
10882 rtx gotsym, insn;
10883
10884 gotsym = gen_sym2GOT (operands[1]);
10885 PUT_MODE (gotsym, Pmode);
10886 insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
10887
10888 MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
10889
10890 DONE;
10891 })
10892
10893 (define_expand "symGOTPLT2reg"
10894 [(match_operand 0 "" "") (match_operand 1 "" "")]
10895 ""
10896 {
10897 rtx pltsym = gen_rtx_CONST (Pmode,
10898 gen_rtx_UNSPEC (Pmode,
10899 gen_rtvec (1, operands[1]),
10900 UNSPEC_GOTPLT));
10901 emit_insn (gen_symGOT_load (operands[0], pltsym));
10902 DONE;
10903 })
10904
10905 (define_expand "sym2GOTOFF"
10906 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
10907 ""
10908 "")
10909
10910 (define_expand "symGOTOFF2reg"
10911 [(match_operand 0 "" "") (match_operand 1 "" "")]
10912 ""
10913 {
10914 rtx gotoffsym, insn;
10915 rtx t = (!can_create_pseudo_p ()
10916 ? operands[0]
10917 : gen_reg_rtx (GET_MODE (operands[0])));
10918
10919 gotoffsym = gen_sym2GOTOFF (operands[1]);
10920 PUT_MODE (gotoffsym, Pmode);
10921 emit_move_insn (t, gotoffsym);
10922 insn = emit_move_insn (operands[0],
10923 gen_rtx_PLUS (Pmode, t,
10924 gen_rtx_REG (Pmode, PIC_REG)));
10925
10926 set_unique_reg_note (insn, REG_EQUAL, operands[1]);
10927
10928 DONE;
10929 })
10930
10931 (define_expand "symPLT_label2reg"
10932 [(set (match_operand:SI 0 "" "")
10933 (const:SI
10934 (unspec:SI
10935 [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
10936 (const:SI (plus:SI (match_operand:SI 2 "" "")
10937 (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
10938 ;; Even though the PIC register is not really used by the call
10939 ;; sequence in which this is expanded, the PLT code assumes the PIC
10940 ;; register is set, so we must not skip its initialization. Since
10941 ;; we only use this expand as part of calling sequences, and never
10942 ;; to take the address of a function, this is the best point to
10943 ;; insert the (use). Using the PLT to take the address of a
10944 ;; function would be wrong, not only because the PLT entry could
10945 ;; then be called from a function that doesn't initialize the PIC
10946 ;; register to the proper GOT, but also because pointers to the
10947 ;; same function might not compare equal, should they be set by
10948 ;; different shared libraries.
10949 (use (reg:SI PIC_REG))]
10950 "TARGET_SH1"
10951 "")
10952
10953 (define_expand "sym2PIC"
10954 [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
10955 ""
10956 "")
10957
10958 ;; -------------------------------------------------------------------------
10959 ;; TLS code generation.
10960
10961 ;; FIXME: The multi-insn asm blocks should be converted to use
10962 ;; define_insn_and_split.
10963 ;; See the thread [PATCH/RFA] SH TLS support on gcc-patches
10964 ;; <http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01898.html>
10965 ;; for details.
10966
10967 (define_insn "tls_global_dynamic"
10968 [(set (match_operand:SI 0 "register_operand" "=&z")
10969 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10970 UNSPEC_TLSGD))
10971 (const_int 0)))
10972 (use (reg:SI FPSCR_MODES_REG))
10973 (use (reg:SI PIC_REG))
10974 (clobber (reg:SI PR_REG))
10975 (clobber (scratch:SI))]
10976 "TARGET_SH1"
10977 {
10978 return "mov.l 1f,r4" "\n"
10979 " mova 2f,r0" "\n"
10980 " mov.l 2f,r1" "\n"
10981 " add r0,r1" "\n"
10982 " jsr @r1" "\n"
10983 " add r12,r4" "\n"
10984 " bra 3f" "\n"
10985 " nop" "\n"
10986 " .align 2" "\n"
10987 "1: .long %a1@TLSGD" "\n"
10988 "2: .long __tls_get_addr@PLT" "\n"
10989 "3:";
10990 }
10991 [(set_attr "type" "tls_load")
10992 (set_attr "length" "26")])
10993
10994 (define_insn "tls_local_dynamic"
10995 [(set (match_operand:SI 0 "register_operand" "=&z")
10996 (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
10997 UNSPEC_TLSLDM))
10998 (const_int 0)))
10999 (use (reg:SI FPSCR_MODES_REG))
11000 (use (reg:SI PIC_REG))
11001 (clobber (reg:SI PR_REG))
11002 (clobber (scratch:SI))]
11003 "TARGET_SH1"
11004 {
11005 return "mov.l 1f,r4" "\n"
11006 " mova 2f,r0" "\n"
11007 " mov.l 2f,r1" "\n"
11008 " add r0,r1" "\n"
11009 " jsr @r1" "\n"
11010 " add r12,r4" "\n"
11011 " bra 3f" "\n"
11012 " nop" "\n"
11013 " .align 2" "\n"
11014 "1: .long %a1@TLSLDM" "\n"
11015 "2: .long __tls_get_addr@PLT" "\n"
11016 "3:";
11017 }
11018 [(set_attr "type" "tls_load")
11019 (set_attr "length" "26")])
11020
11021 (define_expand "sym2DTPOFF"
11022 [(const (unspec [(match_operand 0 "" "")] UNSPEC_DTPOFF))]
11023 ""
11024 "")
11025
11026 (define_expand "symDTPOFF2reg"
11027 [(match_operand 0 "" "") (match_operand 1 "" "") (match_operand 2 "" "")]
11028 ""
11029 {
11030 rtx dtpoffsym;
11031 rtx t = (!can_create_pseudo_p ()
11032 ? operands[0]
11033 : gen_reg_rtx (GET_MODE (operands[0])));
11034
11035 dtpoffsym = gen_sym2DTPOFF (operands[1]);
11036 PUT_MODE (dtpoffsym, Pmode);
11037 emit_move_insn (t, dtpoffsym);
11038 emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
11039 DONE;
11040 })
11041
11042 (define_expand "sym2GOTTPOFF"
11043 [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTTPOFF))]
11044 ""
11045 "")
11046
11047 (define_insn "tls_initial_exec"
11048 [(set (match_operand:SI 0 "register_operand" "=&r")
11049 (unspec:SI [(match_operand:SI 1 "" "")]
11050 UNSPEC_TLSIE))
11051 (use (reg:SI GBR_REG))
11052 (use (reg:SI PIC_REG))
11053 (clobber (reg:SI R0_REG))]
11054 ""
11055 {
11056 return "mov.l 1f,r0" "\n"
11057 " stc gbr,%0" "\n"
11058 " mov.l @(r0,r12),r0" "\n"
11059 " bra 2f" "\n"
11060 " add r0,%0" "\n"
11061 " .align 2" "\n"
11062 "1: .long %a1" "\n"
11063 "2:";
11064 }
11065 [(set_attr "type" "tls_load")
11066 (set_attr "length" "16")])
11067
11068 (define_expand "sym2TPOFF"
11069 [(const (unspec [(match_operand 0 "" "")] UNSPEC_TPOFF))]
11070 ""
11071 "")
11072
11073 (define_expand "symTPOFF2reg"
11074 [(match_operand 0 "" "") (match_operand 1 "" "")]
11075 ""
11076 {
11077 rtx tpoffsym;
11078
11079 tpoffsym = gen_sym2TPOFF (operands[1]);
11080 PUT_MODE (tpoffsym, Pmode);
11081 emit_move_insn (operands[0], tpoffsym);
11082 DONE;
11083 })
11084
11085 ;;------------------------------------------------------------------------------
11086 ;; Thread pointer getter and setter.
11087 ;;
11088 ;; On SH the thread pointer is kept in the GBR.
11089 ;; These patterns are usually expanded from the respective built-in functions.
11090 (define_expand "get_thread_pointersi"
11091 [(set (match_operand:SI 0 "arith_reg_dest") (reg:SI GBR_REG))]
11092 "TARGET_SH1")
11093
11094 ;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses.
11095 (define_insn "store_gbr"
11096 [(set (match_operand:SI 0 "arith_reg_dest" "=r") (reg:SI GBR_REG))]
11097 ""
11098 "stc gbr,%0"
11099 [(set_attr "type" "tls_load")])
11100
11101 (define_expand "set_thread_pointersi"
11102 [(set (reg:SI GBR_REG)
11103 (unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand")]
11104 UNSPECV_GBR))]
11105 "TARGET_SH1")
11106
11107 (define_insn "load_gbr"
11108 [(set (reg:SI GBR_REG)
11109 (unspec_volatile:SI [(match_operand:SI 0 "arith_reg_operand" "r")]
11110 UNSPECV_GBR))]
11111 "TARGET_SH1"
11112 "ldc %0,gbr"
11113 [(set_attr "type" "move")])
11114
11115 ;;------------------------------------------------------------------------------
11116 ;; Thread pointer relative memory loads and stores.
11117 ;;
11118 ;; On SH there are GBR displacement address modes which can be utilized to
11119 ;; access memory behind the thread pointer.
11120 ;; Since we do not allow using GBR for general purpose memory accesses, these
11121 ;; GBR addressing modes are formed by the combine pass.
11122 ;; This could be done with fewer patterns than below by using a mem predicate
11123 ;; for the GBR mem, but then reload would try to reload addresses with a
11124 ;; zero displacement for some strange reason.
11125
11126 (define_insn "*mov<mode>_gbr_load"
11127 [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z")
11128 (mem:QIHISI (plus:SI (reg:SI GBR_REG)
11129 (match_operand:QIHISI 1 "gbr_displacement"))))]
11130 "TARGET_SH1"
11131 "mov.<bwl> @(%O1,gbr),%0"
11132 [(set_attr "type" "load")])
11133
11134 (define_insn "*mov<mode>_gbr_load"
11135 [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z")
11136 (mem:QIHISI (reg:SI GBR_REG)))]
11137 "TARGET_SH1"
11138 "mov.<bwl> @(0,gbr),%0"
11139 [(set_attr "type" "load")])
11140
11141 (define_insn "*mov<mode>_gbr_load"
11142 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11143 (sign_extend:SI
11144 (mem:QIHI (plus:SI (reg:SI GBR_REG)
11145 (match_operand:QIHI 1 "gbr_displacement")))))]
11146 "TARGET_SH1"
11147 "mov.<bw> @(%O1,gbr),%0"
11148 [(set_attr "type" "load")])
11149
11150 (define_insn "*mov<mode>_gbr_load"
11151 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
11152 (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))]
11153 "TARGET_SH1"
11154 "mov.<bw> @(0,gbr),%0"
11155 [(set_attr "type" "load")])
11156
11157 (define_insn "*mov<mode>_gbr_store"
11158 [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG)
11159 (match_operand:QIHISI 0 "gbr_displacement")))
11160 (match_operand:QIHISI 1 "register_operand" "z"))]
11161 "TARGET_SH1"
11162 "mov.<bwl> %1,@(%O0,gbr)"
11163 [(set_attr "type" "store")])
11164
11165 (define_insn "*mov<mode>_gbr_store"
11166 [(set (mem:QIHISI (reg:SI GBR_REG))
11167 (match_operand:QIHISI 0 "register_operand" "z"))]
11168 "TARGET_SH1"
11169 "mov.<bwl> %0,@(0,gbr)"
11170 [(set_attr "type" "store")])
11171
11172 ;; DImode memory accesses have to be split in two SImode accesses.
11173 ;; Split them before reload, so that it gets a better chance to figure out
11174 ;; how to deal with the R0 restriction for the individual SImode accesses.
11175 ;; Do not match this insn during or after reload because it can't be split
11176 ;; afterwards.
11177 (define_insn_and_split "*movdi_gbr_load"
11178 [(set (match_operand:DI 0 "arith_reg_dest")
11179 (match_operand:DI 1 "gbr_address_mem"))]
11180 "TARGET_SH1 && can_create_pseudo_p ()"
11181 "#"
11182 "&& 1"
11183 [(set (match_dup 3) (match_dup 5))
11184 (set (match_dup 4) (match_dup 6))]
11185 {
11186 /* Swap low/high part load order on little endian, so that the result reg
11187 of the second load can be used better. */
11188 int off = TARGET_LITTLE_ENDIAN ? 1 : 0;
11189 operands[3 + off] = gen_lowpart (SImode, operands[0]);
11190 operands[5 + off] = gen_lowpart (SImode, operands[1]);
11191 operands[4 - off] = gen_highpart (SImode, operands[0]);
11192 operands[6 - off] = gen_highpart (SImode, operands[1]);
11193 })
11194
11195 (define_insn_and_split "*movdi_gbr_store"
11196 [(set (match_operand:DI 0 "gbr_address_mem")
11197 (match_operand:DI 1 "register_operand"))]
11198 "TARGET_SH1 && can_create_pseudo_p ()"
11199 "#"
11200 "&& 1"
11201 [(set (match_dup 3) (match_dup 5))
11202 (set (match_dup 4) (match_dup 6))]
11203 {
11204 /* Swap low/high part store order on big endian, so that stores of function
11205 call results can save a reg copy. */
11206 int off = TARGET_LITTLE_ENDIAN ? 0 : 1;
11207 operands[3 + off] = gen_lowpart (SImode, operands[0]);
11208 operands[5 + off] = gen_lowpart (SImode, operands[1]);
11209 operands[4 - off] = gen_highpart (SImode, operands[0]);
11210 operands[6 - off] = gen_highpart (SImode, operands[1]);
11211 })
11212
11213 ;; Sometimes memory accesses do not get combined with the store_gbr insn,
11214 ;; in particular when the displacements are in the range of the regular move
11215 ;; insns. Thus, in the first split pass after the combine pass we search
11216 ;; for missed opportunities and try to fix them up ourselves.
11217 ;; If an equivalent GBR address can be determined the load / store is split
11218 ;; into one of the GBR load / store patterns.
11219 ;; All of that must happen before reload (GBR address modes use R0 as the
11220 ;; other operand) and there's no point of doing it if the GBR is not
11221 ;; referenced in a function at all.
11222 (define_split
11223 [(set (match_operand:QIHISIDI 0 "register_operand")
11224 (match_operand:QIHISIDI 1 "memory_operand"))]
11225 "TARGET_SH1 && !reload_in_progress && !reload_completed
11226 && df_regs_ever_live_p (GBR_REG)"
11227 [(set (match_dup 0) (match_dup 1))]
11228 {
11229 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
11230 if (gbr_mem != NULL_RTX)
11231 operands[1] = replace_equiv_address (operands[1], gbr_mem);
11232 else
11233 FAIL;
11234 })
11235
11236 (define_split
11237 [(set (match_operand:SI 0 "register_operand")
11238 (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))]
11239 "TARGET_SH1 && !reload_in_progress && !reload_completed
11240 && df_regs_ever_live_p (GBR_REG)"
11241 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
11242 {
11243 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
11244 if (gbr_mem != NULL_RTX)
11245 operands[1] = replace_equiv_address (operands[1], gbr_mem);
11246 else
11247 FAIL;
11248 })
11249
11250 ;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads.
11251 ;; Split those so that a GBR load can be used.
11252 (define_split
11253 [(set (match_operand:SI 0 "register_operand")
11254 (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))]
11255 "TARGET_SH2A && !reload_in_progress && !reload_completed
11256 && df_regs_ever_live_p (GBR_REG)"
11257 [(set (match_dup 2) (match_dup 1))
11258 (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
11259 {
11260 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]);
11261 if (gbr_mem != NULL_RTX)
11262 {
11263 operands[2] = gen_reg_rtx (GET_MODE (operands[1]));
11264 operands[1] = replace_equiv_address (operands[1], gbr_mem);
11265 }
11266 else
11267 FAIL;
11268 })
11269
11270 (define_split
11271 [(set (match_operand:QIHISIDI 0 "memory_operand")
11272 (match_operand:QIHISIDI 1 "register_operand"))]
11273 "TARGET_SH1 && !reload_in_progress && !reload_completed
11274 && df_regs_ever_live_p (GBR_REG)"
11275 [(set (match_dup 0) (match_dup 1))]
11276 {
11277 rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]);
11278 if (gbr_mem != NULL_RTX)
11279 operands[0] = replace_equiv_address (operands[0], gbr_mem);
11280 else
11281 FAIL;
11282 })
11283
11284 ;;------------------------------------------------------------------------------
11285 ;; case instruction for switch statements.
11286
11287 ;; operand 0 is index
11288 ;; operand 1 is the minimum bound
11289 ;; operand 2 is the maximum bound - minimum bound + 1
11290 ;; operand 3 is CODE_LABEL for the table;
11291 ;; operand 4 is the CODE_LABEL to go to if index out of range.
11292 (define_expand "casesi"
11293 [(match_operand:SI 0 "arith_reg_operand" "")
11294 (match_operand:SI 1 "arith_reg_operand" "")
11295 (match_operand:SI 2 "arith_reg_operand" "")
11296 (match_operand 3 "" "") (match_operand 4 "" "")]
11297 ""
11298 {
11299 rtx reg = gen_reg_rtx (SImode);
11300 rtx reg2 = gen_reg_rtx (SImode);
11301 if (TARGET_SHMEDIA)
11302 {
11303 rtx reg = gen_reg_rtx (DImode);
11304 rtx reg2 = gen_reg_rtx (DImode);
11305 rtx reg3 = gen_reg_rtx (Pmode);
11306 rtx reg4 = gen_reg_rtx (Pmode);
11307 rtx reg5 = gen_reg_rtx (Pmode);
11308 rtx load, test;
11309
11310 operands[0] = convert_modes (DImode, SImode, operands[0], 0);
11311 operands[1] = convert_modes (DImode, SImode, operands[1], 0);
11312 operands[2] = convert_modes (DImode, SImode, operands[2], 1);
11313
11314 test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
11315 emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0],
11316 operands[4]));
11317 emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
11318 test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
11319 emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
11320 emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
11321 emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
11322 (Pmode, operands[3])));
11323 /* Messy: can we subreg to clean this up? */
11324 if (Pmode == DImode)
11325 load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]);
11326 else
11327 load = gen_casesi_load_media (reg4,
11328 gen_rtx_SUBREG (DImode, reg3, 0),
11329 reg2, operands[3]);
11330 PUT_MODE (SET_SRC (load), Pmode);
11331 emit_insn (load);
11332 /* ??? The following add could be eliminated if we used ptrel. */
11333 emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4));
11334 emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
11335 emit_barrier ();
11336 DONE;
11337 }
11338 operands[1] = copy_to_mode_reg (SImode, operands[1]);
11339 operands[2] = copy_to_mode_reg (SImode, operands[2]);
11340 /* If optimizing, casesi_worker depends on the mode of the instruction
11341 before label it 'uses' - operands[3]. */
11342 emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
11343 reg));
11344 emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
11345 if (TARGET_SH2)
11346 emit_jump_insn (gen_casesi_jump_2 (reg2, gen_label_rtx (), operands[3]));
11347 else
11348 emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
11349 /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
11350 operands[3], but to lab. We will fix this up in
11351 machine_dependent_reorg. */
11352 emit_barrier ();
11353 DONE;
11354 })
11355
11356 (define_expand "casesi_0"
11357 [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
11358 (set (match_dup 4) (minus:SI (match_dup 4)
11359 (match_operand:SI 1 "arith_operand" "")))
11360 (set (reg:SI T_REG)
11361 (gtu:SI (match_dup 4)
11362 (match_operand:SI 2 "arith_reg_operand" "")))
11363 (set (pc)
11364 (if_then_else (ne (reg:SI T_REG)
11365 (const_int 0))
11366 (label_ref (match_operand 3 "" ""))
11367 (pc)))]
11368 "TARGET_SH1"
11369 "")
11370
11371 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
11372 ;; reload; using a R0_REGS pseudo reg is likely to give poor code.
11373 ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
11374 (define_insn "casesi_worker_0"
11375 [(set (match_operand:SI 0 "register_operand" "=r,r")
11376 (unspec:SI [(match_operand:SI 1 "register_operand" "0,r")
11377 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11378 (clobber (match_scratch:SI 3 "=X,1"))
11379 (clobber (match_scratch:SI 4 "=&z,z"))]
11380 "TARGET_SH1"
11381 "#")
11382
11383 (define_split
11384 [(set (match_operand:SI 0 "register_operand" "")
11385 (unspec:SI [(match_operand:SI 1 "register_operand" "")
11386 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11387 (clobber (match_scratch:SI 3 ""))
11388 (clobber (match_scratch:SI 4 ""))]
11389 "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
11390 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
11391 (parallel [(set (match_dup 0)
11392 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
11393 (label_ref (match_dup 2))] UNSPEC_CASESI))
11394 (clobber (match_dup 3))])
11395 (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
11396 {
11397 if (GET_CODE (operands[2]) == CODE_LABEL)
11398 LABEL_NUSES (operands[2])++;
11399 })
11400
11401 (define_split
11402 [(set (match_operand:SI 0 "register_operand" "")
11403 (unspec:SI [(match_operand:SI 1 "register_operand" "")
11404 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11405 (clobber (match_scratch:SI 3 ""))
11406 (clobber (match_scratch:SI 4 ""))]
11407 "TARGET_SH2 && reload_completed"
11408 [(set (reg:SI R0_REG) (unspec:SI [(label_ref (match_dup 2))] UNSPEC_MOVA))
11409 (parallel [(set (match_dup 0)
11410 (unspec:SI [(reg:SI R0_REG) (match_dup 1)
11411 (label_ref (match_dup 2))] UNSPEC_CASESI))
11412 (clobber (match_dup 3))])]
11413 {
11414 if (GET_CODE (operands[2]) == CODE_LABEL)
11415 LABEL_NUSES (operands[2])++;
11416 })
11417
11418 ;; This may be replaced with casesi_worker_2 in sh_reorg for PIC.
11419 ;; The insn length is set to 8 for that case.
11420 (define_insn "casesi_worker_1"
11421 [(set (match_operand:SI 0 "register_operand" "=r,r")
11422 (unspec:SI [(reg:SI R0_REG)
11423 (match_operand:SI 1 "register_operand" "0,r")
11424 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
11425 (clobber (match_scratch:SI 3 "=X,1"))]
11426 "TARGET_SH1"
11427 {
11428 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
11429
11430 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11431
11432 switch (GET_MODE (diff_vec))
11433 {
11434 case SImode:
11435 return "shll2 %1" "\n"
11436 " mov.l @(r0,%1),%0";
11437 case HImode:
11438 return "add %1,%1" "\n"
11439 " mov.w @(r0,%1),%0";
11440 case QImode:
11441 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11442 return "mov.b @(r0,%1),%0" "\n"
11443 " extu.b %0,%0";
11444 else
11445 return "mov.b @(r0,%1),%0";
11446
11447 default:
11448 gcc_unreachable ();
11449 }
11450 }
11451 [(set_attr_alternative "length"
11452 [(if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))
11453 (if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))])])
11454
11455 (define_insn "casesi_worker_2"
11456 [(set (match_operand:SI 0 "register_operand" "=r,r")
11457 (unspec:SI [(reg:SI R0_REG)
11458 (match_operand:SI 1 "register_operand" "0,r")
11459 (label_ref (match_operand 2 "" ""))
11460 (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
11461 (clobber (match_operand:SI 4 "" "=X,1"))]
11462 "TARGET_SH2 && reload_completed && flag_pic"
11463 {
11464 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
11465 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11466
11467 switch (GET_MODE (diff_vec))
11468 {
11469 case SImode:
11470 return "shll2 %1" "\n"
11471 " add r0,%1" "\n"
11472 " mova %O3,r0" "\n"
11473 " mov.l @(r0,%1),%0";
11474 case HImode:
11475 return "add %1,%1" "\n"
11476 " add r0,%1" "\n"
11477 " mova %O3,r0" "\n"
11478 " mov.w @(r0,%1),%0";
11479 case QImode:
11480 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11481 return "add r0,%1" "\n"
11482 " mova %O3,r0" "\n"
11483 " mov.b @(r0,%1),%0" "\n"
11484 " extu.b %0,%0";
11485 else
11486 return "add r0,%1" "\n"
11487 " mova %O3,r0" "\n"
11488 " mov.b @(r0,%1),%0";
11489 default:
11490 gcc_unreachable ();
11491 }
11492 }
11493 [(set_attr "length" "8")])
11494
11495 (define_insn "casesi_shift_media"
11496 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
11497 (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
11498 (unspec:DI [(label_ref:DI (match_operand 2 "" ""))]
11499 UNSPEC_CASESI)))]
11500 "TARGET_SHMEDIA"
11501 {
11502 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
11503
11504 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11505
11506 switch (GET_MODE (diff_vec))
11507 {
11508 case SImode:
11509 return "shlli %1, 2, %0";
11510 case HImode:
11511 return "shlli %1, 1, %0";
11512 case QImode:
11513 if (rtx_equal_p (operands[0], operands[1]))
11514 return "";
11515 return "add %1, r63, %0";
11516 default:
11517 gcc_unreachable ();
11518 }
11519 }
11520 [(set_attr "type" "arith_media")])
11521
11522 (define_insn "casesi_load_media"
11523 [(set (match_operand 0 "any_arith_reg_dest" "=r")
11524 (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r")
11525 (match_operand:DI 2 "arith_reg_operand" "r")
11526 (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
11527 "TARGET_SHMEDIA"
11528 {
11529 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[3])));
11530
11531 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
11532
11533 switch (GET_MODE (diff_vec))
11534 {
11535 case SImode:
11536 return "ldx.l %1, %2, %0";
11537 case HImode:
11538 #if 0
11539 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11540 return "ldx.uw %1, %2, %0";
11541 #endif
11542 return "ldx.w %1, %2, %0";
11543 case QImode:
11544 if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
11545 return "ldx.ub %1, %2, %0";
11546 return "ldx.b %1, %2, %0";
11547 default:
11548 gcc_unreachable ();
11549 }
11550 }
11551 [(set_attr "type" "load_media")])
11552
11553 (define_expand "simple_return"
11554 [(simple_return)]
11555 "sh_can_use_simple_return_p ()")
11556
11557 (define_expand "return"
11558 [(return)]
11559 "reload_completed && epilogue_completed"
11560 {
11561 if (TARGET_SHMEDIA)
11562 {
11563 emit_jump_insn (gen_return_media ());
11564 DONE;
11565 }
11566
11567 if (TARGET_SHCOMPACT
11568 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
11569 {
11570 emit_jump_insn (gen_shcompact_return_tramp ());
11571 DONE;
11572 }
11573 })
11574
11575 (define_insn "*<code>_i"
11576 [(any_return)]
11577 "TARGET_SH1 && ! (TARGET_SHCOMPACT
11578 && (crtl->args.info.call_cookie
11579 & CALL_COOKIE_RET_TRAMP (1)))
11580 && reload_completed
11581 && ! sh_cfun_trap_exit_p ()"
11582 {
11583 if (TARGET_SH2A && (dbr_sequence_length () == 0)
11584 && !current_function_interrupt)
11585 return "rts/n";
11586 else
11587 return "%@ %#";
11588 }
11589 [(set_attr "type" "return")
11590 (set_attr "needs_delay_slot" "yes")])
11591
11592 ;; trapa has no delay slot.
11593 (define_insn "*return_trapa"
11594 [(return)]
11595 "TARGET_SH1 && !TARGET_SHCOMPACT
11596 && reload_completed"
11597 "%@"
11598 [(set_attr "type" "return")])
11599
11600 (define_expand "shcompact_return_tramp"
11601 [(return)]
11602 "TARGET_SHCOMPACT
11603 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11604 {
11605 rtx reg = gen_rtx_REG (Pmode, R0_REG);
11606
11607 function_symbol (reg, "__GCC_shcompact_return_trampoline", SFUNC_STATIC);
11608 emit_jump_insn (gen_shcompact_return_tramp_i ());
11609 DONE;
11610 })
11611
11612 (define_insn "shcompact_return_tramp_i"
11613 [(parallel [(return) (use (reg:SI R0_REG))])]
11614 "TARGET_SHCOMPACT
11615 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
11616 "jmp @r0%#"
11617 [(set_attr "type" "jump_ind")
11618 (set_attr "needs_delay_slot" "yes")])
11619
11620 (define_insn "return_media_i"
11621 [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])]
11622 "TARGET_SHMEDIA && reload_completed"
11623 "blink %0, r63"
11624 [(set_attr "type" "jump_media")])
11625
11626 (define_insn "return_media_rte"
11627 [(return)]
11628 "TARGET_SHMEDIA && reload_completed && current_function_interrupt"
11629 "rte"
11630 [(set_attr "type" "jump_media")])
11631
11632 (define_expand "return_media"
11633 [(return)]
11634 "TARGET_SHMEDIA && reload_completed"
11635 {
11636 int tr_regno = sh_media_register_for_return ();
11637 rtx tr;
11638
11639 if (current_function_interrupt)
11640 {
11641 emit_jump_insn (gen_return_media_rte ());
11642 DONE;
11643 }
11644 if (tr_regno < 0)
11645 {
11646 rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG);
11647
11648 gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]);
11649 tr_regno = TR0_REG;
11650 tr = gen_rtx_REG (Pmode, tr_regno);
11651 emit_move_insn (tr, r18);
11652 }
11653 else
11654 tr = gen_rtx_REG (Pmode, tr_regno);
11655
11656 emit_jump_insn (gen_return_media_i (tr));
11657 DONE;
11658 })
11659
11660 (define_insn "shcompact_preserve_incoming_args"
11661 [(set (match_operand:SI 0 "register_operand" "+r")
11662 (unspec:SI [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
11663 "TARGET_SHCOMPACT"
11664 ""
11665 [(set_attr "length" "0")])
11666
11667 (define_insn "shcompact_incoming_args"
11668 [(set (reg:SI R2_REG) (unspec:SI [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
11669 (set (reg:SI R3_REG) (unspec:SI [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
11670 (set (reg:SI R4_REG) (unspec:SI [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
11671 (set (reg:SI R5_REG) (unspec:SI [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
11672 (set (reg:SI R6_REG) (unspec:SI [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
11673 (set (reg:SI R7_REG) (unspec:SI [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
11674 (set (reg:SI R8_REG) (unspec:SI [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
11675 (set (reg:SI R9_REG) (unspec:SI [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
11676 (set (mem:BLK (reg:SI MACL_REG))
11677 (unspec:BLK [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
11678 (use (reg:SI R0_REG))
11679 (clobber (reg:SI R0_REG))
11680 (clobber (reg:SI MACL_REG))
11681 (clobber (reg:SI MACH_REG))
11682 (clobber (reg:SI PR_REG))]
11683 "TARGET_SHCOMPACT"
11684 "jsr @r0%#"
11685 [(set_attr "needs_delay_slot" "yes")])
11686
11687 (define_insn "shmedia_save_restore_regs_compact"
11688 [(set (reg:SI SP_REG)
11689 (plus:SI (reg:SI SP_REG)
11690 (match_operand:SI 0 "immediate_operand" "i")))
11691 (use (reg:SI R0_REG))
11692 (clobber (reg:SI PR_REG))]
11693 "TARGET_SHCOMPACT
11694 && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
11695 || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
11696 "jsr @r0%#"
11697 [(set_attr "needs_delay_slot" "yes")])
11698
11699 (define_expand "prologue"
11700 [(const_int 0)]
11701 ""
11702 {
11703 sh_expand_prologue ();
11704 DONE;
11705 })
11706
11707 (define_expand "epilogue"
11708 [(return)]
11709 ""
11710 {
11711 sh_expand_epilogue (false);
11712 if (TARGET_SHMEDIA
11713 || (TARGET_SHCOMPACT
11714 && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))))
11715 {
11716 emit_jump_insn (gen_return ());
11717 DONE;
11718 }
11719 })
11720
11721 (define_expand "eh_return"
11722 [(use (match_operand 0 "register_operand" ""))]
11723 ""
11724 {
11725 rtx ra = operands[0];
11726
11727 if (TARGET_SHMEDIA64)
11728 emit_insn (gen_eh_set_ra_di (ra));
11729 else
11730 emit_insn (gen_eh_set_ra_si (ra));
11731
11732 DONE;
11733 })
11734
11735 ;; Clobber the return address on the stack. We can't expand this
11736 ;; until we know where it will be put in the stack frame.
11737
11738 (define_insn "eh_set_ra_si"
11739 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
11740 UNSPECV_EH_RETURN)
11741 (clobber (match_scratch:SI 1 "=&r"))]
11742 "! TARGET_SHMEDIA64"
11743 "#")
11744
11745 (define_insn "eh_set_ra_di"
11746 [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
11747 UNSPECV_EH_RETURN)
11748 (clobber (match_scratch:DI 1 "=&r"))]
11749 "TARGET_SHMEDIA64"
11750 "#")
11751
11752 (define_split
11753 [(unspec_volatile [(match_operand 0 "register_operand" "")]
11754 UNSPECV_EH_RETURN)
11755 (clobber (match_scratch 1 ""))]
11756 "reload_completed"
11757 [(const_int 0)]
11758 {
11759 sh_set_return_address (operands[0], operands[1]);
11760 DONE;
11761 })
11762
11763 (define_insn "blockage"
11764 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
11765 ""
11766 ""
11767 [(set_attr "length" "0")])
11768 \f
11769 ;; Define movml instructions for SH2A target. Currently they are
11770 ;; used to push and pop all banked registers only.
11771
11772 (define_insn "movml_push_banked"
11773 [(set (match_operand:SI 0 "register_operand" "=r")
11774 (plus (match_dup 0) (const_int -32)))
11775 (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
11776 (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
11777 (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
11778 (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
11779 (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
11780 (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
11781 (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
11782 (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
11783 "TARGET_SH2A && REGNO (operands[0]) == 15"
11784 "movml.l r7,@-r15"
11785 [(set_attr "in_delay_slot" "no")])
11786
11787 (define_insn "movml_pop_banked"
11788 [(set (match_operand:SI 0 "register_operand" "=r")
11789 (plus (match_dup 0) (const_int 32)))
11790 (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
11791 (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
11792 (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
11793 (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
11794 (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
11795 (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
11796 (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
11797 (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
11798 "TARGET_SH2A && REGNO (operands[0]) == 15"
11799 "movml.l @r15+,r7"
11800 [(set_attr "in_delay_slot" "no")])
11801 \f
11802 ;; ------------------------------------------------------------------------
11803 ;; Scc instructions
11804 ;; ------------------------------------------------------------------------
11805
11806 (define_insn "movt"
11807 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11808 (match_operand:SI 1 "t_reg_operand"))]
11809 "TARGET_SH1"
11810 "movt %0"
11811 [(set_attr "type" "arith")])
11812
11813 (define_insn "movrt"
11814 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11815 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11816 "TARGET_SH2A"
11817 "movrt %0"
11818 [(set_attr "type" "arith")])
11819
11820 (define_expand "cstore4_media"
11821 [(set (match_operand:SI 0 "register_operand" "=r")
11822 (match_operator:SI 1 "sh_float_comparison_operator"
11823 [(match_operand 2 "logical_operand" "")
11824 (match_operand 3 "cmp_operand" "")]))]
11825 "TARGET_SHMEDIA"
11826 {
11827 machine_mode mode = GET_MODE (operands[2]);
11828 enum rtx_code code = GET_CODE (operands[1]);
11829 bool invert, swap;
11830 if (mode == VOIDmode)
11831 mode = GET_MODE (operands[3]);
11832 if (operands[2] == const0_rtx)
11833 {
11834 if (code == EQ || code == NE)
11835 operands[2] = operands[3], operands[3] = const0_rtx;
11836 }
11837 else
11838 operands[2] = force_reg (mode, operands[2]);
11839 if (operands[3] != const0_rtx)
11840 operands[3] = force_reg (mode, operands[3]);
11841
11842 switch (code)
11843 {
11844 case GEU:
11845 case GE:
11846 swap = invert = !FLOAT_MODE_P (mode);
11847 break;
11848
11849 case LEU:
11850 case LE:
11851 swap = FLOAT_MODE_P (mode), invert = !swap;
11852 break;
11853
11854 case LTU:
11855 case LT:
11856 swap = true, invert = false;
11857 break;
11858
11859 case GTU:
11860 case GT:
11861 case EQ:
11862 case UNORDERED:
11863 swap = invert = false;
11864 break;
11865
11866 case NE:
11867 swap = invert = true;
11868 break;
11869
11870 default:
11871 gcc_unreachable ();
11872 }
11873
11874 if (swap)
11875 {
11876 std::swap (operands[2], operands[3]);
11877 code = swap_condition (code);
11878 }
11879
11880 if (invert)
11881 {
11882 rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
11883 code = reverse_condition (code);
11884 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11885 emit_insn (gen_cstore4_media (tem, operands[1],
11886 operands[2], operands[3]));
11887 code = EQ;
11888 operands[2] = tem;
11889 operands[3] = const0_rtx;
11890 }
11891
11892 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
11893 })
11894
11895 (define_expand "cstoresi4"
11896 [(set (match_operand:SI 0 "register_operand" "=r")
11897 (match_operator:SI 1 "comparison_operator"
11898 [(match_operand:SI 2 "cmpsi_operand" "")
11899 (match_operand:SI 3 "arith_operand" "")]))]
11900 "TARGET_SH1 || TARGET_SHMEDIA"
11901 {
11902 if (TARGET_SHMEDIA)
11903 {
11904 emit_insn (gen_cstore4_media (operands[0], operands[1],
11905 operands[2], operands[3]));
11906 DONE;
11907 }
11908
11909 if (sh_expand_t_scc (operands))
11910 DONE;
11911
11912 if (! currently_expanding_to_rtl)
11913 FAIL;
11914
11915 sh_emit_compare_and_set (operands, SImode);
11916 DONE;
11917 })
11918
11919 (define_expand "cstoredi4"
11920 [(set (match_operand:SI 0 "register_operand" "=r")
11921 (match_operator:SI 1 "comparison_operator"
11922 [(match_operand:DI 2 "arith_operand" "")
11923 (match_operand:DI 3 "arith_operand" "")]))]
11924 "TARGET_SH2 || TARGET_SHMEDIA"
11925 {
11926 if (TARGET_SHMEDIA)
11927 {
11928 emit_insn (gen_cstore4_media (operands[0], operands[1],
11929 operands[2], operands[3]));
11930 DONE;
11931 }
11932
11933 if (sh_expand_t_scc (operands))
11934 DONE;
11935
11936 if (! currently_expanding_to_rtl)
11937 FAIL;
11938
11939 sh_emit_compare_and_set (operands, DImode);
11940 DONE;
11941 })
11942
11943 ;; Move the complement of the T reg to a reg.
11944 ;; On SH2A the movrt insn can be used.
11945 ;; On anything else than SH2A this has to be done with multiple instructions.
11946 ;; One obvious way would be:
11947 ;; cmp/eq ...
11948 ;; movt r0
11949 ;; xor #1,r0
11950 ;;
11951 ;; However, this puts pressure on r0 in most cases and thus the following is
11952 ;; more appealing:
11953 ;; cmp/eq ...
11954 ;; mov #-1,temp
11955 ;; negc temp,dest
11956 ;;
11957 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
11958 ;; becomes a one instruction operation. Moreover, care must be taken that
11959 ;; the insn can still be combined with inverted compare and branch code
11960 ;; around it. On the other hand, if a function returns the complement of
11961 ;; a previous comparison result in the T bit, the xor #1,r0 approach might
11962 ;; lead to better code.
11963 (define_expand "movnegt"
11964 [(set (match_operand:SI 0 "arith_reg_dest" "")
11965 (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
11966 "TARGET_SH1"
11967 {
11968 if (TARGET_SH2A)
11969 emit_insn (gen_movrt (operands[0], operands[1]));
11970 else
11971 {
11972 rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
11973 emit_insn (gen_movrt_negc (operands[0], operands[1], val));
11974 }
11975 DONE;
11976 })
11977
11978 (define_insn_and_split "movrt_negc"
11979 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
11980 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
11981 (set (reg:SI T_REG) (const_int 1))
11982 (use (match_operand:SI 2 "arith_reg_operand" "r"))]
11983 "TARGET_SH1"
11984 "negc %2,%0"
11985 "&& !sh_in_recog_treg_set_expr ()"
11986 [(const_int 0)]
11987 {
11988 if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands))
11989 DONE;
11990 else
11991 FAIL;
11992 }
11993 [(set_attr "type" "arith")])
11994
11995 ;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
11996 ;; pattern can be used by the combine pass. Using a scratch reg for the
11997 ;; -1 constant results in slightly better register allocations compared to
11998 ;; generating a pseudo reg before reload.
11999 (define_insn_and_split "*movrt_negc"
12000 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12001 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
12002 (clobber (match_scratch:SI 2 "=r"))
12003 (clobber (reg:SI T_REG))]
12004 "TARGET_SH1 && ! TARGET_SH2A"
12005 "#"
12006 "&& !sh_in_recog_treg_set_expr ()"
12007 [(const_int 0)]
12008 {
12009 if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands))
12010 DONE;
12011 else if (reload_completed)
12012 {
12013 emit_move_insn (operands[2], gen_int_mode (-1, SImode));
12014 emit_insn (gen_movrt_negc (operands[0], operands[1], operands[2]));
12015 DONE;
12016 }
12017 else
12018 FAIL;
12019 })
12020
12021 ;; Store the negated T bit in a reg using r0 and xor. This one doesn't
12022 ;; clobber the T bit, which is useful when storing the T bit and the
12023 ;; negated T bit in parallel. On SH2A the movrt insn can be used for that.
12024 ;; Usually we don't want this insn to be matched, except for cases where the
12025 ;; T bit clobber is really not appreciated. Hence the extra use on T_REG.
12026 (define_insn_and_split "movrt_xor"
12027 [(set (match_operand:SI 0 "arith_reg_dest" "=z")
12028 (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
12029 (use (reg:SI T_REG))]
12030 "TARGET_SH1"
12031 "#"
12032 "&& reload_completed"
12033 [(set (match_dup 0) (reg:SI T_REG))
12034 (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
12035
12036 ;; 0x7fffffff + T
12037 ;; 0x7fffffff + (1-T) = 0 - 0x80000000 - T
12038 ;;
12039 ;; Notice that 0 - 0x80000000 = 0x80000000.
12040
12041 ;; Single bit tests are usually done with zero_extract. On non-SH2A this
12042 ;; will use a tst-negc sequence. On SH2A it will use a bld-addc sequence.
12043 ;; The zeroth bit requires a special pattern, otherwise we get a shlr-addc.
12044 ;; This is a special case of the generic treg_set_expr pattern and thus has
12045 ;; to come first or it will never match.
12046 (define_insn_and_split "*mov_t_msb_neg"
12047 [(set (match_operand:SI 0 "arith_reg_dest")
12048 (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
12049 (const_int 1))
12050 (const_int 2147483647)))
12051 (clobber (reg:SI T_REG))]
12052 "TARGET_SH1"
12053 "#"
12054 "&& can_create_pseudo_p ()"
12055 [(parallel [(set (match_dup 0)
12056 (plus:SI (zero_extract:SI (match_dup 1)
12057 (const_int 1) (const_int 0))
12058 (const_int 2147483647)))
12059 (clobber (reg:SI T_REG))])])
12060
12061 (define_insn_and_split "*mov_t_msb_neg"
12062 [(set (match_operand:SI 0 "arith_reg_dest")
12063 (plus:SI (match_operand 1 "treg_set_expr")
12064 (const_int 2147483647))) ;; 0x7fffffff
12065 (clobber (reg:SI T_REG))]
12066 "TARGET_SH1"
12067 "#"
12068 "&& can_create_pseudo_p ()"
12069 [(const_int 0)]
12070 {
12071 if (negt_reg_operand (operands[1], VOIDmode))
12072 {
12073 emit_insn (gen_negc (operands[0],
12074 force_reg (SImode, GEN_INT (-2147483648LL))));
12075 DONE;
12076 }
12077
12078 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12079 if (ti.remove_trailing_nott ())
12080 emit_insn (gen_negc (operands[0],
12081 force_reg (SImode, GEN_INT (-2147483648LL))));
12082 else
12083 emit_insn (gen_addc (operands[0],
12084 force_reg (SImode, const0_rtx),
12085 force_reg (SImode, GEN_INT (2147483647))));
12086 DONE;
12087 })
12088
12089 (define_insn_and_split "*mov_t_msb_neg"
12090 [(set (match_operand:SI 0 "arith_reg_dest")
12091 (if_then_else:SI (match_operand 1 "treg_set_expr")
12092 (match_operand 2 "const_int_operand")
12093 (match_operand 3 "const_int_operand")))
12094 (clobber (reg:SI T_REG))]
12095 "TARGET_SH1 && can_create_pseudo_p ()
12096 && ((INTVAL (operands[2]) == -2147483648LL
12097 && INTVAL (operands[3]) == 2147483647LL)
12098 || (INTVAL (operands[2]) == 2147483647LL
12099 && INTVAL (operands[3]) == -2147483648LL))"
12100 "#"
12101 "&& 1"
12102 [(const_int 0)]
12103 {
12104 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12105
12106 if (INTVAL (operands[2]) == -2147483648LL)
12107 {
12108 if (ti.remove_trailing_nott ())
12109 emit_insn (gen_negc (operands[0],
12110 force_reg (SImode, GEN_INT (-2147483648LL))));
12111 else
12112 emit_insn (gen_addc (operands[0],
12113 force_reg (SImode, const0_rtx),
12114 force_reg (SImode, operands[3])));
12115 DONE;
12116 }
12117 else if (INTVAL (operands[2]) == 2147483647LL)
12118 {
12119 if (ti.remove_trailing_nott ())
12120 emit_insn (gen_addc (operands[0],
12121 force_reg (SImode, const0_rtx),
12122 force_reg (SImode, GEN_INT (2147483647LL))));
12123 else
12124 emit_insn (gen_negc (operands[0],
12125 force_reg (SImode, GEN_INT (-2147483648LL))));
12126 DONE;
12127 }
12128 else
12129 gcc_unreachable ();
12130 })
12131
12132 ;; The *negnegt pattern helps the combine pass to figure out how to fold
12133 ;; an explicit double T bit negation.
12134 (define_insn_and_split "*negnegt"
12135 [(set (reg:SI T_REG)
12136 (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
12137 "TARGET_SH1"
12138 "#"
12139 ""
12140 [(const_int 0)])
12141
12142 ;; Store (negated) T bit as all zeros or ones in a reg.
12143 ;; subc Rn,Rn ! Rn = Rn - Rn - T; T = T
12144 ;; not Rn,Rn ! Rn = 0 - Rn
12145 (define_insn_and_split "mov_neg_si_t"
12146 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12147 (neg:SI (match_operand 1 "treg_set_expr")))]
12148 "TARGET_SH1"
12149 {
12150 gcc_assert (t_reg_operand (operands[1], VOIDmode));
12151 return "subc %0,%0";
12152 }
12153 "&& can_create_pseudo_p () && !t_reg_operand (operands[1], VOIDmode)"
12154 [(const_int 0)]
12155 {
12156 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12157 emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
12158
12159 if (ti.remove_trailing_nott ())
12160 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
12161
12162 DONE;
12163 }
12164 [(set_attr "type" "arith")])
12165
12166 ;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
12167 (define_insn_and_split "*movtt"
12168 [(set (reg:SI T_REG)
12169 (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
12170 "TARGET_SH1"
12171 "#"
12172 ""
12173 [(const_int 0)])
12174
12175 ;; Invert the T bit.
12176 ;; On SH2A we can use the nott insn. On anything else this must be done with
12177 ;; multiple insns like:
12178 ;; movt Rn
12179 ;; tst Rn,Rn
12180 ;; This requires an additional pseudo. The SH specific sh_treg_combine RTL
12181 ;; pass will look for this insn. Disallow using it if pseudos can't be
12182 ;; created.
12183 ;; Don't split the nott inside the splitting of a treg_set_expr, or else
12184 ;; surrounding insns might not see and recombine it. Defer the splitting
12185 ;; of the nott until after the whole insn containing the treg_set_expr
12186 ;; has been split.
12187 (define_insn_and_split "nott"
12188 [(set (reg:SI T_REG)
12189 (xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))]
12190 "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())"
12191 {
12192 gcc_assert (TARGET_SH2A);
12193 return "nott";
12194 }
12195 "!TARGET_SH2A && can_create_pseudo_p () && !sh_in_recog_treg_set_expr ()"
12196 [(set (match_dup 0) (reg:SI T_REG))
12197 (set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))]
12198 {
12199 operands[0] = gen_reg_rtx (SImode);
12200 })
12201
12202 ;; Store T bit as MSB in a reg.
12203 ;; T = 0: 0x00000000 -> reg
12204 ;; T = 1: 0x80000000 -> reg
12205 (define_insn_and_split "*movt_msb"
12206 [(set (match_operand:SI 0 "arith_reg_dest")
12207 (mult:SI (match_operand:SI 1 "t_reg_operand")
12208 (const_int -2147483648))) ;; 0xffffffff80000000
12209 (clobber (reg:SI T_REG))]
12210 "TARGET_SH1"
12211 "#"
12212 "&& 1"
12213 [(set (match_dup 0) (ashift:SI (reg:SI T_REG) (const_int 31)))])
12214
12215 ;; Store inverted T bit as MSB in a reg.
12216 ;; T = 0: 0x80000000 -> reg
12217 ;; T = 1: 0x00000000 -> reg
12218 ;; On SH2A we can get away without clobbering the T_REG using the movrt insn.
12219 ;; On non SH2A we resort to the following sequence:
12220 ;; movt Rn
12221 ;; tst Rn,Rn
12222 ;; rotcr Rn
12223 ;; The T bit value will be modified during the sequence, but the rotcr insn
12224 ;; will restore its original value.
12225 (define_insn_and_split "*negt_msb"
12226 [(set (match_operand:SI 0 "arith_reg_dest")
12227 (match_operand:SI 1 "negt_reg_shl31_operand"))]
12228 "TARGET_SH1"
12229 "#"
12230 "&& can_create_pseudo_p ()"
12231 [(const_int 0)]
12232 {
12233 rtx tmp = gen_reg_rtx (SImode);
12234
12235 if (TARGET_SH2A)
12236 {
12237 emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
12238 emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
12239 }
12240 else
12241 {
12242 emit_move_insn (tmp, get_t_reg_rtx ());
12243 emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
12244 emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
12245 }
12246 DONE;
12247 })
12248
12249 ;; The *cset_zero patterns convert optimizations such as
12250 ;; "if (test) x = 0;"
12251 ;; to
12252 ;; "x &= -(test == 0);"
12253 ;; back to conditional branch sequences if zero-displacement branches
12254 ;; are enabled.
12255 ;; FIXME: These patterns can be removed when conditional execution patterns
12256 ;; are implemented, since ifcvt will not perform these optimizations if
12257 ;; conditional execution is supported.
12258 (define_insn "*cset_zero"
12259 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12260 (and:SI (plus:SI (match_operand:SI 1 "t_reg_operand")
12261 (const_int -1))
12262 (match_operand:SI 2 "arith_reg_operand" "0")))]
12263 "TARGET_SH1 && TARGET_ZDCBRANCH"
12264 {
12265 return "bf 0f" "\n"
12266 " mov #0,%0" "\n"
12267 "0:";
12268 }
12269 [(set_attr "type" "arith") ;; poor approximation
12270 (set_attr "length" "4")])
12271
12272 (define_insn "*cset_zero"
12273 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12274 (if_then_else:SI (match_operand:SI 1 "cbranch_treg_value")
12275 (match_operand:SI 2 "arith_reg_operand" "0")
12276 (const_int 0)))]
12277 "TARGET_SH1 && TARGET_ZDCBRANCH"
12278 {
12279 int tval = sh_eval_treg_value (operands[1]);
12280 if (tval == true)
12281 return "bt 0f" "\n"
12282 " mov #0,%0" "\n"
12283 "0:";
12284 else if (tval == false)
12285 return "bf 0f" "\n"
12286 " mov #0,%0" "\n"
12287 "0:";
12288 else
12289 gcc_unreachable ();
12290 }
12291 [(set_attr "type" "arith") ;; poor approximation
12292 (set_attr "length" "4")])
12293
12294 (define_expand "cstoresf4"
12295 [(set (match_operand:SI 0 "register_operand" "=r")
12296 (match_operator:SI 1 "sh_float_comparison_operator"
12297 [(match_operand:SF 2 "arith_operand" "")
12298 (match_operand:SF 3 "arith_operand" "")]))]
12299 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12300 {
12301 if (TARGET_SHMEDIA)
12302 {
12303 emit_insn (gen_cstore4_media (operands[0], operands[1],
12304 operands[2], operands[3]));
12305 DONE;
12306 }
12307
12308 if (! currently_expanding_to_rtl)
12309 FAIL;
12310
12311 sh_emit_compare_and_set (operands, SFmode);
12312 DONE;
12313 })
12314
12315 (define_expand "cstoredf4"
12316 [(set (match_operand:SI 0 "register_operand" "=r")
12317 (match_operator:SI 1 "sh_float_comparison_operator"
12318 [(match_operand:DF 2 "arith_operand" "")
12319 (match_operand:DF 3 "arith_operand" "")]))]
12320 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
12321 {
12322 if (TARGET_SHMEDIA)
12323 {
12324 emit_insn (gen_cstore4_media (operands[0], operands[1],
12325 operands[2], operands[3]));
12326 DONE;
12327 }
12328
12329 if (! currently_expanding_to_rtl)
12330 FAIL;
12331
12332 sh_emit_compare_and_set (operands, DFmode);
12333 DONE;
12334 })
12335
12336 ;; Sometimes the T bit result of insns is needed in normal registers.
12337 ;; Instead of open coding all the pattern variations, use the treg_set_expr
12338 ;; predicate to match any T bit output insn and split it out after.
12339 ;; This pattern should be below all other related patterns so that it is
12340 ;; considered as a last resort option during matching. This allows
12341 ;; overriding it with special case patterns.
12342 (define_insn_and_split "any_treg_expr_to_reg"
12343 [(set (match_operand:SI 0 "arith_reg_dest")
12344 (match_operand 1 "treg_set_expr"))
12345 (clobber (reg:SI T_REG))]
12346 "TARGET_SH1 && can_create_pseudo_p ()"
12347 "#"
12348 "&& !sh_in_recog_treg_set_expr ()"
12349 [(const_int 0)]
12350 {
12351 if (dump_file)
12352 fprintf (dump_file, "splitting any_treg_expr_to_reg\n");
12353
12354 if (t_reg_operand (operands[1], VOIDmode))
12355 {
12356 if (dump_file)
12357 fprintf (dump_file, "t_reg_operand: emitting movt\n");
12358 emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
12359 DONE;
12360 }
12361 if (negt_reg_operand (operands[1], VOIDmode))
12362 {
12363 if (dump_file)
12364 fprintf (dump_file, "negt_reg_operand: emitting movrt\n");
12365 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
12366 DONE;
12367 }
12368
12369 /* If the split out insns ended with a nott, emit a movrt sequence,
12370 otherwise a normal movt. */
12371 sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
12372 rtx_insn* i = NULL;
12373 if (ti.remove_trailing_nott ())
12374 {
12375 /* Emit this same insn_and_split again. However, the next time it
12376 is split, it will emit the actual negc/movrt insn. This gives
12377 other surrounding insns the chance to see the trailing movrt. */
12378 if (dump_file)
12379 fprintf (dump_file,
12380 "any_treg_expr_to_reg: replacing trailing nott with movrt\n");
12381 i = emit_insn (gen_any_treg_expr_to_reg (
12382 operands[0], gen_rtx_XOR (SImode, get_t_reg_rtx (),
12383 const1_rtx)));
12384 }
12385 else
12386 {
12387 i = emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
12388 if (dump_file)
12389 fprintf (dump_file, "any_treg_expr_to_reg: appending movt\n");
12390 }
12391
12392 add_reg_note (i, REG_UNUSED, get_t_reg_rtx ());
12393 DONE;
12394 })
12395
12396 ;; -------------------------------------------------------------------------
12397 ;; Instructions to cope with inline literal tables
12398 ;; -------------------------------------------------------------------------
12399
12400 ;; 2 byte integer in line
12401 (define_insn "consttable_2"
12402 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
12403 (match_operand 1 "" "")]
12404 UNSPECV_CONST2)]
12405 ""
12406 {
12407 if (operands[1] != const0_rtx)
12408 assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1);
12409 return "";
12410 }
12411 [(set_attr "length" "2")
12412 (set_attr "in_delay_slot" "no")])
12413
12414 ;; 4 byte integer in line
12415 (define_insn "consttable_4"
12416 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
12417 (match_operand 1 "" "")]
12418 UNSPECV_CONST4)]
12419 ""
12420 {
12421 if (operands[1] != const0_rtx)
12422 {
12423 assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
12424 mark_symbol_refs_as_used (operands[0]);
12425 }
12426 return "";
12427 }
12428 [(set_attr "length" "4")
12429 (set_attr "in_delay_slot" "no")])
12430
12431 ;; 8 byte integer in line
12432 (define_insn "consttable_8"
12433 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
12434 (match_operand 1 "" "")]
12435 UNSPECV_CONST8)]
12436 ""
12437 {
12438 if (operands[1] != const0_rtx)
12439 assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1);
12440 return "";
12441 }
12442 [(set_attr "length" "8")
12443 (set_attr "in_delay_slot" "no")])
12444
12445 ;; 4 byte floating point
12446 (define_insn "consttable_sf"
12447 [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
12448 (match_operand 1 "" "")]
12449 UNSPECV_CONST4)]
12450 ""
12451 {
12452 if (operands[1] != const0_rtx)
12453 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
12454 SFmode, GET_MODE_ALIGNMENT (SFmode));
12455 return "";
12456 }
12457 [(set_attr "length" "4")
12458 (set_attr "in_delay_slot" "no")])
12459
12460 ;; 8 byte floating point
12461 (define_insn "consttable_df"
12462 [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
12463 (match_operand 1 "" "")]
12464 UNSPECV_CONST8)]
12465 ""
12466 {
12467 if (operands[1] != const0_rtx)
12468 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
12469 DFmode, GET_MODE_ALIGNMENT (DFmode));
12470 return "";
12471 }
12472 [(set_attr "length" "8")
12473 (set_attr "in_delay_slot" "no")])
12474
12475 ;; Alignment is needed for some constant tables; it may also be added for
12476 ;; Instructions at the start of loops, or after unconditional branches.
12477 ;; ??? We would get more accurate lengths if we did instruction
12478 ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
12479 ;; here is too conservative.
12480
12481 ;; align to a two byte boundary
12482 (define_expand "align_2"
12483 [(unspec_volatile [(const_int 1)] UNSPECV_ALIGN)]
12484 ""
12485 "")
12486
12487 ;; Align to a four byte boundary.
12488 ;; align_4 and align_log are instructions for the starts of loops, or
12489 ;; after unconditional branches, which may take up extra room.
12490 (define_expand "align_4"
12491 [(unspec_volatile [(const_int 2)] UNSPECV_ALIGN)]
12492 ""
12493 "")
12494
12495 ;; Align to a cache line boundary.
12496 (define_insn "align_log"
12497 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPECV_ALIGN)]
12498 ""
12499 ""
12500 [(set_attr "length" "0")
12501 (set_attr "in_delay_slot" "no")])
12502
12503 ;; Emitted at the end of the literal table, used to emit the
12504 ;; 32bit branch labels if needed.
12505 (define_insn "consttable_end"
12506 [(unspec_volatile [(const_int 0)] UNSPECV_CONST_END)]
12507 ""
12508 {
12509 return output_jump_label_table ();
12510 }
12511 [(set_attr "in_delay_slot" "no")])
12512
12513 ;; Emitted at the end of the window in the literal table.
12514 (define_insn "consttable_window_end"
12515 [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
12516 ""
12517 ""
12518 [(set_attr "length" "0")
12519 (set_attr "in_delay_slot" "no")])
12520
12521 ;; -------------------------------------------------------------------------
12522 ;; Minimum / maximum operations.
12523 ;; -------------------------------------------------------------------------
12524
12525 ;; The SH2A clips.b and clips.w insns do a signed min-max function. If smin
12526 ;; and smax standard name patterns are defined, they will be used during
12527 ;; initial expansion and combine will then be able to form the actual min-max
12528 ;; pattern.
12529 ;; The clips.b and clips.w set the SR.CS bit if the value in the register is
12530 ;; clipped, but there is currently no way of making use of this information.
12531 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
12532 (define_expand "<code>si3"
12533 [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
12534 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
12535 (match_operand 2 "const_int_operand")))
12536 (clobber (reg:SI T_REG))])]
12537 "TARGET_SH2A"
12538 {
12539 /* Force the comparison value into a register, because greater-than
12540 comparisons can work only on registers. Combine will be able to pick up
12541 the constant value from the REG_EQUAL note when trying to form a min-max
12542 pattern. */
12543 operands[2] = force_reg (SImode, operands[2]);
12544 })
12545
12546 ;; Convert
12547 ;; smax (smin (...))
12548 ;; to
12549 ;; smin (smax (...))
12550 (define_insn_and_split "*clips"
12551 [(set (match_operand:SI 0 "arith_reg_dest")
12552 (smax:SI (smin:SI (match_operand:SI 1 "arith_reg_operand")
12553 (match_operand 2 "clips_max_const_int"))
12554 (match_operand 3 "clips_min_const_int")))]
12555 "TARGET_SH2A"
12556 "#"
12557 "&& 1"
12558 [(set (match_dup 0)
12559 (smin:SI (smax:SI (match_dup 1) (match_dup 3)) (match_dup 2)))])
12560
12561 (define_insn "*clips"
12562 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12563 (smin:SI (smax:SI (match_operand:SI 1 "arith_reg_operand" "0")
12564 (match_operand 2 "clips_min_const_int"))
12565 (match_operand 3 "clips_max_const_int")))]
12566 "TARGET_SH2A"
12567 {
12568 if (INTVAL (operands[3]) == 127)
12569 return "clips.b %0";
12570 else if (INTVAL (operands[3]) == 32767)
12571 return "clips.w %0";
12572 else
12573 gcc_unreachable ();
12574 }
12575 [(set_attr "type" "arith")])
12576
12577 ;; If the expanded smin or smax patterns were not combined, split them into
12578 ;; a compare and branch sequence, because there are no real smin or smax
12579 ;; insns.
12580 (define_insn_and_split "*<code>si3"
12581 [(set (match_operand:SI 0 "arith_reg_dest")
12582 (SMIN_SMAX:SI (match_operand:SI 1 "arith_reg_operand")
12583 (match_operand:SI 2 "arith_reg_or_0_or_1_operand")))
12584 (clobber (reg:SI T_REG))]
12585 "TARGET_SH2A && can_create_pseudo_p ()"
12586 "#"
12587 "&& 1"
12588 [(const_int 0)]
12589 {
12590 rtx skip_label = gen_label_rtx ();
12591 emit_move_insn (operands[0], operands[1]);
12592
12593 rtx cmp_val = operands[2];
12594 if (satisfies_constraint_M (cmp_val))
12595 cmp_val = const0_rtx;
12596
12597 emit_insn (gen_cmpgtsi_t (operands[0], cmp_val));
12598 emit_jump_insn (<CODE> == SMIN
12599 ? gen_branch_false (skip_label)
12600 : gen_branch_true (skip_label));
12601
12602 emit_label_after (skip_label, emit_move_insn (operands[0], operands[2]));
12603 DONE;
12604 })
12605
12606 ;; The SH2A clipu.b and clipu.w insns can be used to implement a min function
12607 ;; with a register and a constant.
12608 ;; The clipu.b and clipu.w set the SR.CS bit if the value in the register is
12609 ;; clipped, but there is currently no way of making use of this information.
12610 ;; The only way to read or reset the SR.CS bit is by accessing the SR.
12611 (define_expand "uminsi3"
12612 [(set (match_operand:SI 0 "arith_reg_dest")
12613 (umin:SI (match_operand:SI 1 "arith_reg_operand")
12614 (match_operand 2 "const_int_operand")))]
12615 "TARGET_SH2A"
12616 {
12617 if (INTVAL (operands[2]) == 1)
12618 {
12619 emit_insn (gen_clipu_one (operands[0], operands[1]));
12620 DONE;
12621 }
12622 else if (! clipu_max_const_int (operands[2], VOIDmode))
12623 FAIL;
12624 })
12625
12626 (define_insn "*clipu"
12627 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
12628 (umin:SI (match_operand:SI 1 "arith_reg_operand" "0")
12629 (match_operand 2 "clipu_max_const_int")))]
12630 "TARGET_SH2A"
12631 {
12632 if (INTVAL (operands[2]) == 255)
12633 return "clipu.b %0";
12634 else if (INTVAL (operands[2]) == 65535)
12635 return "clipu.w %0";
12636 else
12637 gcc_unreachable ();
12638 }
12639 [(set_attr "type" "arith")])
12640
12641 (define_insn_and_split "clipu_one"
12642 [(set (match_operand:SI 0 "arith_reg_dest")
12643 (umin:SI (match_operand:SI 1 "arith_reg_operand") (const_int 1)))
12644 (clobber (reg:SI T_REG))]
12645 "TARGET_SH2A"
12646 "#"
12647 "&& can_create_pseudo_p ()"
12648 [(const_int 0)]
12649 {
12650 emit_insn (gen_cmpeqsi_t (operands[1], const0_rtx));
12651 emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
12652 DONE;
12653 })
12654
12655 ;; -------------------------------------------------------------------------
12656 ;; Misc
12657 ;; -------------------------------------------------------------------------
12658
12659 ;; String/block move insn.
12660
12661 (define_expand "movmemsi"
12662 [(parallel [(set (mem:BLK (match_operand:BLK 0))
12663 (mem:BLK (match_operand:BLK 1)))
12664 (use (match_operand:SI 2 "nonmemory_operand"))
12665 (use (match_operand:SI 3 "immediate_operand"))
12666 (clobber (reg:SI PR_REG))
12667 (clobber (reg:SI R4_REG))
12668 (clobber (reg:SI R5_REG))
12669 (clobber (reg:SI R0_REG))])]
12670 "TARGET_SH1 && ! TARGET_SH5"
12671 {
12672 if (expand_block_move (operands))
12673 DONE;
12674 else
12675 FAIL;
12676 })
12677
12678 (define_insn "block_move_real"
12679 [(parallel [(set (mem:BLK (reg:SI R4_REG))
12680 (mem:BLK (reg:SI R5_REG)))
12681 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12682 (clobber (reg:SI PR_REG))
12683 (clobber (reg:SI R0_REG))])]
12684 "TARGET_SH1 && ! TARGET_HARD_SH4"
12685 "jsr @%0%#"
12686 [(set_attr "type" "sfunc")
12687 (set_attr "needs_delay_slot" "yes")])
12688
12689 (define_insn "block_lump_real"
12690 [(parallel [(set (mem:BLK (reg:SI R4_REG))
12691 (mem:BLK (reg:SI R5_REG)))
12692 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12693 (use (reg:SI R6_REG))
12694 (clobber (reg:SI PR_REG))
12695 (clobber (reg:SI T_REG))
12696 (clobber (reg:SI R4_REG))
12697 (clobber (reg:SI R5_REG))
12698 (clobber (reg:SI R6_REG))
12699 (clobber (reg:SI R0_REG))])]
12700 "TARGET_SH1 && ! TARGET_HARD_SH4"
12701 "jsr @%0%#"
12702 [(set_attr "type" "sfunc")
12703 (set_attr "needs_delay_slot" "yes")])
12704
12705 (define_insn "block_move_real_i4"
12706 [(parallel [(set (mem:BLK (reg:SI R4_REG))
12707 (mem:BLK (reg:SI R5_REG)))
12708 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12709 (clobber (reg:SI PR_REG))
12710 (clobber (reg:SI R0_REG))
12711 (clobber (reg:SI R1_REG))
12712 (clobber (reg:SI R2_REG))])]
12713 "TARGET_HARD_SH4"
12714 "jsr @%0%#"
12715 [(set_attr "type" "sfunc")
12716 (set_attr "needs_delay_slot" "yes")])
12717
12718 (define_insn "block_lump_real_i4"
12719 [(parallel [(set (mem:BLK (reg:SI R4_REG))
12720 (mem:BLK (reg:SI R5_REG)))
12721 (use (match_operand:SI 0 "arith_reg_operand" "r"))
12722 (use (reg:SI R6_REG))
12723 (clobber (reg:SI PR_REG))
12724 (clobber (reg:SI T_REG))
12725 (clobber (reg:SI R4_REG))
12726 (clobber (reg:SI R5_REG))
12727 (clobber (reg:SI R6_REG))
12728 (clobber (reg:SI R0_REG))
12729 (clobber (reg:SI R1_REG))
12730 (clobber (reg:SI R2_REG))
12731 (clobber (reg:SI R3_REG))])]
12732 "TARGET_HARD_SH4"
12733 "jsr @%0%#"
12734 [(set_attr "type" "sfunc")
12735 (set_attr "needs_delay_slot" "yes")])
12736
12737 ;; byte compare pattern
12738 ;; temp = a ^ b;
12739 ;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F))
12740 (define_insn "cmpstr_t"
12741 [(set (reg:SI T_REG)
12742 (eq:SI (and:SI
12743 (and:SI
12744 (and:SI
12745 (zero_extract:SI
12746 (xor:SI (match_operand:SI 0 "arith_reg_operand" "r")
12747 (match_operand:SI 1 "arith_reg_operand" "r"))
12748 (const_int 8) (const_int 0))
12749 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12750 (const_int 8) (const_int 8)))
12751 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12752 (const_int 8) (const_int 16)))
12753 (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
12754 (const_int 8) (const_int 24)))
12755 (const_int 0)))]
12756 "TARGET_SH1"
12757 "cmp/str %0,%1"
12758 [(set_attr "type" "mt_group")])
12759
12760 (define_expand "cmpstrsi"
12761 [(set (match_operand:SI 0 "register_operand")
12762 (compare:SI (match_operand:BLK 1 "memory_operand")
12763 (match_operand:BLK 2 "memory_operand")))
12764 (use (match_operand 3 "immediate_operand"))]
12765 "TARGET_SH1 && optimize"
12766 {
12767 if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands))
12768 DONE;
12769 else
12770 FAIL;
12771 })
12772
12773 (define_expand "cmpstrnsi"
12774 [(set (match_operand:SI 0 "register_operand")
12775 (compare:SI (match_operand:BLK 1 "memory_operand")
12776 (match_operand:BLK 2 "memory_operand")))
12777 (use (match_operand:SI 3 "nonmemory_operand"))
12778 (use (match_operand:SI 4 "immediate_operand"))]
12779 "TARGET_SH1 && optimize"
12780 {
12781 if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands))
12782 DONE;
12783 else
12784 FAIL;
12785 })
12786
12787 (define_expand "strlensi"
12788 [(set (match_operand:SI 0 "register_operand")
12789 (unspec:SI [(match_operand:BLK 1 "memory_operand")
12790 (match_operand:SI 2 "immediate_operand")
12791 (match_operand:SI 3 "immediate_operand")]
12792 UNSPEC_BUILTIN_STRLEN))]
12793 "TARGET_SH1 && optimize"
12794 {
12795 if (! optimize_insn_for_size_p () && sh_expand_strlen (operands))
12796 DONE;
12797 else
12798 FAIL;
12799 })
12800
12801 (define_expand "setmemqi"
12802 [(parallel [(set (match_operand:BLK 0 "memory_operand")
12803 (match_operand 2 "const_int_operand"))
12804 (use (match_operand:QI 1 "const_int_operand"))
12805 (use (match_operand:QI 3 "const_int_operand"))])]
12806 "TARGET_SH1 && optimize"
12807 {
12808 if (optimize_insn_for_size_p ())
12809 FAIL;
12810
12811 sh_expand_setmem (operands);
12812 DONE;
12813 })
12814
12815 \f
12816 ;; -------------------------------------------------------------------------
12817 ;; Floating point instructions.
12818 ;; -------------------------------------------------------------------------
12819
12820 ;; FIXME: For now we disallow any memory operands for fpscr loads/stores,
12821 ;; except for post-inc loads and pre-dec stores for push/pop purposes.
12822 ;; This avoids problems with reload. As a consequence, user initiated fpscr
12823 ;; stores to memory will always be ferried through a general register.
12824 ;; User initiated fpscr loads always have to undergo bit masking to preserve
12825 ;; the current fpu mode settings for the compiler generated code. Thus such
12826 ;; fpscr loads will always have to go through general registers anyways.
12827 (define_insn "lds_fpscr"
12828 [(set (reg:SI FPSCR_REG)
12829 (match_operand:SI 0 "fpscr_movsrc_operand" "r,>"))
12830 (set (reg:SI FPSCR_STAT_REG)
12831 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_STAT))
12832 (set (reg:SI FPSCR_MODES_REG)
12833 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
12834 "TARGET_FPU_ANY"
12835 "@
12836 lds %0,fpscr
12837 lds.l %0,fpscr"
12838 [(set_attr "type" "gp_fpscr,mem_fpscr")])
12839
12840 ;; A move fpscr -> reg schedules like a move mac -> reg. Thus we use mac_gp
12841 ;; type for it.
12842 (define_insn "sts_fpscr"
12843 [(set (match_operand:SI 0 "fpscr_movdst_operand" "=r,<")
12844 (reg:SI FPSCR_REG))
12845 (use (reg:SI FPSCR_STAT_REG))
12846 (use (reg:SI FPSCR_MODES_REG))]
12847 "TARGET_FPU_ANY"
12848 "@
12849 sts fpscr,%0
12850 sts.l fpscr,%0"
12851 [(set_attr "type" "mac_gp,fstore")])
12852
12853 (define_expand "set_fpscr"
12854 [(parallel [(set (reg:SI FPSCR_REG)
12855 (match_operand:SI 0 "general_operand"))
12856 (set (reg:SI FPSCR_STAT_REG)
12857 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))])]
12858 "TARGET_FPU_ANY"
12859 {
12860 /* We have to mask out the FR, SZ and PR bits. To do that, we need to
12861 get the current FPSCR value first.
12862 (a & ~mask) | (b & mask) = a ^ ((a ^ b) & mask) */
12863
12864 rtx mask = force_reg (SImode, GEN_INT (FPSCR_FR | FPSCR_SZ | FPSCR_PR));
12865
12866 rtx a = force_reg (SImode, operands[0]);
12867
12868 rtx b = gen_reg_rtx (SImode);
12869 emit_insn (gen_sts_fpscr (b));
12870
12871 rtx a_xor_b = gen_reg_rtx (SImode);
12872 emit_insn (gen_xorsi3 (a_xor_b, a, b));
12873
12874 rtx a_xor_b_and_mask = gen_reg_rtx (SImode);
12875 emit_insn (gen_andsi3 (a_xor_b_and_mask, a_xor_b, mask));
12876
12877 rtx r = gen_reg_rtx (SImode);
12878 emit_insn (gen_xorsi3 (r, a_xor_b_and_mask, a));
12879 emit_insn (gen_lds_fpscr (r));
12880
12881 DONE;
12882 })
12883
12884 ;; ??? This uses the fp unit, but has no type indicating that.
12885 ;; If we did that, this would either give a bogus latency or introduce
12886 ;; a bogus FIFO constraint.
12887 ;; Since this insn is currently only used for prologues/epilogues,
12888 ;; it is probably best to claim no function unit, which matches the
12889 ;; current setting.
12890 (define_insn "toggle_sz"
12891 [(set (reg:SI FPSCR_REG)
12892 (xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_SZ)))
12893 (set (reg:SI FPSCR_MODES_REG)
12894 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
12895 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
12896 "fschg"
12897 [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
12898
12899 ;; Toggle FPU precision PR mode.
12900
12901 (define_insn "toggle_pr"
12902 [(set (reg:SI FPSCR_REG)
12903 (xor:SI (reg:SI FPSCR_REG) (const_int FPSCR_PR)))
12904 (set (reg:SI FPSCR_MODES_REG)
12905 (unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
12906 "TARGET_SH4A_FP"
12907 "fpchg"
12908 [(set_attr "type" "fpscr_toggle")])
12909
12910 (define_expand "addsf3"
12911 [(set (match_operand:SF 0 "fp_arith_reg_operand")
12912 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand")
12913 (match_operand:SF 2 "fp_arith_reg_operand")))]
12914 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
12915 {
12916 if (TARGET_SH2E)
12917 {
12918 emit_insn (gen_addsf3_i (operands[0], operands[1], operands[2]));
12919 DONE;
12920 }
12921 })
12922
12923 (define_insn "*addsf3_media"
12924 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
12925 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
12926 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
12927 "TARGET_SHMEDIA_FPU"
12928 "fadd.s %1, %2, %0"
12929 [(set_attr "type" "fparith_media")])
12930
12931 (define_insn_and_split "unary_sf_op"
12932 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12933 (vec_select:V2SF
12934 (vec_concat:V2SF
12935 (vec_select:SF
12936 (match_dup 0)
12937 (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
12938 (match_operator:SF 2 "unary_float_operator"
12939 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12940 (parallel [(match_operand 4
12941 "const_int_operand" "n")]))]))
12942 (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
12943 "TARGET_SHMEDIA_FPU"
12944 "#"
12945 "TARGET_SHMEDIA_FPU && reload_completed"
12946 [(set (match_dup 5) (match_dup 6))]
12947 {
12948 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12949 rtx op1 = gen_rtx_REG (SFmode,
12950 (true_regnum (operands[1])
12951 + (INTVAL (operands[4]) ^ endian)));
12952
12953 operands[7] = gen_rtx_REG (SFmode,
12954 (true_regnum (operands[0])
12955 + (INTVAL (operands[3]) ^ endian)));
12956 operands[6] = gen_rtx_fmt_e (GET_CODE (operands[2]), SFmode, op1);
12957 }
12958 [(set_attr "type" "fparith_media")])
12959
12960 (define_insn_and_split "binary_sf_op0"
12961 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12962 (vec_concat:V2SF
12963 (match_operator:SF 3 "binary_float_operator"
12964 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12965 (parallel [(const_int 0)]))
12966 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12967 (parallel [(const_int 0)]))])
12968 (vec_select:SF
12969 (match_dup 0)
12970 (parallel [(const_int 1)]))))]
12971 "TARGET_SHMEDIA_FPU"
12972 "#"
12973 "&& reload_completed"
12974 [(set (match_dup 4) (match_dup 5))]
12975 {
12976 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
12977 rtx op1 = gen_rtx_REG (SFmode,
12978 true_regnum (operands[1]) + endian);
12979 rtx op2 = gen_rtx_REG (SFmode,
12980 true_regnum (operands[2]) + endian);
12981
12982 operands[4] = gen_rtx_REG (SFmode,
12983 true_regnum (operands[0]) + endian);
12984 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
12985 }
12986 [(set_attr "type" "fparith_media")])
12987
12988 (define_insn_and_split "binary_sf_op1"
12989 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
12990 (vec_concat:V2SF
12991 (vec_select:SF
12992 (match_dup 0)
12993 (parallel [(const_int 0)]))
12994 (match_operator:SF 3 "binary_float_operator"
12995 [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
12996 (parallel [(const_int 1)]))
12997 (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
12998 (parallel [(const_int 1)]))])))]
12999 "TARGET_SHMEDIA_FPU"
13000 "#"
13001 "&& reload_completed"
13002 [(set (match_dup 4) (match_dup 5))]
13003 {
13004 int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
13005 rtx op1 = gen_rtx_REG (SFmode, true_regnum (operands[1]) + (1 ^ endian));
13006 rtx op2 = gen_rtx_REG (SFmode, true_regnum (operands[2]) + (1 ^ endian));
13007
13008 operands[4] = gen_rtx_REG (SFmode, true_regnum (operands[0]) + (1 ^ endian));
13009 operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
13010 }
13011 [(set_attr "type" "fparith_media")])
13012
13013 (define_insn "addsf3_i"
13014 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13015 (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
13016 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13017 (clobber (reg:SI FPSCR_STAT_REG))
13018 (use (reg:SI FPSCR_MODES_REG))]
13019 "TARGET_SH2E"
13020 "fadd %2,%0"
13021 [(set_attr "type" "fp")
13022 (set_attr "fp_mode" "single")])
13023
13024 (define_expand "subsf3"
13025 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13026 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
13027 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
13028 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13029 {
13030 if (TARGET_SH2E)
13031 {
13032 emit_insn (gen_subsf3_i (operands[0], operands[1], operands[2]));
13033 DONE;
13034 }
13035 })
13036
13037 (define_insn "*subsf3_media"
13038 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13039 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
13040 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13041 "TARGET_SHMEDIA_FPU"
13042 "fsub.s %1, %2, %0"
13043 [(set_attr "type" "fparith_media")])
13044
13045 (define_insn "subsf3_i"
13046 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13047 (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
13048 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13049 (clobber (reg:SI FPSCR_STAT_REG))
13050 (use (reg:SI FPSCR_MODES_REG))]
13051 "TARGET_SH2E"
13052 "fsub %2,%0"
13053 [(set_attr "type" "fp")
13054 (set_attr "fp_mode" "single")])
13055
13056 (define_expand "mulsf3"
13057 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13058 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
13059 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
13060 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13061 {
13062 if (TARGET_SH2E)
13063 {
13064 emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2]));
13065 DONE;
13066 }
13067 })
13068
13069 (define_insn "*mulsf3_media"
13070 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13071 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
13072 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13073 "TARGET_SHMEDIA_FPU"
13074 "fmul.s %1, %2, %0"
13075 [(set_attr "type" "fparith_media")])
13076
13077 (define_insn "mulsf3_i"
13078 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13079 (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
13080 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13081 (clobber (reg:SI FPSCR_STAT_REG))
13082 (use (reg:SI FPSCR_MODES_REG))]
13083 "TARGET_SH2E"
13084 "fmul %2,%0"
13085 [(set_attr "type" "fp")
13086 (set_attr "fp_mode" "single")])
13087
13088 ;; FMA (fused multiply-add) patterns
13089 (define_expand "fmasf4"
13090 [(set (match_operand:SF 0 "fp_arith_reg_operand")
13091 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand")
13092 (match_operand:SF 2 "fp_arith_reg_operand")
13093 (match_operand:SF 3 "fp_arith_reg_operand")))]
13094 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13095 {
13096 if (TARGET_SH2E)
13097 {
13098 emit_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
13099 operands[3]));
13100 DONE;
13101 }
13102 })
13103
13104 (define_insn "fmasf4_i"
13105 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13106 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
13107 (match_operand:SF 2 "fp_arith_reg_operand" "f")
13108 (match_operand:SF 3 "fp_arith_reg_operand" "0")))
13109 (clobber (reg:SI FPSCR_STAT_REG))
13110 (use (reg:SI FPSCR_MODES_REG))]
13111 "TARGET_SH2E"
13112 "fmac %1,%2,%0"
13113 [(set_attr "type" "fp")
13114 (set_attr "fp_mode" "single")])
13115
13116 (define_insn "fmasf4_media"
13117 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13118 (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
13119 (match_operand:SF 2 "fp_arith_reg_operand" "f")
13120 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
13121 "TARGET_SHMEDIA_FPU"
13122 "fmac.s %1, %2, %0"
13123 [(set_attr "type" "fparith_media")])
13124
13125 ;; For some cases such as 'a * b + a' the FMA pattern is not generated by
13126 ;; previous transformations. If FMA is generally allowed, let the combine
13127 ;; pass utilize it.
13128 (define_insn_and_split "*fmasf4"
13129 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13130 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
13131 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
13132 (match_operand:SF 3 "arith_reg_operand" "0")))
13133 (clobber (reg:SI FPSCR_STAT_REG))
13134 (use (reg:SI FPSCR_MODES_REG))]
13135 "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
13136 "fmac %1,%2,%0"
13137 "&& can_create_pseudo_p ()"
13138 [(parallel [(set (match_dup 0)
13139 (fma:SF (match_dup 1) (match_dup 2) (match_dup 3)))
13140 (clobber (reg:SI FPSCR_STAT_REG))
13141 (use (reg:SI FPSCR_MODES_REG))])]
13142 {
13143 /* Change 'b * a + a' into 'a * b + a'.
13144 This is better for register allocation. */
13145 if (REGNO (operands[2]) == REGNO (operands[3]))
13146 std::swap (operands[1], operands[2]);
13147 }
13148 [(set_attr "type" "fp")
13149 (set_attr "fp_mode" "single")])
13150
13151 (define_insn "*fmasf4_media"
13152 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13153 (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
13154 (match_operand:SF 2 "fp_arith_reg_operand" "f"))
13155 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
13156 "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF"
13157 "fmac.s %1, %2, %0"
13158 [(set_attr "type" "fparith_media")])
13159
13160 (define_expand "divsf3"
13161 [(set (match_operand:SF 0 "fp_arith_reg_operand")
13162 (div:SF (match_operand:SF 1 "fp_arith_reg_operand")
13163 (match_operand:SF 2 "fp_arith_reg_operand")))]
13164 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13165 {
13166 if (TARGET_SH2E)
13167 {
13168 emit_insn (gen_divsf3_i (operands[0], operands[1], operands[2]));
13169 DONE;
13170 }
13171 })
13172
13173 (define_insn "*divsf3_media"
13174 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13175 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
13176 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13177 "TARGET_SHMEDIA_FPU"
13178 "fdiv.s %1, %2, %0"
13179 [(set_attr "type" "fdiv_media")])
13180
13181 (define_insn "divsf3_i"
13182 [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f")
13183 (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
13184 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
13185 (clobber (reg:SI FPSCR_STAT_REG))
13186 (use (reg:SI FPSCR_MODES_REG))]
13187 "TARGET_SH2E"
13188 "fdiv %2,%0"
13189 [(set_attr "type" "fdiv")
13190 (set_attr "fp_mode" "single")])
13191
13192 (define_insn "floatdisf2"
13193 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13194 (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
13195 "TARGET_SHMEDIA_FPU"
13196 "float.qs %1, %0"
13197 [(set_attr "type" "fpconv_media")])
13198
13199 (define_expand "floatsisf2"
13200 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13201 (float:SF (match_operand:SI 1 "fpul_operand" "")))]
13202 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13203 {
13204 if (!TARGET_SHMEDIA_FPU)
13205 {
13206 emit_insn (gen_floatsisf2_i4 (operands[0], operands[1]));
13207 DONE;
13208 }
13209 })
13210
13211 (define_insn "*floatsisf2_media"
13212 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13213 (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
13214 "TARGET_SHMEDIA_FPU"
13215 "float.ls %1, %0"
13216 [(set_attr "type" "fpconv_media")])
13217
13218 (define_insn "floatsisf2_i4"
13219 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13220 (float:SF (match_operand:SI 1 "fpul_operand" "y")))
13221 (clobber (reg:SI FPSCR_STAT_REG))
13222 (use (reg:SI FPSCR_MODES_REG))]
13223 "TARGET_SH2E"
13224 "float %1,%0"
13225 [(set_attr "type" "fp")
13226 (set_attr "fp_mode" "single")])
13227
13228 (define_insn "fix_truncsfdi2"
13229 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
13230 (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13231 "TARGET_SHMEDIA_FPU"
13232 "ftrc.sq %1, %0"
13233 [(set_attr "type" "fpconv_media")])
13234
13235 (define_expand "fix_truncsfsi2"
13236 [(set (match_operand:SI 0 "fpul_operand" "=y")
13237 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13238 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13239 {
13240 if (!TARGET_SHMEDIA_FPU)
13241 {
13242 emit_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1]));
13243 DONE;
13244 }
13245 })
13246
13247 (define_insn "*fix_truncsfsi2_media"
13248 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
13249 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13250 "TARGET_SHMEDIA_FPU"
13251 "ftrc.sl %1, %0"
13252 [(set_attr "type" "fpconv_media")])
13253
13254 (define_insn "fix_truncsfsi2_i4"
13255 [(set (match_operand:SI 0 "fpul_operand" "=y")
13256 (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
13257 (clobber (reg:SI FPSCR_STAT_REG))
13258 (use (reg:SI FPSCR_MODES_REG))]
13259 "TARGET_SH2E"
13260 "ftrc %1,%0"
13261 [(set_attr "type" "ftrc_s")
13262 (set_attr "fp_mode" "single")])
13263
13264 (define_insn "cmpgtsf_t"
13265 [(set (reg:SI T_REG)
13266 (gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
13267 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
13268 (clobber (reg:SI FPSCR_STAT_REG))
13269 (use (reg:SI FPSCR_MODES_REG))]
13270 "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
13271 "fcmp/gt %1,%0"
13272 [(set_attr "type" "fp_cmp")
13273 (set_attr "fp_mode" "single")])
13274
13275 (define_insn "cmpeqsf_t"
13276 [(set (reg:SI T_REG)
13277 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
13278 (match_operand:SF 1 "fp_arith_reg_operand" "f")))
13279 (clobber (reg:SI FPSCR_STAT_REG))
13280 (use (reg:SI FPSCR_MODES_REG))]
13281 "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
13282 "fcmp/eq %1,%0"
13283 [(set_attr "type" "fp_cmp")
13284 (set_attr "fp_mode" "single")])
13285
13286 (define_insn "ieee_ccmpeqsf_t"
13287 [(set (reg:SI T_REG)
13288 (ior:SI (reg:SI T_REG)
13289 (eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
13290 (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
13291 (clobber (reg:SI FPSCR_STAT_REG))
13292 (use (reg:SI FPSCR_MODES_REG))]
13293 "TARGET_IEEE && TARGET_SH2E"
13294 {
13295 return output_ieee_ccmpeq (insn, operands);
13296 }
13297 [(set_attr "length" "4")
13298 (set_attr "fp_mode" "single")])
13299
13300 (define_insn "cmpeqsf_media"
13301 [(set (match_operand:SI 0 "register_operand" "=r")
13302 (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13303 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13304 "TARGET_SHMEDIA_FPU"
13305 "fcmpeq.s %1, %2, %0"
13306 [(set_attr "type" "fcmp_media")])
13307
13308 (define_insn "cmpgtsf_media"
13309 [(set (match_operand:SI 0 "register_operand" "=r")
13310 (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13311 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13312 "TARGET_SHMEDIA_FPU"
13313 "fcmpgt.s %1, %2, %0"
13314 [(set_attr "type" "fcmp_media")])
13315
13316 (define_insn "cmpgesf_media"
13317 [(set (match_operand:SI 0 "register_operand" "=r")
13318 (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13319 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13320 "TARGET_SHMEDIA_FPU"
13321 "fcmpge.s %1, %2, %0"
13322 [(set_attr "type" "fcmp_media")])
13323
13324 (define_insn "cmpunsf_media"
13325 [(set (match_operand:SI 0 "register_operand" "=r")
13326 (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
13327 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
13328 "TARGET_SHMEDIA_FPU"
13329 "fcmpun.s %1, %2, %0"
13330 [(set_attr "type" "fcmp_media")])
13331
13332 (define_expand "cbranchsf4"
13333 [(set (pc)
13334 (if_then_else (match_operator 0 "sh_float_comparison_operator"
13335 [(match_operand:SF 1 "arith_operand" "")
13336 (match_operand:SF 2 "arith_operand" "")])
13337 (match_operand 3 "" "")
13338 (pc)))]
13339 "TARGET_SH2E || TARGET_SHMEDIA_FPU"
13340 {
13341 if (TARGET_SHMEDIA)
13342 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
13343 operands[3]));
13344 else
13345 sh_emit_compare_and_branch (operands, SFmode);
13346 DONE;
13347 })
13348
13349 (define_expand "negsf2"
13350 [(set (match_operand:SF 0 "fp_arith_reg_operand")
13351 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand")))]
13352 "TARGET_SH2E || TARGET_SHMEDIA_FPU")
13353
13354 (define_insn "*negsf2_media"
13355 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13356 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13357 "TARGET_SHMEDIA_FPU"
13358 "fneg.s %1, %0"
13359 [(set_attr "type" "fmove_media")])
13360
13361 (define_insn "*negsf2_i"
13362 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13363 (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))]
13364 "TARGET_SH2E"
13365 "fneg %0"
13366 [(set_attr "type" "fmove")])
13367
13368 (define_expand "sqrtsf2"
13369 [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
13370 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
13371 "TARGET_SH3E || TARGET_SHMEDIA_FPU"
13372 {
13373 if (TARGET_SH3E)
13374 {
13375 emit_insn (gen_sqrtsf2_i (operands[0], operands[1]));
13376 DONE;
13377 }
13378 })
13379
13380 (define_insn "*sqrtsf2_media"
13381 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13382 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13383 "TARGET_SHMEDIA_FPU"
13384 "fsqrt.s %1, %0"
13385 [(set_attr "type" "fdiv_media")])
13386
13387 (define_insn "sqrtsf2_i"
13388 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13389 (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
13390 (clobber (reg:SI FPSCR_STAT_REG))
13391 (use (reg:SI FPSCR_MODES_REG))]
13392 "TARGET_SH3E"
13393 "fsqrt %0"
13394 [(set_attr "type" "fdiv")
13395 (set_attr "fp_mode" "single")])
13396
13397 (define_insn "rsqrtsf2"
13398 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13399 (div:SF (match_operand:SF 1 "immediate_operand" "i")
13400 (sqrt:SF (match_operand:SF 2 "fp_arith_reg_operand" "0"))))
13401 (clobber (reg:SI FPSCR_STAT_REG))
13402 (use (reg:SI FPSCR_MODES_REG))]
13403 "TARGET_FPU_ANY && TARGET_FSRRA
13404 && operands[1] == CONST1_RTX (SFmode)"
13405 "fsrra %0"
13406 [(set_attr "type" "fsrra")
13407 (set_attr "fp_mode" "single")])
13408
13409 ;; When the sincos pattern is defined, the builtin functions sin and cos
13410 ;; will be expanded to the sincos pattern and one of the output values will
13411 ;; remain unused.
13412 (define_expand "sincossf3"
13413 [(set (match_operand:SF 0 "nonimmediate_operand")
13414 (unspec:SF [(match_operand:SF 2 "fp_arith_reg_operand")] UNSPEC_FCOSA))
13415 (set (match_operand:SF 1 "nonimmediate_operand")
13416 (unspec:SF [(match_dup 2)] UNSPEC_FSINA))]
13417 "TARGET_FPU_ANY && TARGET_FSCA"
13418 {
13419 rtx scaled = gen_reg_rtx (SFmode);
13420 rtx truncated = gen_reg_rtx (SImode);
13421 rtx fsca = gen_reg_rtx (V2SFmode);
13422 rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
13423
13424 emit_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
13425 emit_insn (gen_fix_truncsfsi2 (truncated, scaled));
13426 emit_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf ()));
13427
13428 emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
13429 emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
13430 DONE;
13431 })
13432
13433 (define_insn_and_split "fsca"
13434 [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
13435 (vec_concat:V2SF
13436 (unspec:SF [(mult:SF
13437 (float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
13438 (match_operand:SF 2 "fsca_scale_factor" "i"))
13439 ] UNSPEC_FSINA)
13440 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
13441 ] UNSPEC_FCOSA)))
13442 (clobber (reg:SI FPSCR_STAT_REG))
13443 (use (reg:SI FPSCR_MODES_REG))]
13444 "TARGET_FPU_ANY && TARGET_FSCA"
13445 "fsca fpul,%d0"
13446 "&& !fpul_operand (operands[1], SImode)"
13447 [(const_int 0)]
13448 {
13449 /* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
13450 to a simple reg, otherwise reload will have trouble reloading the
13451 pseudo into fpul. */
13452 rtx x = XEXP (operands[1], 0);
13453 while (x != NULL_RTX && !fpul_operand (x, SImode))
13454 {
13455 gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
13456 x = XEXP (x, 0);
13457 }
13458 gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
13459 emit_insn (gen_fsca (operands[0], x, operands[2]));
13460 DONE;
13461 }
13462 [(set_attr "type" "fsca")
13463 (set_attr "fp_mode" "single")])
13464
13465 (define_expand "abssf2"
13466 [(set (match_operand:SF 0 "fp_arith_reg_operand")
13467 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand")))]
13468 "TARGET_SH2E || TARGET_SHMEDIA_FPU")
13469
13470 (define_insn "*abssf2_media"
13471 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13472 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13473 "TARGET_SHMEDIA_FPU"
13474 "fabs.s %1, %0"
13475 [(set_attr "type" "fmove_media")])
13476
13477 (define_insn "*abssf2_i"
13478 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13479 (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))]
13480 "TARGET_SH2E"
13481 "fabs %0"
13482 [(set_attr "type" "fmove")])
13483
13484 (define_expand "adddf3"
13485 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13486 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13487 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13488 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13489 {
13490 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13491 {
13492 emit_insn (gen_adddf3_i (operands[0], operands[1], operands[2]));
13493 DONE;
13494 }
13495 })
13496
13497 (define_insn "*adddf3_media"
13498 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13499 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
13500 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13501 "TARGET_SHMEDIA_FPU"
13502 "fadd.d %1, %2, %0"
13503 [(set_attr "type" "dfparith_media")])
13504
13505 (define_insn "adddf3_i"
13506 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13507 (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
13508 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13509 (clobber (reg:SI FPSCR_STAT_REG))
13510 (use (reg:SI FPSCR_MODES_REG))]
13511 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13512 "fadd %2,%0"
13513 [(set_attr "type" "dfp_arith")
13514 (set_attr "fp_mode" "double")])
13515
13516 (define_expand "subdf3"
13517 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13518 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13519 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13520 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13521 {
13522 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13523 {
13524 emit_insn (gen_subdf3_i (operands[0], operands[1], operands[2]));
13525 DONE;
13526 }
13527 })
13528
13529 (define_insn "*subdf3_media"
13530 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13531 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
13532 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13533 "TARGET_SHMEDIA_FPU"
13534 "fsub.d %1, %2, %0"
13535 [(set_attr "type" "dfparith_media")])
13536
13537 (define_insn "subdf3_i"
13538 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13539 (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
13540 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13541 (clobber (reg:SI FPSCR_STAT_REG))
13542 (use (reg:SI FPSCR_MODES_REG))]
13543 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13544 "fsub %2,%0"
13545 [(set_attr "type" "dfp_arith")
13546 (set_attr "fp_mode" "double")])
13547
13548 (define_expand "muldf3"
13549 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13550 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13551 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13552 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13553 {
13554 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13555 {
13556 emit_insn (gen_muldf3_i (operands[0], operands[1], operands[2]));
13557 DONE;
13558 }
13559 })
13560
13561 (define_insn "*muldf3_media"
13562 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13563 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
13564 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13565 "TARGET_SHMEDIA_FPU"
13566 "fmul.d %1, %2, %0"
13567 [(set_attr "type" "dfmul_media")])
13568
13569 (define_insn "muldf3_i"
13570 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13571 (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
13572 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13573 (clobber (reg:SI FPSCR_STAT_REG))
13574 (use (reg:SI FPSCR_MODES_REG))]
13575 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13576 "fmul %2,%0"
13577 [(set_attr "type" "dfp_mul")
13578 (set_attr "fp_mode" "double")])
13579
13580 (define_expand "divdf3"
13581 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13582 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
13583 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
13584 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13585 {
13586 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13587 {
13588 emit_insn (gen_divdf3_i (operands[0], operands[1], operands[2]));
13589 DONE;
13590 }
13591 })
13592
13593 (define_insn "*divdf3_media"
13594 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13595 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
13596 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13597 "TARGET_SHMEDIA_FPU"
13598 "fdiv.d %1, %2, %0"
13599 [(set_attr "type" "dfdiv_media")])
13600
13601 (define_insn "divdf3_i"
13602 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13603 (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
13604 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
13605 (clobber (reg:SI FPSCR_STAT_REG))
13606 (use (reg:SI FPSCR_MODES_REG))]
13607 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13608 "fdiv %2,%0"
13609 [(set_attr "type" "dfdiv")
13610 (set_attr "fp_mode" "double")])
13611
13612 (define_insn "floatdidf2"
13613 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13614 (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
13615 "TARGET_SHMEDIA_FPU"
13616 "float.qd %1, %0"
13617 [(set_attr "type" "dfpconv_media")])
13618
13619 (define_expand "floatsidf2"
13620 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13621 (float:DF (match_operand:SI 1 "fpul_operand" "")))]
13622 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13623 {
13624 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13625 {
13626 emit_insn (gen_floatsidf2_i (operands[0], operands[1]));
13627 DONE;
13628 }
13629 })
13630
13631 (define_insn "*floatsidf2_media"
13632 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13633 (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
13634 "TARGET_SHMEDIA_FPU"
13635 "float.ld %1, %0"
13636 [(set_attr "type" "dfpconv_media")])
13637
13638 (define_insn "floatsidf2_i"
13639 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13640 (float:DF (match_operand:SI 1 "fpul_operand" "y")))
13641 (clobber (reg:SI FPSCR_STAT_REG))
13642 (use (reg:SI FPSCR_MODES_REG))]
13643 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13644 "float %1,%0"
13645 [(set_attr "type" "dfp_conv")
13646 (set_attr "fp_mode" "double")])
13647
13648 (define_insn "fix_truncdfdi2"
13649 [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
13650 (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13651 "TARGET_SHMEDIA_FPU"
13652 "ftrc.dq %1, %0"
13653 [(set_attr "type" "dfpconv_media")])
13654
13655 (define_expand "fix_truncdfsi2"
13656 [(set (match_operand:SI 0 "fpul_operand" "")
13657 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13658 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13659 {
13660 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13661 {
13662 emit_insn (gen_fix_truncdfsi2_i (operands[0], operands[1]));
13663 DONE;
13664 }
13665 })
13666
13667 (define_insn "*fix_truncdfsi2_media"
13668 [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
13669 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13670 "TARGET_SHMEDIA_FPU"
13671 "ftrc.dl %1, %0"
13672 [(set_attr "type" "dfpconv_media")])
13673
13674 (define_insn "fix_truncdfsi2_i"
13675 [(set (match_operand:SI 0 "fpul_operand" "=y")
13676 (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13677 (clobber (reg:SI FPSCR_STAT_REG))
13678 (use (reg:SI FPSCR_MODES_REG))]
13679 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13680 "ftrc %1,%0"
13681 [(set_attr "type" "dfp_conv")
13682 (set_attr "dfp_comp" "no")
13683 (set_attr "fp_mode" "double")])
13684
13685 (define_insn "cmpgtdf_t"
13686 [(set (reg:SI T_REG)
13687 (gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13688 (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13689 (clobber (reg:SI FPSCR_STAT_REG))
13690 (use (reg:SI FPSCR_MODES_REG))]
13691 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13692 "fcmp/gt %1,%0"
13693 [(set_attr "type" "dfp_cmp")
13694 (set_attr "fp_mode" "double")])
13695
13696 (define_insn "cmpeqdf_t"
13697 [(set (reg:SI T_REG)
13698 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13699 (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13700 (clobber (reg:SI FPSCR_STAT_REG))
13701 (use (reg:SI FPSCR_MODES_REG))]
13702 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13703 "fcmp/eq %1,%0"
13704 [(set_attr "type" "dfp_cmp")
13705 (set_attr "fp_mode" "double")])
13706
13707 (define_insn "*ieee_ccmpeqdf_t"
13708 [(set (reg:SI T_REG)
13709 (ior:SI (reg:SI T_REG)
13710 (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
13711 (match_operand:DF 1 "fp_arith_reg_operand" "f"))))
13712 (clobber (reg:SI FPSCR_STAT_REG))
13713 (use (reg:SI FPSCR_MODES_REG))]
13714 "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13715 {
13716 return output_ieee_ccmpeq (insn, operands);
13717 }
13718 [(set_attr "length" "4")
13719 (set_attr "fp_mode" "double")])
13720
13721 (define_insn "cmpeqdf_media"
13722 [(set (match_operand:SI 0 "register_operand" "=r")
13723 (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13724 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13725 "TARGET_SHMEDIA_FPU"
13726 "fcmpeq.d %1,%2,%0"
13727 [(set_attr "type" "fcmp_media")])
13728
13729 (define_insn "cmpgtdf_media"
13730 [(set (match_operand:SI 0 "register_operand" "=r")
13731 (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13732 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13733 "TARGET_SHMEDIA_FPU"
13734 "fcmpgt.d %1,%2,%0"
13735 [(set_attr "type" "fcmp_media")])
13736
13737 (define_insn "cmpgedf_media"
13738 [(set (match_operand:SI 0 "register_operand" "=r")
13739 (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13740 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13741 "TARGET_SHMEDIA_FPU"
13742 "fcmpge.d %1,%2,%0"
13743 [(set_attr "type" "fcmp_media")])
13744
13745 (define_insn "cmpundf_media"
13746 [(set (match_operand:SI 0 "register_operand" "=r")
13747 (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
13748 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
13749 "TARGET_SHMEDIA_FPU"
13750 "fcmpun.d %1,%2,%0"
13751 [(set_attr "type" "fcmp_media")])
13752
13753 (define_expand "cbranchdf4"
13754 [(set (pc)
13755 (if_then_else (match_operator 0 "sh_float_comparison_operator"
13756 [(match_operand:DF 1 "arith_operand" "")
13757 (match_operand:DF 2 "arith_operand" "")])
13758 (match_operand 3 "" "")
13759 (pc)))]
13760 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13761 {
13762 if (TARGET_SHMEDIA)
13763 emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
13764 operands[3]));
13765 else
13766 sh_emit_compare_and_branch (operands, DFmode);
13767 DONE;
13768 })
13769
13770 (define_expand "negdf2"
13771 [(set (match_operand:DF 0 "fp_arith_reg_operand")
13772 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13773 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU")
13774
13775 (define_insn "*negdf2_media"
13776 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13777 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13778 "TARGET_SHMEDIA_FPU"
13779 "fneg.d %1, %0"
13780 [(set_attr "type" "fmove_media")])
13781
13782 (define_insn "*negdf2_i"
13783 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13784 (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))]
13785 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13786 "fneg %0"
13787 [(set_attr "type" "fmove")])
13788
13789 (define_expand "sqrtdf2"
13790 [(set (match_operand:DF 0 "fp_arith_reg_operand")
13791 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13792 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13793 {
13794 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13795 {
13796 emit_insn (gen_sqrtdf2_i (operands[0], operands[1]));
13797 DONE;
13798 }
13799 })
13800
13801 (define_insn "*sqrtdf2_media"
13802 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13803 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13804 "TARGET_SHMEDIA_FPU"
13805 "fsqrt.d %1, %0"
13806 [(set_attr "type" "dfdiv_media")])
13807
13808 (define_insn "sqrtdf2_i"
13809 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13810 (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
13811 (clobber (reg:SI FPSCR_STAT_REG))
13812 (use (reg:SI FPSCR_MODES_REG))]
13813 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13814 "fsqrt %0"
13815 [(set_attr "type" "dfdiv")
13816 (set_attr "fp_mode" "double")])
13817
13818 (define_expand "absdf2"
13819 [(set (match_operand:DF 0 "fp_arith_reg_operand")
13820 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
13821 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU")
13822
13823 (define_insn "*absdf2_media"
13824 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13825 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13826 "TARGET_SHMEDIA_FPU"
13827 "fabs.d %1, %0"
13828 [(set_attr "type" "fmove_media")])
13829
13830 (define_insn "*absdf2_i"
13831 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13832 (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))]
13833 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13834 "fabs %0"
13835 [(set_attr "type" "fmove")])
13836
13837 (define_expand "extendsfdf2"
13838 [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
13839 (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
13840 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13841 {
13842 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13843 {
13844 emit_insn (gen_extendsfdf2_i4 (operands[0], operands[1]));
13845 DONE;
13846 }
13847 })
13848
13849 (define_insn "*extendsfdf2_media"
13850 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13851 (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
13852 "TARGET_SHMEDIA_FPU"
13853 "fcnv.sd %1, %0"
13854 [(set_attr "type" "dfpconv_media")])
13855
13856 (define_insn "extendsfdf2_i4"
13857 [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
13858 (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
13859 (clobber (reg:SI FPSCR_STAT_REG))
13860 (use (reg:SI FPSCR_MODES_REG))]
13861 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13862 "fcnvsd %1,%0"
13863 [(set_attr "type" "fp")
13864 (set_attr "fp_mode" "double")])
13865
13866 (define_expand "truncdfsf2"
13867 [(set (match_operand:SF 0 "fpul_operand" "")
13868 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
13869 "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
13870 {
13871 if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
13872 {
13873 emit_insn (gen_truncdfsf2_i4 (operands[0], operands[1]));
13874 DONE;
13875 }
13876 })
13877
13878 (define_insn "*truncdfsf2_media"
13879 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
13880 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
13881 "TARGET_SHMEDIA_FPU"
13882 "fcnv.ds %1, %0"
13883 [(set_attr "type" "dfpconv_media")])
13884
13885 (define_insn "truncdfsf2_i4"
13886 [(set (match_operand:SF 0 "fpul_operand" "=y")
13887 (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
13888 (clobber (reg:SI FPSCR_STAT_REG))
13889 (use (reg:SI FPSCR_MODES_REG))]
13890 "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
13891 "fcnvds %1,%0"
13892 [(set_attr "type" "fp")
13893 (set_attr "fp_mode" "double")])
13894 \f
13895 ;; -------------------------------------------------------------------------
13896 ;; Bit field extract patterns.
13897 ;; -------------------------------------------------------------------------
13898
13899 ;; These give better code for packed bitfields, because they allow
13900 ;; auto-increment addresses to be generated.
13901
13902 (define_expand "insv"
13903 [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
13904 (match_operand:SI 1 "immediate_operand" "")
13905 (match_operand:SI 2 "immediate_operand" ""))
13906 (match_operand:SI 3 "general_operand" ""))]
13907 "TARGET_SH1 && TARGET_BIG_ENDIAN"
13908 {
13909 rtx addr_target, orig_address, shift_reg, qi_val;
13910 HOST_WIDE_INT bitsize, size, v = 0;
13911 rtx x = operands[3];
13912
13913 if (TARGET_SH2A && TARGET_BITOPS
13914 && (satisfies_constraint_Sbw (operands[0])
13915 || satisfies_constraint_Sbv (operands[0]))
13916 && satisfies_constraint_M (operands[1])
13917 && satisfies_constraint_K03 (operands[2]))
13918 {
13919 if (satisfies_constraint_N (operands[3]))
13920 {
13921 emit_insn (gen_bclr_m2a (operands[0], operands[2]));
13922 DONE;
13923 }
13924 else if (satisfies_constraint_M (operands[3]))
13925 {
13926 emit_insn (gen_bset_m2a (operands[0], operands[2]));
13927 DONE;
13928 }
13929 else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
13930 && satisfies_constraint_M (operands[1]))
13931 {
13932 emit_insn (gen_bst_m2a (operands[0], operands[2]));
13933 DONE;
13934 }
13935 else if (REG_P (operands[3])
13936 && satisfies_constraint_M (operands[1]))
13937 {
13938 emit_insn (gen_bldsi_reg (operands[3], const0_rtx));
13939 emit_insn (gen_bst_m2a (operands[0], operands[2]));
13940 DONE;
13941 }
13942 }
13943 /* ??? expmed doesn't care for non-register predicates. */
13944 if (! memory_operand (operands[0], VOIDmode)
13945 || ! immediate_operand (operands[1], VOIDmode)
13946 || ! immediate_operand (operands[2], VOIDmode)
13947 || ! general_operand (x, VOIDmode))
13948 FAIL;
13949 /* If this isn't a 16 / 24 / 32 bit field, or if
13950 it doesn't start on a byte boundary, then fail. */
13951 bitsize = INTVAL (operands[1]);
13952 if (bitsize < 16 || bitsize > 32 || bitsize % 8 != 0
13953 || (INTVAL (operands[2]) % 8) != 0)
13954 FAIL;
13955
13956 size = bitsize / 8;
13957 orig_address = XEXP (operands[0], 0);
13958 shift_reg = gen_reg_rtx (SImode);
13959 if (CONST_INT_P (x))
13960 {
13961 v = INTVAL (x);
13962 qi_val = force_reg (QImode, GEN_INT (trunc_int_for_mode (v, QImode)));
13963 }
13964 else
13965 {
13966 emit_insn (gen_movsi (shift_reg, operands[3]));
13967 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13968 }
13969 addr_target = copy_addr_to_reg (plus_constant (Pmode,
13970 orig_address, size - 1));
13971
13972 operands[0] = replace_equiv_address (operands[0], addr_target);
13973 emit_insn (gen_movqi (operands[0], qi_val));
13974
13975 while (size -= 1)
13976 {
13977 if (CONST_INT_P (x))
13978 qi_val
13979 = force_reg (QImode, GEN_INT (trunc_int_for_mode (v >>= 8, QImode)));
13980 else
13981 {
13982 emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
13983 qi_val = gen_rtx_SUBREG (QImode, shift_reg, 3);
13984 }
13985 emit_insn (gen_addsi3 (addr_target, addr_target, constm1_rtx));
13986 emit_insn (gen_movqi (operands[0], qi_val));
13987 }
13988
13989 DONE;
13990 })
13991
13992 (define_insn "movua"
13993 [(set (match_operand:SI 0 "register_operand" "=z")
13994 (unspec:SI [(match_operand:BLK 1 "unaligned_load_operand" "Sua>")]
13995 UNSPEC_MOVUA))]
13996 "TARGET_SH4A"
13997 "movua.l %1,%0"
13998 [(set_attr "type" "movua")])
13999
14000 ;; We shouldn't need this, but cse replaces increments with references
14001 ;; to other regs before flow has a chance to create post_inc
14002 ;; addressing modes, and only postreload's cse_move2add brings the
14003 ;; increments back to a usable form.
14004 (define_peephole2
14005 [(set (match_operand:SI 0 "register_operand" "")
14006 (sign_extract:SI (mem:SI (match_operand:SI 1 "register_operand" ""))
14007 (const_int 32) (const_int 0)))
14008 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
14009 "TARGET_SH4A && REGNO (operands[0]) != REGNO (operands[1])"
14010 [(set (match_operand:SI 0 "register_operand" "")
14011 (sign_extract:SI (mem:SI (post_inc:SI
14012 (match_operand:SI 1 "register_operand" "")))
14013 (const_int 32) (const_int 0)))]
14014 "")
14015
14016 (define_expand "extv"
14017 [(set (match_operand:SI 0 "register_operand" "")
14018 (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
14019 (match_operand 2 "const_int_operand" "")
14020 (match_operand 3 "const_int_operand" "")))]
14021 "TARGET_SH4A || TARGET_SH2A"
14022 {
14023 if (TARGET_SH2A && TARGET_BITOPS
14024 && (satisfies_constraint_Sbw (operands[1])
14025 || satisfies_constraint_Sbv (operands[1]))
14026 && satisfies_constraint_M (operands[2])
14027 && satisfies_constraint_K03 (operands[3]))
14028 {
14029 emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
14030 if (REGNO (operands[0]) != T_REG)
14031 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
14032 DONE;
14033 }
14034 if (TARGET_SH4A
14035 && INTVAL (operands[2]) == 32
14036 && INTVAL (operands[3]) == 0
14037 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
14038 {
14039 rtx src = adjust_address (operands[1], BLKmode, 0);
14040 set_mem_size (src, 4);
14041 emit_insn (gen_movua (operands[0], src));
14042 DONE;
14043 }
14044
14045 FAIL;
14046 })
14047
14048 (define_expand "extzv"
14049 [(set (match_operand:SI 0 "register_operand" "")
14050 (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
14051 (match_operand 2 "const_int_operand" "")
14052 (match_operand 3 "const_int_operand" "")))]
14053 "TARGET_SH4A || TARGET_SH2A"
14054 {
14055 if (TARGET_SH2A && TARGET_BITOPS
14056 && (satisfies_constraint_Sbw (operands[1])
14057 || satisfies_constraint_Sbv (operands[1]))
14058 && satisfies_constraint_M (operands[2])
14059 && satisfies_constraint_K03 (operands[3]))
14060 {
14061 emit_insn (gen_bld_m2a (operands[1], operands[3]));
14062 if (REGNO (operands[0]) != T_REG)
14063 emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
14064 DONE;
14065 }
14066 if (TARGET_SH4A
14067 && INTVAL (operands[2]) == 32
14068 && INTVAL (operands[3]) == 0
14069 && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
14070 {
14071 rtx src = adjust_address (operands[1], BLKmode, 0);
14072 set_mem_size (src, 4);
14073 emit_insn (gen_movua (operands[0], src));
14074 DONE;
14075 }
14076
14077 FAIL;
14078 })
14079
14080 ;; -------------------------------------------------------------------------
14081 ;; Extract negated single bit and zero extend it.
14082 ;; Generally we don't care about the exact xor const_int value, as long
14083 ;; as it contains the extracted bit. For simplicity, the pattern variations
14084 ;; that convert everything into the primary '*neg_zero_extract_0' pattern use
14085 ;; a xor const_int -1 value.
14086
14087 (define_insn_and_split "*neg_zero_extract_0"
14088 [(set (reg:SI T_REG)
14089 (zero_extract:SI (xor:QIHISI (match_operand:QIHISI 0 "arith_reg_operand")
14090 (match_operand 1 "const_int_operand"))
14091 (const_int 1)
14092 (match_operand 2 "const_int_operand")))]
14093 "TARGET_SH1 && can_create_pseudo_p ()
14094 && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))"
14095 "#"
14096 "&& 1"
14097 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 2))
14098 (const_int 0)))]
14099 {
14100 if (INTVAL (operands[2]) == 31 && <MODE>mode == SImode)
14101 {
14102 /* Use cmp/pz to extract bit 31 into the T bit. */
14103 emit_insn (gen_cmpgesi_t (operands[0], const0_rtx));
14104 DONE;
14105 }
14106
14107 operands[2] = GEN_INT ((1 << INTVAL (operands[2])));
14108 if (GET_MODE (operands[0]) != SImode)
14109 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
14110 })
14111
14112 (define_insn_and_split "*neg_zero_extract_1"
14113 [(set (reg:SI T_REG)
14114 (and:SI (not:SI (match_operand:SI 0 "arith_reg_operand"))
14115 (const_int 1)))]
14116 "TARGET_SH1"
14117 "#"
14118 "&& 1"
14119 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14120 (const_int 1) (const_int 0)))])
14121
14122 ;; x & (1 << n) == 0: 0x00000000 + 1 = 1
14123 ;; x & (1 << n) != 0: 0xFFFFFFFF + 1 = 0
14124 (define_insn_and_split "*neg_zero_extract_2"
14125 [(set (reg:SI T_REG)
14126 (plus:SI (sign_extract:SI (match_operand:QIHISI 0 "arith_reg_operand")
14127 (const_int 1)
14128 (match_operand 1 "const_int_operand"))
14129 (const_int 1)))]
14130 "TARGET_SH1 && can_create_pseudo_p ()"
14131 "#"
14132 "&& 1"
14133 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14134 (const_int 1) (match_dup 1)))])
14135
14136 ;; (signed)x >> 31 + 1 = (x >= 0) ^ 1
14137 (define_insn_and_split "*neg_zero_extract_3"
14138 [(set (reg:SI T_REG)
14139 (plus:SI (ashiftrt:SI (match_operand:SI 0 "arith_reg_operand")
14140 (const_int 31))
14141 (const_int 1)))]
14142 "TARGET_SH1 && can_create_pseudo_p ()"
14143 "#"
14144 "&& 1"
14145 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14146 (const_int 1) (const_int 31)))])
14147
14148 ;; This is required for some bit patterns of DImode subregs.
14149 ;; It looks like combine gets confused by the DImode right shift and fails
14150 ;; to simplify things.
14151 (define_insn_and_split "*neg_zero_extract_4"
14152 [(set (reg:SI T_REG)
14153 (and:SI (and:SI
14154 (lshiftrt:SI (xor:SI (match_operand:SI 0 "arith_reg_operand")
14155 (match_operand 1 "const_int_operand"))
14156 (match_operand 2 "const_int_operand"))
14157 (not:SI (ashift:SI (match_operand:SI 3 "arith_reg_operand")
14158 (match_operand 4 "const_int_operand"))))
14159 (const_int 1)))]
14160 "TARGET_SH1 && can_create_pseudo_p ()
14161 && INTVAL (operands[4]) > 0
14162 && INTVAL (operands[1]) & (1LL << INTVAL (operands[2]))"
14163 "#"
14164 "&& 1"
14165 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
14166 (const_int 1) (match_dup 2)))])
14167
14168 (define_insn_and_split "*neg_zero_extract_5"
14169 [(set (reg:SI T_REG)
14170 (and:SI (not:SI (subreg:SI
14171 (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand")
14172 (match_operand 1 "const_int_operand"))
14173 0))
14174 (const_int 1)))]
14175 "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()
14176 && INTVAL (operands[1]) < 32"
14177 "#"
14178 "&& 1"
14179 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14180 (const_int 1) (match_dup 1)))]
14181 {
14182 operands[0] = gen_lowpart (SImode, operands[0]);
14183 })
14184
14185 (define_insn_and_split "*neg_zero_extract_6"
14186 [(set (reg:SI T_REG)
14187 (and:SI (not:SI (subreg:SI
14188 (lshiftrt:DI (match_operand:DI 0 "arith_reg_operand")
14189 (match_operand 1 "const_int_operand"))
14190 4))
14191 (const_int 1)))]
14192 "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()
14193 && INTVAL (operands[1]) < 32"
14194 "#"
14195 "&& 1"
14196 [(set (reg:SI T_REG) (zero_extract:SI (xor:SI (match_dup 0) (const_int -1))
14197 (const_int 1) (match_dup 1)))]
14198 {
14199 operands[0] = gen_lowpart (SImode, operands[0]);
14200 })
14201
14202 ;; -------------------------------------------------------------------------
14203 ;; Extract single bit and zero extend it.
14204 ;; All patterns store the result bit in the T bit, although that is not
14205 ;; always possible to do with a single insn and a nott must be appended.
14206 ;; The trailing nott will be optimized away in most cases. E.g. if the
14207 ;; extracted bit is fed into a branch condition, the condition can be
14208 ;; inverted and the nott will be eliminated.
14209 ;; FIXME: In cases where the trailing nott can't be eliminated, try to
14210 ;; convert it into a (not, tst) sequence, which could be better on non-SH2A.
14211
14212 ;; On SH2A the 'bld<mode>_reg' insn will be used if the bit position fits.
14213 (define_insn_and_split "*zero_extract_0"
14214 [(set (reg:SI T_REG)
14215 (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand")
14216 (const_int 1)
14217 (match_operand 1 "const_int_operand")))]
14218 "TARGET_SH1 && can_create_pseudo_p ()
14219 && !(TARGET_SH2A && satisfies_constraint_K03 (operands[1]))"
14220 "#"
14221 "&& 1"
14222 [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 1))
14223 (const_int 0)))
14224 (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]
14225 {
14226 if (INTVAL (operands[1]) == 31 && <MODE>mode == SImode)
14227 {
14228 emit_insn (gen_shll (gen_reg_rtx (SImode), operands[0]));
14229 DONE;
14230 }
14231
14232 operands[1] = GEN_INT (1 << INTVAL (operands[1]));
14233 if (GET_MODE (operands[0]) != SImode)
14234 operands[0] = simplify_gen_subreg (SImode, operands[0], <MODE>mode, 0);
14235 })
14236
14237 ;; This is required for some bit patterns of DImode subregs.
14238 ;; It looks like combine gets confused by the DImode right shift and fails
14239 ;; to simplify things.
14240 (define_insn_and_split "*zero_extract_1"
14241 [(set (reg:SI T_REG)
14242 (subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand")
14243 (const_int 1)
14244 (match_operand 1 "const_int_operand"))
14245 0))]
14246 "TARGET_SH1 && TARGET_LITTLE_ENDIAN && can_create_pseudo_p ()
14247 && INTVAL (operands[1]) < 32"
14248 "#"
14249 "&& 1"
14250 [(set (reg:SI T_REG)
14251 (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))])
14252
14253 (define_insn_and_split "*zero_extract_2"
14254 [(set (reg:SI T_REG)
14255 (subreg:SI (zero_extract:DI (match_operand:SI 0 "arith_reg_operand")
14256 (const_int 1)
14257 (match_operand 1 "const_int_operand"))
14258 4))]
14259 "TARGET_SH1 && TARGET_BIG_ENDIAN && can_create_pseudo_p ()
14260 && INTVAL (operands[1]) < 32"
14261 "#"
14262 "&& 1"
14263 [(set (reg:SI T_REG)
14264 (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))])
14265
14266 ;; -------------------------------------------------------------------------
14267 ;; SH2A instructions for bitwise operations.
14268 ;; FIXME: Convert multiple instruction insns to insn_and_split.
14269 ;; FIXME: Use iterators to fold at least and,xor,or insn variations.
14270
14271 ;; Clear a bit in a memory location.
14272 (define_insn "bclr_m2a"
14273 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14274 (and:QI
14275 (not:QI (ashift:QI (const_int 1)
14276 (match_operand:QI 1 "const_int_operand" "K03,K03")))
14277 (match_dup 0)))]
14278 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14279 "@
14280 bclr.b %1,%0
14281 bclr.b %1,@(0,%t0)"
14282 [(set_attr "length" "4,4")])
14283
14284 (define_insn "bclrmem_m2a"
14285 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14286 (and:QI (match_dup 0)
14287 (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
14288 "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
14289 "@
14290 bclr.b %W1,%0
14291 bclr.b %W1,@(0,%t0)"
14292 [(set_attr "length" "4,4")])
14293
14294 ;; Set a bit in a memory location.
14295 (define_insn "bset_m2a"
14296 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14297 (ior:QI
14298 (ashift:QI (const_int 1)
14299 (match_operand:QI 1 "const_int_operand" "K03,K03"))
14300 (match_dup 0)))]
14301 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14302 "@
14303 bset.b %1,%0
14304 bset.b %1,@(0,%t0)"
14305 [(set_attr "length" "4,4")])
14306
14307 (define_insn "bsetmem_m2a"
14308 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
14309 (ior:QI (match_dup 0)
14310 (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
14311 "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
14312 "@
14313 bset.b %V1,%0
14314 bset.b %V1,@(0,%t0)"
14315 [(set_attr "length" "4,4")])
14316
14317 ;;; Transfer the contents of the T bit to a specified bit of memory.
14318 (define_insn "bst_m2a"
14319 [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
14320 (if_then_else (eq (reg:SI T_REG) (const_int 0))
14321 (and:QI
14322 (not:QI (ashift:QI (const_int 1)
14323 (match_operand:QI 1 "const_int_operand" "K03,K03")))
14324 (match_dup 0))
14325 (ior:QI
14326 (ashift:QI (const_int 1) (match_dup 1))
14327 (match_dup 0))))]
14328 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14329 "@
14330 bst.b %1,%0
14331 bst.b %1,@(0,%t0)"
14332 [(set_attr "length" "4")])
14333
14334 ;; Store a specified bit of memory in the T bit.
14335 (define_insn "bld_m2a"
14336 [(set (reg:SI T_REG)
14337 (zero_extract:SI
14338 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
14339 (const_int 1)
14340 (match_operand 1 "const_int_operand" "K03,K03")))]
14341 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14342 "@
14343 bld.b %1,%0
14344 bld.b %1,@(0,%t0)"
14345 [(set_attr "length" "4,4")])
14346
14347 ;; Store a specified bit of memory in the T bit.
14348 (define_insn "bldsign_m2a"
14349 [(set (reg:SI T_REG)
14350 (sign_extract:SI
14351 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14352 (const_int 1)
14353 (match_operand 1 "const_int_operand" "K03,K03")))]
14354 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14355 "@
14356 bld.b %1,%0
14357 bld.b %1,@(0,%t0)"
14358 [(set_attr "length" "4,4")])
14359
14360 ;; Store a specified bit of the LSB 8 bits of a register in the T bit.
14361 (define_insn "bld<mode>_reg"
14362 [(set (reg:SI T_REG)
14363 (zero_extract:SI (match_operand:QIHISI 0 "arith_reg_operand" "r")
14364 (const_int 1)
14365 (match_operand 1 "const_int_operand" "K03")))]
14366 "TARGET_SH2A && satisfies_constraint_K03 (operands[1])"
14367 "bld %1,%0")
14368
14369 ;; Take logical and of a specified bit of memory with the T bit and
14370 ;; store its result in the T bit.
14371 (define_insn "band_m2a"
14372 [(set (reg:SI T_REG)
14373 (and:SI (reg:SI T_REG)
14374 (zero_extract:SI
14375 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14376 (const_int 1)
14377 (match_operand 1 "const_int_operand" "K03,K03"))))]
14378 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14379 "@
14380 band.b %1,%0
14381 band.b %1,@(0,%t0)"
14382 [(set_attr "length" "4,4")])
14383
14384 (define_insn "bandreg_m2a"
14385 [(set (match_operand:SI 0 "register_operand" "=r,r")
14386 (and:SI (zero_extract:SI
14387 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
14388 (const_int 1)
14389 (match_operand 2 "const_int_operand" "K03,K03"))
14390 (match_operand:SI 3 "register_operand" "r,r")))]
14391 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
14392 {
14393 static const char* alt[] =
14394 {
14395 "band.b %2,%1" "\n"
14396 " movt %0",
14397
14398 "band.b %2,@(0,%t1)" "\n"
14399 " movt %0"
14400 };
14401 return alt[which_alternative];
14402 }
14403 [(set_attr "length" "6,6")])
14404
14405 ;; Take logical or of a specified bit of memory with the T bit and
14406 ;; store its result in the T bit.
14407 (define_insn "bor_m2a"
14408 [(set (reg:SI T_REG)
14409 (ior:SI (reg:SI T_REG)
14410 (zero_extract:SI
14411 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14412 (const_int 1)
14413 (match_operand 1 "const_int_operand" "K03,K03"))))]
14414 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14415 "@
14416 bor.b %1,%0
14417 bor.b %1,@(0,%t0)"
14418 [(set_attr "length" "4,4")])
14419
14420 (define_insn "borreg_m2a"
14421 [(set (match_operand:SI 0 "register_operand" "=r,r")
14422 (ior:SI (zero_extract:SI
14423 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
14424 (const_int 1)
14425 (match_operand 2 "const_int_operand" "K03,K03"))
14426 (match_operand:SI 3 "register_operand" "=r,r")))]
14427 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
14428 {
14429 static const char* alt[] =
14430 {
14431 "bor.b %2,%1" "\n"
14432 " movt %0",
14433
14434 "bor.b %2,@(0,%t1)" "\n"
14435 " movt %0"
14436 };
14437 return alt[which_alternative];
14438 }
14439 [(set_attr "length" "6,6")])
14440
14441 ;; Take exclusive or of a specified bit of memory with the T bit and
14442 ;; store its result in the T bit.
14443 (define_insn "bxor_m2a"
14444 [(set (reg:SI T_REG)
14445 (xor:SI (reg:SI T_REG)
14446 (zero_extract:SI
14447 (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
14448 (const_int 1)
14449 (match_operand 1 "const_int_operand" "K03,K03"))))]
14450 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[1])"
14451 "@
14452 bxor.b %1,%0
14453 bxor.b %1,@(0,%t0)"
14454 [(set_attr "length" "4,4")])
14455
14456 (define_insn "bxorreg_m2a"
14457 [(set (match_operand:SI 0 "register_operand" "=r,r")
14458 (xor:SI (zero_extract:SI
14459 (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
14460 (const_int 1)
14461 (match_operand 2 "const_int_operand" "K03,K03"))
14462 (match_operand:SI 3 "register_operand" "=r,r")))]
14463 "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_K03 (operands[2])"
14464 {
14465 static const char* alt[] =
14466 {
14467 "bxor.b %2,%1" "\n"
14468 " movt %0",
14469
14470 "bxor.b %2,@(0,%t1)" "\n"
14471 " movt %0"
14472 };
14473 return alt[which_alternative];
14474 }
14475 [(set_attr "length" "6,6")])
14476 \f
14477 ;; -------------------------------------------------------------------------
14478 ;; Peepholes
14479 ;; -------------------------------------------------------------------------
14480 ;; This matches cases where the bit in a memory location is set.
14481 (define_peephole2
14482 [(set (match_operand:SI 0 "register_operand")
14483 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
14484 (set (match_dup 0)
14485 (ior:SI (match_dup 0)
14486 (match_operand:SI 2 "const_int_operand")))
14487 (set (match_dup 1)
14488 (match_operand 3 "arith_reg_operand"))]
14489 "TARGET_SH2A && TARGET_BITOPS
14490 && satisfies_constraint_Pso (operands[2])
14491 && REGNO (operands[0]) == REGNO (operands[3])"
14492 [(set (match_dup 1)
14493 (ior:QI (match_dup 1) (match_dup 2)))]
14494 "")
14495
14496 ;; This matches cases where the bit in a memory location is cleared.
14497 (define_peephole2
14498 [(set (match_operand:SI 0 "register_operand")
14499 (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand")))
14500 (set (match_dup 0)
14501 (and:SI (match_dup 0)
14502 (match_operand:SI 2 "const_int_operand")))
14503 (set (match_dup 1)
14504 (match_operand 3 "arith_reg_operand"))]
14505 "TARGET_SH2A && TARGET_BITOPS
14506 && satisfies_constraint_Psz (operands[2])
14507 && REGNO (operands[0]) == REGNO (operands[3])"
14508 [(set (match_dup 1)
14509 (and:QI (match_dup 1) (match_dup 2)))]
14510 "")
14511
14512 ;; This matches cases where a stack pointer increment at the start of the
14513 ;; epilogue combines with a stack slot read loading the return value.
14514 (define_peephole
14515 [(set (match_operand:SI 0 "arith_reg_operand" "")
14516 (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
14517 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
14518 "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
14519 "mov.l @%1+,%0")
14520
14521 ;; See the comment on the dt combiner pattern above.
14522 (define_peephole
14523 [(set (match_operand:SI 0 "arith_reg_operand" "=r")
14524 (plus:SI (match_dup 0)
14525 (const_int -1)))
14526 (set (reg:SI T_REG)
14527 (eq:SI (match_dup 0) (const_int 0)))]
14528 "TARGET_SH2"
14529 "dt %0")
14530
14531 ;; The following peepholes fold load sequences for which reload was not
14532 ;; able to generate a displacement addressing move insn.
14533 ;; This can happen when reload has to transform a move insn
14534 ;; without displacement into one with displacement. Or when reload can't
14535 ;; fit a displacement into the insn's constraints. In the latter case, the
14536 ;; load destination reg remains at r0, which reload compensates by inserting
14537 ;; another mov insn.
14538
14539 ;; Fold sequence:
14540 ;; mov #54,r0
14541 ;; mov.{b,w} @(r0,r15),r0
14542 ;; mov r0,r3
14543 ;; into:
14544 ;; mov.{b,w} @(54,r15),r3
14545 ;;
14546 (define_peephole2
14547 [(set (match_operand:SI 0 "arith_reg_dest" "")
14548 (match_operand:SI 1 "const_int_operand" ""))
14549 (set (match_operand:SI 2 "arith_reg_dest" "")
14550 (sign_extend:SI
14551 (mem:QI (plus:SI (match_dup 0)
14552 (match_operand:SI 3 "arith_reg_operand" "")))))
14553 (set (match_operand:QI 4 "arith_reg_dest" "")
14554 (match_operand:QI 5 "arith_reg_operand" ""))]
14555 "TARGET_SH2A
14556 && sh_legitimate_index_p (QImode, operands[1], true, true)
14557 && REGNO (operands[2]) == REGNO (operands[5])
14558 && peep2_reg_dead_p (3, operands[5])"
14559 [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
14560 "")
14561
14562 (define_peephole2
14563 [(set (match_operand:SI 0 "arith_reg_dest" "")
14564 (match_operand:SI 1 "const_int_operand" ""))
14565 (set (match_operand:SI 2 "arith_reg_dest" "")
14566 (sign_extend:SI
14567 (mem:HI (plus:SI (match_dup 0)
14568 (match_operand:SI 3 "arith_reg_operand" "")))))
14569 (set (match_operand:HI 4 "arith_reg_dest" "")
14570 (match_operand:HI 5 "arith_reg_operand" ""))]
14571 "TARGET_SH2A
14572 && sh_legitimate_index_p (HImode, operands[1], true, true)
14573 && REGNO (operands[2]) == REGNO (operands[5])
14574 && peep2_reg_dead_p (3, operands[5])"
14575 [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
14576 "")
14577
14578 ;; Fold sequence:
14579 ;; mov #54,r0
14580 ;; mov.{b,w} @(r0,r15),r1
14581 ;; into:
14582 ;; mov.{b,w} @(54,r15),r1
14583 ;;
14584 (define_peephole2
14585 [(set (match_operand:SI 0 "arith_reg_dest" "")
14586 (match_operand:SI 1 "const_int_operand" ""))
14587 (set (match_operand:SI 2 "arith_reg_dest" "")
14588 (sign_extend:SI
14589 (mem:QI (plus:SI (match_dup 0)
14590 (match_operand:SI 3 "arith_reg_operand" "")))))]
14591 "TARGET_SH2A
14592 && sh_legitimate_index_p (QImode, operands[1], true, true)
14593 && (peep2_reg_dead_p (2, operands[0])
14594 || REGNO (operands[0]) == REGNO (operands[2]))"
14595 [(set (match_dup 2)
14596 (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
14597 "")
14598
14599 (define_peephole2
14600 [(set (match_operand:SI 0 "arith_reg_dest" "")
14601 (match_operand:SI 1 "const_int_operand" ""))
14602 (set (match_operand:SI 2 "arith_reg_dest" "")
14603 (sign_extend:SI
14604 (mem:HI (plus:SI (match_dup 0)
14605 (match_operand:SI 3 "arith_reg_operand" "")))))]
14606 "TARGET_SH2A
14607 && sh_legitimate_index_p (HImode, operands[1], true, true)
14608 && (peep2_reg_dead_p (2, operands[0])
14609 || REGNO (operands[0]) == REGNO (operands[2]))"
14610 [(set (match_dup 2)
14611 (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
14612 "")
14613
14614 ;; Fold sequence:
14615 ;; mov.{b,w} @(r0,r15),r0
14616 ;; mov r0,r3
14617 ;; into:
14618 ;; mov.{b,w} @(r0,r15),r3
14619 ;;
14620 ;; This can happen when initially a displacement address is picked, where
14621 ;; the destination reg is fixed to r0, and then the address is transformed
14622 ;; into 'r0 + reg'.
14623 (define_peephole2
14624 [(set (match_operand:SI 0 "arith_reg_dest" "")
14625 (sign_extend:SI
14626 (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
14627 (match_operand:SI 2 "arith_reg_operand" "")))))
14628 (set (match_operand:QI 3 "arith_reg_dest" "")
14629 (match_operand:QI 4 "arith_reg_operand" ""))]
14630 "TARGET_SH1
14631 && REGNO (operands[0]) == REGNO (operands[4])
14632 && peep2_reg_dead_p (2, operands[0])"
14633 [(set (match_dup 3)
14634 (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
14635 "")
14636
14637 (define_peephole2
14638 [(set (match_operand:SI 0 "arith_reg_dest" "")
14639 (sign_extend:SI
14640 (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
14641 (match_operand:SI 2 "arith_reg_operand" "")))))
14642 (set (match_operand:HI 3 "arith_reg_dest" "")
14643 (match_operand:HI 4 "arith_reg_operand" ""))]
14644 "TARGET_SH1
14645 && REGNO (operands[0]) == REGNO (operands[4])
14646 && peep2_reg_dead_p (2, operands[0])"
14647 [(set (match_dup 3)
14648 (mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
14649 "")
14650
14651 ;; extu.bw a,b
14652 ;; mov b,c -> extu.bw a,c
14653 (define_peephole2
14654 [(set (match_operand:SI 0 "arith_reg_dest")
14655 (zero_extend:SI (match_operand:QIHI 1 "arith_reg_operand")))
14656 (set (match_operand:SI 2 "arith_reg_dest")
14657 (match_dup 0))]
14658 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14659 [(set (match_dup 2) (zero_extend:SI (match_dup 1)))])
14660
14661 ;; mov r0,r1
14662 ;; extu.bw r1,r1 -> extu.bw r0,r1
14663 (define_peephole2
14664 [(set (match_operand 0 "arith_reg_dest")
14665 (match_operand 1 "arith_reg_operand"))
14666 (set (match_operand:SI 2 "arith_reg_dest")
14667 (zero_extend:SI (match_operand:QIHI 3 "arith_reg_operand")))]
14668 "TARGET_SH1
14669 && REGNO (operands[0]) == REGNO (operands[3])
14670 && (REGNO (operands[0]) == REGNO (operands[2])
14671 || peep2_reg_dead_p (2, operands[0]))"
14672 [(set (match_dup 2) (zero_extend:SI (match_dup 1)))]
14673 {
14674 operands[1] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
14675 })
14676
14677 ;; mov a,b
14678 ;; mov b,a -> < nop >
14679 (define_peephole2
14680 [(set (match_operand 0 "register_operand")
14681 (match_operand 1 "register_operand"))
14682 (set (match_operand 2 "register_operand")
14683 (match_operand 3 "register_operand"))]
14684 "TARGET_SH1
14685 && REGNO (operands[0]) == REGNO (operands[3])
14686 && REGNO (operands[1]) == REGNO (operands[2])
14687 && peep2_reg_dead_p (2, operands[3])"
14688 [(const_int 0)])
14689
14690 ;; mov #3,r4
14691 ;; and r4,r1 -> mov r1,r0
14692 ;; mov r1,r0 and #3,r0
14693 (define_code_iterator ANDIORXOR [and ior xor])
14694 (define_peephole2
14695 [(set (match_operand:SI 0 "register_operand")
14696 (match_operand:SI 1 "const_logical_operand"))
14697 (set (match_operand:SI 2) (ANDIORXOR:SI (match_dup 2) (match_dup 0)))
14698 (set (reg:SI R0_REG) (match_dup 2))]
14699 "TARGET_SH1
14700 && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2])"
14701 [(set (reg:SI R0_REG) (match_dup 2))
14702 (set (reg:SI R0_REG) (ANDIORXOR:SI (reg:SI R0_REG) (match_dup 1)))])
14703
14704 ;; ... r2,r0 ... r2,r0
14705 ;; or r1,r0 -> or r0,r1
14706 ;; mov r0,r1
14707 ;; (r0 dead)
14708 (define_code_iterator ANDIORXORPLUS [and ior xor plus])
14709 (define_peephole2
14710 [(set (match_operand:SI 0 "arith_reg_dest")
14711 (ANDIORXORPLUS:SI (match_dup 0) (match_operand:SI 1 "arith_reg_dest")))
14712 (set (match_dup 1) (match_dup 0))]
14713 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14714 [(set (match_dup 1) (ANDIORXORPLUS:SI (match_dup 1) (match_dup 0)))])
14715
14716 ;; mov r12,r0
14717 ;; add #-48,r0 -> add #-48,r12
14718 ;; mov.l r0,@(4,r10) mov.l r12,@(4,r10)
14719 ;; (r12 dead)
14720 (define_peephole2
14721 [(set (match_operand:SI 0 "arith_reg_dest")
14722 (match_operand:SI 1 "arith_reg_dest"))
14723 (set (match_dup 0) (plus:SI (match_dup 0)
14724 (match_operand:SI 2 "const_int_operand")))
14725 (set (match_operand:SI 3 "general_movdst_operand") (match_dup 0))]
14726 "TARGET_SH1
14727 && peep2_reg_dead_p (2, operands[1]) && peep2_reg_dead_p (3, operands[0])"
14728 [(const_int 0)]
14729 {
14730 emit_insn (gen_addsi3 (operands[1], operands[1], operands[2]));
14731 sh_peephole_emit_move_insn (operands[3], operands[1]);
14732 })
14733
14734 ;; mov.l @(r0,r9),r1
14735 ;; mov r1,r0 -> mov @(r0,r9),r0
14736 (define_peephole2
14737 [(set (match_operand:SI 0 "arith_reg_dest")
14738 (match_operand:SI 1 "general_movsrc_operand"))
14739 (set (match_operand:SI 2 "arith_reg_dest")
14740 (match_dup 0))]
14741 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14742 [(const_int 0)]
14743 {
14744 sh_peephole_emit_move_insn (operands[2], operands[1]);
14745 })
14746
14747 (define_peephole2
14748 [(set (match_operand:QIHI 0 "register_operand")
14749 (match_operand:QIHI 1 "movsrc_no_disp_mem_operand"))
14750 (set (match_operand:QIHI 2 "register_operand")
14751 (match_dup 0))]
14752 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14753 [(const_int 0)]
14754 {
14755 sh_peephole_emit_move_insn (operands[2], operands[1]);
14756 })
14757
14758 (define_peephole2
14759 [(set (match_operand:SI 0 "arith_reg_dest")
14760 (sign_extend:SI (match_operand:QIHI 1 "movsrc_no_disp_mem_operand")))
14761 (set (match_operand:SI 2 "arith_reg_dest")
14762 (match_dup 0))]
14763 "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
14764 [(const_int 0)]
14765 {
14766 sh_check_add_incdec_notes (emit_insn (gen_extend<mode>si2 (operands[2],
14767 sh_remove_overlapping_post_inc (operands[2], operands[1]))));
14768 })
14769
14770 ;; mov.w @(18,r1),r0 (r0 = HImode)
14771 ;; mov r0,r1 (r0 = r1 = HImode) mov.w @(18,r1),r0
14772 ;; ... ..,r13 (r13 = SImode) -> ... ..,r13
14773 ;; tst r1,r13 tst r0,r13
14774 (define_peephole2
14775 [(set (match_operand 0 "arith_reg_dest")
14776 (match_operand 1 "arith_reg_dest"))
14777 (set (match_operand:SI 2 "arith_reg_dest")
14778 (match_operand:SI 3))
14779 (set (reg:SI T_REG)
14780 (eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand")
14781 (match_operand:SI 5 "arith_reg_operand"))
14782 (const_int 0)))]
14783 "TARGET_SH1
14784 && peep2_reg_dead_p (3, operands[0])
14785 && !reg_overlap_mentioned_p (operands[0], operands[3])
14786 && (REGNO (operands[0]) == REGNO (operands[4])
14787 || REGNO (operands[0]) == REGNO (operands[5]))
14788 && (REGNO (operands[2]) == REGNO (operands[4])
14789 || REGNO (operands[2]) == REGNO (operands[5]))"
14790 [(const_int 0)]
14791 {
14792 if (REGNO (operands[1]) == REGNO (operands[2]))
14793 operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));
14794
14795 // We don't know what the new set insn will be in detail. Just make sure
14796 // that it still can be recognized and the constraints are satisfied.
14797 rtx_insn* i = emit_insn (gen_rtx_SET (operands[2],
14798 sh_remove_overlapping_post_inc (operands[2], operands[3])));
14799
14800 recog_data_d prev_recog_data = recog_data;
14801 bool i_invalid = insn_invalid_p (i, false);
14802 recog_data = prev_recog_data;
14803
14804 if (i_invalid)
14805 FAIL;
14806
14807 sh_check_add_incdec_notes (i);
14808
14809 emit_insn (gen_tstsi_t (operands[2],
14810 gen_rtx_REG (SImode, (REGNO (operands[1])))));
14811 })
14812
14813 ;; mov.w @(18,r1),r0 (r0 = HImode)
14814 ;; ... ..,r13 (r13 = SImode) mov.w @(18,r1),r0
14815 ;; mov r0,r1 (r0 = r1 = HImode) -> ... ..,r13
14816 ;; tst r1,r13 tst r0,r13
14817 (define_peephole2
14818 [(set (match_operand:SI 2 "arith_reg_dest")
14819 (match_operand:SI 3))
14820 (set (match_operand 0 "arith_reg_dest")
14821 (match_operand 1 "arith_reg_operand"))
14822 (set (reg:SI T_REG)
14823 (eq:SI (and:SI (match_operand:SI 4 "arith_reg_operand")
14824 (match_operand:SI 5 "arith_reg_operand"))
14825 (const_int 0)))]
14826 "TARGET_SH1
14827 && peep2_reg_dead_p (3, operands[0])
14828 && !reg_overlap_mentioned_p (operands[0], operands[3])
14829 && (REGNO (operands[0]) == REGNO (operands[4])
14830 || REGNO (operands[0]) == REGNO (operands[5]))
14831 && (REGNO (operands[2]) == REGNO (operands[4])
14832 || REGNO (operands[2]) == REGNO (operands[5]))"
14833 [(const_int 0)]
14834 {
14835 // We don't know what the new set insn will be in detail. Just make sure
14836 // that it still can be recognized and the constraints are satisfied.
14837 rtx_insn* i = emit_insn (gen_rtx_SET (operands[2],
14838 sh_remove_overlapping_post_inc (operands[2], operands[3])));
14839
14840 recog_data_d prev_recog_data = recog_data;
14841 bool i_invalid = insn_invalid_p (i, false);
14842 recog_data = prev_recog_data;
14843
14844 if (i_invalid)
14845 FAIL;
14846
14847 sh_check_add_incdec_notes (i);
14848
14849 emit_insn (gen_tstsi_t (operands[2],
14850 gen_rtx_REG (SImode, (REGNO (operands[1])))));
14851 })
14852
14853 ;; This is not a peephole, but it's here because it's actually supposed
14854 ;; to be one. It tries to convert a sequence such as
14855 ;; movt r2 -> movt r2
14856 ;; movt r13 mov r2,r13
14857 ;; This gives the schduler a bit more freedom to hoist a following
14858 ;; comparison insn. Moreover, it the reg-reg mov insn is MT group which has
14859 ;; better chances for parallel execution.
14860 ;; We can do this with a peephole2 pattern, but then the cprop_hardreg
14861 ;; pass will revert the change. See also PR 64331.
14862 ;; Thus do it manually in one of the split passes after register allocation.
14863 ;; Sometimes the cprop_hardreg pass might also eliminate the reg-reg copy.
14864 (define_split
14865 [(set (match_operand:SI 0 "arith_reg_dest")
14866 (match_operand:SI 1 "t_reg_operand"))]
14867 "TARGET_SH1 && reload_completed"
14868 [(set (match_dup 0) (match_dup 1))]
14869 {
14870 rtx t_reg = get_t_reg_rtx ();
14871
14872 for (rtx_insn* i = prev_nonnote_insn_bb (curr_insn); i != NULL;
14873 i = prev_nonnote_insn_bb (i))
14874 {
14875 if (!INSN_P (i) || DEBUG_INSN_P (i))
14876 continue;
14877
14878 if (modified_in_p (t_reg, i) || BARRIER_P (i))
14879 FAIL;
14880
14881 if (sh_is_movt_insn (i))
14882 {
14883 rtx r = sh_movt_set_dest (i);
14884 if (!modified_between_p (r, i, curr_insn))
14885 {
14886 operands[1] = r;
14887 break;
14888 }
14889 }
14890 }
14891 })
14892
14893 (define_peephole
14894 [(set (match_operand:SI 0 "register_operand" "=r")
14895 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
14896 (set (mem:SF (match_dup 0))
14897 (match_operand:SF 2 "general_movsrc_operand" ""))]
14898 "TARGET_SH1 && REGNO (operands[0]) == 0
14899 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
14900 || (GET_CODE (operands[2]) == SUBREG
14901 && REGNO (SUBREG_REG (operands[2])) < 16))
14902 && reg_unused_after (operands[0], insn)"
14903 "mov.l %2,@(%0,%1)")
14904
14905 (define_peephole
14906 [(set (match_operand:SI 0 "register_operand" "=r")
14907 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
14908 (set (match_operand:SF 2 "general_movdst_operand" "")
14909
14910 (mem:SF (match_dup 0)))]
14911 "TARGET_SH1 && REGNO (operands[0]) == 0
14912 && ((REG_P (operands[2]) && REGNO (operands[2]) < 16)
14913 || (GET_CODE (operands[2]) == SUBREG
14914 && REGNO (SUBREG_REG (operands[2])) < 16))
14915 && reg_unused_after (operands[0], insn)"
14916 "mov.l @(%0,%1),%2")
14917
14918 (define_peephole
14919 [(set (match_operand:SI 0 "register_operand" "=r")
14920 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
14921 (set (mem:SF (match_dup 0))
14922 (match_operand:SF 2 "general_movsrc_operand" ""))]
14923 "TARGET_SH2E && REGNO (operands[0]) == 0
14924 && ((REG_P (operands[2])
14925 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
14926 || (GET_CODE (operands[2]) == SUBREG
14927 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
14928 && reg_unused_after (operands[0], insn)"
14929 "fmov{.s|} %2,@(%0,%1)")
14930
14931 (define_peephole
14932 [(set (match_operand:SI 0 "register_operand" "=r")
14933 (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
14934 (set (match_operand:SF 2 "general_movdst_operand" "")
14935
14936 (mem:SF (match_dup 0)))]
14937 "TARGET_SH2E && REGNO (operands[0]) == 0
14938 && ((REG_P (operands[2])
14939 && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
14940 || (GET_CODE (operands[2]) == SUBREG
14941 && FP_OR_XD_REGISTER_P (REGNO (SUBREG_REG (operands[2])))))
14942 && reg_unused_after (operands[0], insn)"
14943 "fmov{.s|} @(%0,%1),%2")
14944
14945 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).
14946 (define_insn "sp_switch_1"
14947 [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")]
14948 UNSPECV_SP_SWITCH_B))]
14949 "TARGET_SH1"
14950 {
14951 return "mov.l r0,@-r15" "\n"
14952 " mov.l %0,r0" "\n"
14953 " mov.l @r0,r0" "\n"
14954 " mov.l r15,@-r0" "\n"
14955 " mov r0,r15";
14956 }
14957 [(set_attr "length" "10")])
14958
14959 ;; Switch back to the original stack for interrupt functions with the
14960 ;; sp_switch attribute.
14961 (define_insn "sp_switch_2"
14962 [(unspec_volatile [(const_int 0)]
14963 UNSPECV_SP_SWITCH_E)]
14964 "TARGET_SH1"
14965 {
14966 return "mov.l @r15,r15" "\n"
14967 " mov.l @r15+,r0";
14968 }
14969 [(set_attr "length" "4")])
14970
14971 ;; -------------------------------------------------------------------------
14972 ;; Integer vector moves
14973 ;; -------------------------------------------------------------------------
14974
14975 (define_expand "movv8qi"
14976 [(set (match_operand:V8QI 0 "general_movdst_operand" "")
14977 (match_operand:V8QI 1 "general_movsrc_operand" ""))]
14978 "TARGET_SHMEDIA"
14979 {
14980 prepare_move_operands (operands, V8QImode);
14981 })
14982
14983 (define_insn "movv8qi_i"
14984 [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m")
14985 (match_operand:V8QI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
14986 "TARGET_SHMEDIA
14987 && (register_operand (operands[0], V8QImode)
14988 || sh_register_operand (operands[1], V8QImode))"
14989 "@
14990 add %1, r63, %0
14991 movi %1, %0
14992 #
14993 ld%M1.q %m1, %0
14994 st%M0.q %m0, %N1"
14995 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
14996 (set_attr "length" "4,4,16,4,4")])
14997
14998 (define_split
14999 [(set (match_operand:V8QI 0 "arith_reg_dest" "")
15000 (subreg:V8QI (const_int 0) 0))]
15001 "TARGET_SHMEDIA"
15002 [(set (match_dup 0)
15003 (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0)
15004 (const_int 0) (const_int 0) (const_int 0)
15005 (const_int 0) (const_int 0)]))])
15006
15007 (define_split
15008 [(set (match_operand 0 "arith_reg_dest" "")
15009 (match_operand 1 "sh_rep_vec" ""))]
15010 "TARGET_SHMEDIA && reload_completed
15011 && GET_MODE (operands[0]) == GET_MODE (operands[1])
15012 && sh_vector_mode_supported_p (GET_MODE (operands[0]))
15013 && GET_MODE_SIZE (GET_MODE (operands[0])) == 8
15014 && (XVECEXP (operands[1], 0, 0) != const0_rtx
15015 || XVECEXP (operands[1], 0, 1) != const0_rtx)
15016 && (XVECEXP (operands[1], 0, 0) != constm1_rtx
15017 || XVECEXP (operands[1], 0, 1) != constm1_rtx)"
15018 [(set (match_dup 0) (match_dup 1))
15019 (match_dup 2)]
15020 {
15021 int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1]));
15022 rtx elt1 = XVECEXP (operands[1], 0, 1);
15023
15024 if (unit_size > 2)
15025 operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]);
15026 else
15027 {
15028 if (unit_size < 2)
15029 operands[0] = gen_rtx_REG (V4HImode, true_regnum (operands[0]));
15030 operands[2] = gen_mperm_w0 (operands[0], operands[0]);
15031 }
15032 operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0]));
15033 operands[1] = XVECEXP (operands[1], 0, 0);
15034 if (unit_size < 2)
15035 {
15036 if (CONST_INT_P (operands[1]) && CONST_INT_P (elt1))
15037 operands[1]
15038 = GEN_INT (TARGET_LITTLE_ENDIAN
15039 ? (INTVAL (operands[1]) & 0xff) + (INTVAL (elt1) << 8)
15040 : (INTVAL (operands[1]) << 8) + (INTVAL (elt1) & 0xff));
15041 else
15042 {
15043 operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0]));
15044 operands[1]
15045 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1));
15046 }
15047 }
15048 })
15049
15050 (define_split
15051 [(set (match_operand 0 "arith_reg_dest" "")
15052 (match_operand 1 "sh_const_vec" ""))]
15053 "TARGET_SHMEDIA && reload_completed
15054 && GET_MODE (operands[0]) == GET_MODE (operands[1])
15055 && sh_vector_mode_supported_p (GET_MODE (operands[0]))"
15056 [(set (match_dup 0) (match_dup 1))]
15057 {
15058 rtx v = operands[1];
15059 machine_mode new_mode
15060 = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0);
15061
15062 operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0]));
15063 operands[1]
15064 = simplify_subreg (new_mode, operands[1], GET_MODE (operands[1]), 0);
15065 })
15066
15067 (define_expand "movv2hi"
15068 [(set (match_operand:V2HI 0 "general_movdst_operand" "")
15069 (match_operand:V2HI 1 "general_movsrc_operand" ""))]
15070 "TARGET_SHMEDIA"
15071 {
15072 prepare_move_operands (operands, V2HImode);
15073 })
15074
15075 (define_insn "movv2hi_i"
15076 [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m")
15077 (match_operand:V2HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15078 "TARGET_SHMEDIA
15079 && (register_operand (operands[0], V2HImode)
15080 || sh_register_operand (operands[1], V2HImode))"
15081 "@
15082 add.l %1, r63, %0
15083 movi %1, %0
15084 #
15085 ld%M1.l %m1, %0
15086 st%M0.l %m0, %N1"
15087 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
15088 (set_attr "length" "4,4,16,4,4")
15089 (set (attr "highpart")
15090 (cond [(match_test "sh_contains_memref_p (insn)")
15091 (const_string "user")]
15092 (const_string "ignore")))])
15093
15094 (define_expand "movv4hi"
15095 [(set (match_operand:V4HI 0 "general_movdst_operand" "")
15096 (match_operand:V4HI 1 "general_movsrc_operand" ""))]
15097 "TARGET_SHMEDIA"
15098 {
15099 prepare_move_operands (operands, V4HImode);
15100 })
15101
15102 (define_insn "movv4hi_i"
15103 [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m")
15104 (match_operand:V4HI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15105 "TARGET_SHMEDIA
15106 && (register_operand (operands[0], V4HImode)
15107 || sh_register_operand (operands[1], V4HImode))"
15108 "@
15109 add %1, r63, %0
15110 movi %1, %0
15111 #
15112 ld%M1.q %m1, %0
15113 st%M0.q %m0, %N1"
15114 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
15115 (set_attr "length" "4,4,16,4,4")
15116 (set_attr "highpart" "depend")])
15117
15118 (define_expand "movv2si"
15119 [(set (match_operand:V2SI 0 "general_movdst_operand" "")
15120 (match_operand:V2SI 1 "general_movsrc_operand" ""))]
15121 "TARGET_SHMEDIA"
15122 {
15123 prepare_move_operands (operands, V2SImode);
15124 })
15125
15126 (define_insn "movv2si_i"
15127 [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m")
15128 (match_operand:V2SI 1 "general_movsrc_operand" "r,I16CssZ,nW,m,rlZ"))]
15129 "TARGET_SHMEDIA
15130 && (register_operand (operands[0], V2SImode)
15131 || sh_register_operand (operands[1], V2SImode))"
15132 "@
15133 add %1, r63, %0
15134 #
15135 #
15136 ld%M1.q %m1, %0
15137 st%M0.q %m0, %N1"
15138 [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
15139 (set_attr "length" "4,4,16,4,4")
15140 (set_attr "highpart" "depend")])
15141
15142 ;; -------------------------------------------------------------------------
15143 ;; Multimedia Intrinsics
15144 ;; -------------------------------------------------------------------------
15145
15146 (define_insn "absv2si2"
15147 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15148 (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))]
15149 "TARGET_SHMEDIA"
15150 "mabs.l %1, %0"
15151 [(set_attr "type" "mcmp_media")
15152 (set_attr "highpart" "depend")])
15153
15154 (define_insn "absv4hi2"
15155 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15156 (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))]
15157 "TARGET_SHMEDIA"
15158 "mabs.w %1, %0"
15159 [(set_attr "type" "mcmp_media")
15160 (set_attr "highpart" "depend")])
15161
15162 (define_insn "addv2si3"
15163 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15164 (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
15165 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15166 "TARGET_SHMEDIA"
15167 "madd.l %1, %2, %0"
15168 [(set_attr "type" "arith_media")
15169 (set_attr "highpart" "depend")])
15170
15171 (define_insn "addv4hi3"
15172 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15173 (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
15174 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15175 "TARGET_SHMEDIA"
15176 "madd.w %1, %2, %0"
15177 [(set_attr "type" "arith_media")
15178 (set_attr "highpart" "depend")])
15179
15180 (define_insn_and_split "addv2hi3"
15181 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
15182 (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r")
15183 (match_operand:V2HI 2 "extend_reg_operand" "r")))]
15184 "TARGET_SHMEDIA"
15185 "#"
15186 "TARGET_SHMEDIA"
15187 [(const_int 0)]
15188 {
15189 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
15190 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
15191 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
15192 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
15193 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
15194
15195 emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1));
15196 emit_insn (gen_truncdisi2 (si_dst, di_dst));
15197 DONE;
15198 }
15199 [(set_attr "highpart" "must_split")])
15200
15201 (define_insn "ssaddv2si3"
15202 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15203 (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r")
15204 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15205 "TARGET_SHMEDIA"
15206 "madds.l %1, %2, %0"
15207 [(set_attr "type" "mcmp_media")
15208 (set_attr "highpart" "depend")])
15209
15210 (define_insn "usaddv8qi3"
15211 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15212 (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r")
15213 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
15214 "TARGET_SHMEDIA"
15215 "madds.ub %1, %2, %0"
15216 [(set_attr "type" "mcmp_media")
15217 (set_attr "highpart" "depend")])
15218
15219 (define_insn "ssaddv4hi3"
15220 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15221 (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r")
15222 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15223 "TARGET_SHMEDIA"
15224 "madds.w %1, %2, %0"
15225 [(set_attr "type" "mcmp_media")
15226 (set_attr "highpart" "depend")])
15227
15228 (define_insn "negcmpeqv8qi"
15229 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15230 (neg:V8QI (eq:V8QI
15231 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
15232 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
15233 "TARGET_SHMEDIA"
15234 "mcmpeq.b %N1, %N2, %0"
15235 [(set_attr "type" "mcmp_media")
15236 (set_attr "highpart" "depend")])
15237
15238 (define_insn "negcmpeqv2si"
15239 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15240 (neg:V2SI (eq:V2SI
15241 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
15242 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
15243 "TARGET_SHMEDIA"
15244 "mcmpeq.l %N1, %N2, %0"
15245 [(set_attr "type" "mcmp_media")
15246 (set_attr "highpart" "depend")])
15247
15248 (define_insn "negcmpeqv4hi"
15249 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15250 (neg:V4HI (eq:V4HI
15251 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
15252 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15253 "TARGET_SHMEDIA"
15254 "mcmpeq.w %N1, %N2, %0"
15255 [(set_attr "type" "mcmp_media")
15256 (set_attr "highpart" "depend")])
15257
15258 (define_insn "negcmpgtuv8qi"
15259 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15260 (neg:V8QI (gtu:V8QI
15261 (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rZ")
15262 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))]
15263 "TARGET_SHMEDIA"
15264 "mcmpgt.ub %N1, %N2, %0"
15265 [(set_attr "type" "mcmp_media")
15266 (set_attr "highpart" "depend")])
15267
15268 (define_insn "negcmpgtv2si"
15269 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15270 (neg:V2SI (gt:V2SI
15271 (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rZ")
15272 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
15273 "TARGET_SHMEDIA"
15274 "mcmpgt.l %N1, %N2, %0"
15275 [(set_attr "type" "mcmp_media")
15276 (set_attr "highpart" "depend")])
15277
15278 (define_insn "negcmpgtv4hi"
15279 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15280 (neg:V4HI (gt:V4HI
15281 (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rZ")
15282 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15283 "TARGET_SHMEDIA"
15284 "mcmpgt.w %N1, %N2, %0"
15285 [(set_attr "type" "mcmp_media")
15286 (set_attr "highpart" "depend")])
15287
15288 (define_insn "mcmv"
15289 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15290 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15291 (match_operand:DI 2 "arith_reg_operand" "r"))
15292 (and:DI (match_operand:DI 3 "arith_reg_operand" "0")
15293 (not:DI (match_dup 2)))))]
15294 "TARGET_SHMEDIA"
15295 "mcmv %N1, %2, %0"
15296 [(set_attr "type" "arith_media")
15297 (set_attr "highpart" "depend")])
15298
15299 (define_insn "mcnvs_lw"
15300 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15301 (vec_concat:V4HI
15302 (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ"))
15303 (ss_truncate:V2HI
15304 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))]
15305 "TARGET_SHMEDIA"
15306 "mcnvs.lw %N1, %N2, %0"
15307 [(set_attr "type" "mcmp_media")])
15308
15309 (define_insn "mcnvs_wb"
15310 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15311 (vec_concat:V8QI
15312 (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
15313 (ss_truncate:V4QI
15314 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15315 "TARGET_SHMEDIA"
15316 "mcnvs.wb %N1, %N2, %0"
15317 [(set_attr "type" "mcmp_media")])
15318
15319 (define_insn "mcnvs_wub"
15320 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
15321 (vec_concat:V8QI
15322 (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ"))
15323 (us_truncate:V4QI
15324 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))]
15325 "TARGET_SHMEDIA"
15326 "mcnvs.wub %N1, %N2, %0"
15327 [(set_attr "type" "mcmp_media")])
15328
15329 (define_insn "mextr_rl"
15330 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15331 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15332 (match_operand:HI 3 "mextr_bit_offset" "i"))
15333 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15334 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
15335 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
15336 {
15337 static char templ[21];
15338 sprintf (templ, "mextr%d %%N1, %%N2, %%0",
15339 (int) INTVAL (operands[3]) >> 3);
15340 return templ;
15341 }
15342 [(set_attr "type" "arith_media")])
15343
15344 (define_insn "*mextr_lr"
15345 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15346 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15347 (match_operand:HI 3 "mextr_bit_offset" "i"))
15348 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
15349 (match_operand:HI 4 "mextr_bit_offset" "i"))))]
15350 "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64"
15351 {
15352 static char templ[21];
15353 sprintf (templ, "mextr%d %%N2, %%N1, %%0",
15354 (int) INTVAL (operands[4]) >> 3);
15355 return templ;
15356 }
15357 [(set_attr "type" "arith_media")])
15358
15359 ; mextrN can be modelled with vec_select / vec_concat, but the selection
15360 ; vector then varies depending on endianness.
15361 (define_expand "mextr1"
15362 [(match_operand:DI 0 "arith_reg_dest" "")
15363 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15364 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15365 "TARGET_SHMEDIA"
15366 {
15367 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15368 GEN_INT (1 * 8), GEN_INT (7 * 8)));
15369 DONE;
15370 })
15371
15372 (define_expand "mextr2"
15373 [(match_operand:DI 0 "arith_reg_dest" "")
15374 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15375 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15376 "TARGET_SHMEDIA"
15377 {
15378 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15379 GEN_INT (2 * 8), GEN_INT (6 * 8)));
15380 DONE;
15381 })
15382
15383 (define_expand "mextr3"
15384 [(match_operand:DI 0 "arith_reg_dest" "")
15385 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15386 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15387 "TARGET_SHMEDIA"
15388 {
15389 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15390 GEN_INT (3 * 8), GEN_INT (5 * 8)));
15391 DONE;
15392 })
15393
15394 (define_expand "mextr4"
15395 [(match_operand:DI 0 "arith_reg_dest" "")
15396 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15397 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15398 "TARGET_SHMEDIA"
15399 {
15400 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15401 GEN_INT (4 * 8), GEN_INT (4 * 8)));
15402 DONE;
15403 })
15404
15405 (define_expand "mextr5"
15406 [(match_operand:DI 0 "arith_reg_dest" "")
15407 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15408 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15409 "TARGET_SHMEDIA"
15410 {
15411 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15412 GEN_INT (5 * 8), GEN_INT (3 * 8)));
15413 DONE;
15414 })
15415
15416 (define_expand "mextr6"
15417 [(match_operand:DI 0 "arith_reg_dest" "")
15418 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15419 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15420 "TARGET_SHMEDIA"
15421 {
15422 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15423 GEN_INT (6 * 8), GEN_INT (2 * 8)));
15424 DONE;
15425 })
15426
15427 (define_expand "mextr7"
15428 [(match_operand:DI 0 "arith_reg_dest" "")
15429 (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
15430 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")]
15431 "TARGET_SHMEDIA"
15432 {
15433 emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
15434 GEN_INT (7 * 8), GEN_INT (1 * 8)));
15435 DONE;
15436 })
15437
15438 (define_expand "mmacfx_wl"
15439 [(match_operand:V2SI 0 "arith_reg_dest" "")
15440 (match_operand:V2HI 1 "extend_reg_operand" "")
15441 (match_operand:V2HI 2 "extend_reg_operand" "")
15442 (match_operand:V2SI 3 "arith_reg_operand" "")]
15443 "TARGET_SHMEDIA"
15444 {
15445 emit_insn (gen_mmacfx_wl_i (operands[0], operands[3],
15446 operands[1], operands[2]));
15447 DONE;
15448 })
15449
15450 ;; This could be highpart ignore if it only had inputs 2 or 3, but input 1
15451 ;; is depend
15452 (define_insn "mmacfx_wl_i"
15453 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15454 (ss_plus:V2SI
15455 (match_operand:V2SI 1 "arith_reg_operand" "0")
15456 (ss_truncate:V2SI
15457 (ashift:V2DI
15458 (sign_extend:V2DI
15459 (mult:V2SI
15460 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
15461 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
15462 (const_int 1)))))]
15463 "TARGET_SHMEDIA"
15464 "mmacfx.wl %2, %3, %0"
15465 [(set_attr "type" "mac_media")
15466 (set_attr "highpart" "depend")])
15467
15468 (define_expand "mmacnfx_wl"
15469 [(match_operand:V2SI 0 "arith_reg_dest" "")
15470 (match_operand:V2HI 1 "extend_reg_operand" "")
15471 (match_operand:V2HI 2 "extend_reg_operand" "")
15472 (match_operand:V2SI 3 "arith_reg_operand" "")]
15473 "TARGET_SHMEDIA"
15474 {
15475 emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3],
15476 operands[1], operands[2]));
15477 DONE;
15478 })
15479
15480 (define_insn "mmacnfx_wl_i"
15481 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15482 (ss_minus:V2SI
15483 (match_operand:V2SI 1 "arith_reg_operand" "0")
15484 (ss_truncate:V2SI
15485 (ashift:V2DI
15486 (sign_extend:V2DI
15487 (mult:V2SI
15488 (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r"))
15489 (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r"))))
15490 (const_int 1)))))]
15491 "TARGET_SHMEDIA"
15492 "mmacnfx.wl %2, %3, %0"
15493 [(set_attr "type" "mac_media")
15494 (set_attr "highpart" "depend")])
15495
15496 (define_insn "mulv2si3"
15497 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15498 (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15499 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
15500 "TARGET_SHMEDIA"
15501 "mmul.l %1, %2, %0"
15502 [(set_attr "type" "d2mpy_media")
15503 (set_attr "highpart" "depend")])
15504
15505 (define_insn "mulv4hi3"
15506 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15507 (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15508 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
15509 "TARGET_SHMEDIA"
15510 "mmul.w %1, %2, %0"
15511 [(set_attr "type" "dmpy_media")
15512 (set_attr "highpart" "depend")])
15513
15514 (define_insn "mmulfx_l"
15515 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15516 (ss_truncate:V2SI
15517 (ashiftrt:V2DI
15518 (mult:V2DI
15519 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
15520 (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r")))
15521 (const_int 31))))]
15522 "TARGET_SHMEDIA"
15523 "mmulfx.l %1, %2, %0"
15524 [(set_attr "type" "d2mpy_media")
15525 (set_attr "highpart" "depend")])
15526
15527 (define_insn "mmulfx_w"
15528 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15529 (ss_truncate:V4HI
15530 (ashiftrt:V4SI
15531 (mult:V4SI
15532 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15533 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15534 (const_int 15))))]
15535 "TARGET_SHMEDIA"
15536 "mmulfx.w %1, %2, %0"
15537 [(set_attr "type" "dmpy_media")
15538 (set_attr "highpart" "depend")])
15539
15540 (define_insn "mmulfxrp_w"
15541 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15542 (ss_truncate:V4HI
15543 (ashiftrt:V4SI
15544 (plus:V4SI
15545 (mult:V4SI
15546 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15547 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15548 (const_int 16384))
15549 (const_int 15))))]
15550 "TARGET_SHMEDIA"
15551 "mmulfxrp.w %1, %2, %0"
15552 [(set_attr "type" "dmpy_media")
15553 (set_attr "highpart" "depend")])
15554
15555
15556 (define_expand "mmulhi_wl"
15557 [(match_operand:V2SI 0 "arith_reg_dest" "")
15558 (match_operand:V4HI 1 "arith_reg_operand" "")
15559 (match_operand:V4HI 2 "arith_reg_operand" "")]
15560 "TARGET_SHMEDIA"
15561 {
15562 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl)
15563 (operands[0], operands[1], operands[2]));
15564 DONE;
15565 })
15566
15567 (define_expand "mmullo_wl"
15568 [(match_operand:V2SI 0 "arith_reg_dest" "")
15569 (match_operand:V4HI 1 "arith_reg_operand" "")
15570 (match_operand:V4HI 2 "arith_reg_operand" "")]
15571 "TARGET_SHMEDIA"
15572 {
15573 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl)
15574 (operands[0], operands[1], operands[2]));
15575 DONE;
15576 })
15577
15578 (define_insn "mmul23_wl"
15579 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15580 (vec_select:V2SI
15581 (mult:V4SI
15582 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15583 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15584 (parallel [(const_int 2) (const_int 3)])))]
15585 "TARGET_SHMEDIA"
15586 {
15587 return (TARGET_LITTLE_ENDIAN
15588 ? "mmulhi.wl %1, %2, %0"
15589 : "mmullo.wl %1, %2, %0");
15590 }
15591 [(set_attr "type" "dmpy_media")
15592 (set (attr "highpart")
15593 (cond [(eq_attr "endian" "big") (const_string "ignore")]
15594 (const_string "user")))])
15595
15596 (define_insn "mmul01_wl"
15597 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15598 (vec_select:V2SI
15599 (mult:V4SI
15600 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15601 (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
15602 (parallel [(const_int 0) (const_int 1)])))]
15603 "TARGET_SHMEDIA"
15604 {
15605 return (TARGET_LITTLE_ENDIAN
15606 ? "mmullo.wl %1, %2, %0"
15607 : "mmulhi.wl %1, %2, %0");
15608 }
15609 [(set_attr "type" "dmpy_media")
15610 (set (attr "highpart")
15611 (cond [(eq_attr "endian" "little") (const_string "ignore")]
15612 (const_string "user")))])
15613
15614
15615 (define_expand "mmulsum_wq"
15616 [(match_operand:DI 0 "arith_reg_dest" "")
15617 (match_operand:V4HI 1 "arith_reg_operand" "")
15618 (match_operand:V4HI 2 "arith_reg_operand" "")
15619 (match_operand:DI 3 "arith_reg_operand" "")]
15620 "TARGET_SHMEDIA"
15621 {
15622 emit_insn (gen_mmulsum_wq_i (operands[0], operands[3],
15623 operands[1], operands[2]));
15624 DONE;
15625 })
15626
15627 (define_insn "mmulsum_wq_i"
15628 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15629 (plus:DI (match_operand:DI 1 "arith_reg_operand" "0")
15630 (plus:DI
15631 (plus:DI
15632 (vec_select:DI
15633 (mult:V4DI
15634 (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
15635 (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
15636 (parallel [(const_int 0)]))
15637 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
15638 (sign_extend:V4DI (match_dup 3)))
15639 (parallel [(const_int 1)])))
15640 (plus:DI
15641 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
15642 (sign_extend:V4DI (match_dup 3)))
15643 (parallel [(const_int 2)]))
15644 (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
15645 (sign_extend:V4DI (match_dup 3)))
15646 (parallel [(const_int 3)]))))))]
15647 "TARGET_SHMEDIA"
15648 "mmulsum.wq %2, %3, %0"
15649 [(set_attr "type" "mac_media")])
15650
15651 (define_expand "mperm_w"
15652 [(match_operand:V4HI 0 "arith_reg_dest" "=r")
15653 (match_operand:V4HI 1 "arith_reg_operand" "r")
15654 (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")]
15655 "TARGET_SHMEDIA"
15656 {
15657 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big)
15658 (operands[0], operands[1], operands[2]));
15659 DONE;
15660 })
15661
15662 ; This use of vec_select isn't exactly correct according to rtl.texi
15663 ; (because not constant), but it seems a straightforward extension.
15664 (define_insn "mperm_w_little"
15665 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15666 (vec_select:V4HI
15667 (match_operand:V4HI 1 "arith_reg_operand" "r")
15668 (parallel
15669 [(zero_extract:QI (match_operand:QI 2 "extend_reg_or_0_operand" "rZ")
15670 (const_int 2) (const_int 0))
15671 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 2))
15672 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 4))
15673 (zero_extract:QI (match_dup 2) (const_int 2) (const_int 6))])))]
15674 "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN"
15675 "mperm.w %1, %N2, %0"
15676 [(set_attr "type" "arith_media")])
15677
15678 (define_insn "mperm_w_big"
15679 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15680 (vec_select:V4HI
15681 (match_operand:V4HI 1 "arith_reg_operand" "r")
15682 (parallel
15683 [(zero_extract:QI (not:QI (match_operand:QI 2
15684 "extend_reg_or_0_operand" "rZ"))
15685 (const_int 2) (const_int 0))
15686 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 2))
15687 (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
15688 (zero_extract:QI (not:QI (match_dup 2))
15689 (const_int 2) (const_int 6))])))]
15690 "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
15691 "mperm.w %1, %N2, %0"
15692 [(set_attr "type" "arith_media")])
15693
15694 (define_insn "mperm_w0"
15695 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15696 (vec_duplicate:V4HI (truncate:HI (match_operand 1
15697 "trunc_hi_operand" "r"))))]
15698 "TARGET_SHMEDIA"
15699 "mperm.w %1, r63, %0"
15700 [(set_attr "type" "arith_media")
15701 (set_attr "highpart" "ignore")])
15702
15703 (define_expand "msad_ubq"
15704 [(match_operand:DI 0 "arith_reg_dest" "")
15705 (match_operand:V8QI 1 "arith_reg_or_0_operand" "")
15706 (match_operand:V8QI 2 "arith_reg_or_0_operand" "")
15707 (match_operand:DI 3 "arith_reg_operand" "")]
15708 "TARGET_SHMEDIA"
15709 {
15710 emit_insn (gen_msad_ubq_i (operands[0], operands[3],
15711 operands[1], operands[2]));
15712 DONE;
15713 })
15714
15715 (define_insn "msad_ubq_i"
15716 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
15717 (plus:DI
15718 (plus:DI
15719 (plus:DI
15720 (plus:DI
15721 (match_operand:DI 1 "arith_reg_operand" "0")
15722 (abs:DI (vec_select:DI
15723 (minus:V8DI
15724 (zero_extend:V8DI
15725 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
15726 (zero_extend:V8DI
15727 (match_operand:V8QI 3 "arith_reg_or_0_operand" "rZ")))
15728 (parallel [(const_int 0)]))))
15729 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15730 (zero_extend:V8DI (match_dup 3)))
15731 (parallel [(const_int 1)]))))
15732 (plus:DI
15733 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15734 (zero_extend:V8DI (match_dup 3)))
15735 (parallel [(const_int 2)])))
15736 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15737 (zero_extend:V8DI (match_dup 3)))
15738 (parallel [(const_int 3)])))))
15739 (plus:DI
15740 (plus:DI
15741 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15742 (zero_extend:V8DI (match_dup 3)))
15743 (parallel [(const_int 4)])))
15744 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15745 (zero_extend:V8DI (match_dup 3)))
15746 (parallel [(const_int 5)]))))
15747 (plus:DI
15748 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15749 (zero_extend:V8DI (match_dup 3)))
15750 (parallel [(const_int 6)])))
15751 (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
15752 (zero_extend:V8DI (match_dup 3)))
15753 (parallel [(const_int 7)])))))))]
15754 "TARGET_SHMEDIA"
15755 "msad.ubq %N2, %N3, %0"
15756 [(set_attr "type" "mac_media")])
15757
15758 (define_insn "mshalds_l"
15759 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15760 (ss_truncate:V2SI
15761 (ashift:V2DI
15762 (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r"))
15763 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
15764 (const_int 31)))))]
15765 "TARGET_SHMEDIA"
15766 "mshalds.l %1, %2, %0"
15767 [(set_attr "type" "mcmp_media")
15768 (set_attr "highpart" "depend")])
15769
15770 (define_insn "mshalds_w"
15771 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15772 (ss_truncate:V4HI
15773 (ashift:V4SI
15774 (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
15775 (and:DI (match_operand:DI 2 "arith_reg_operand" "r")
15776 (const_int 15)))))]
15777 "TARGET_SHMEDIA"
15778 "mshalds.w %1, %2, %0"
15779 [(set_attr "type" "mcmp_media")
15780 (set_attr "highpart" "depend")])
15781
15782 (define_insn "ashrv2si3"
15783 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15784 (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
15785 (match_operand:DI 2 "arith_reg_operand" "r")))]
15786 "TARGET_SHMEDIA"
15787 "mshard.l %1, %2, %0"
15788 [(set_attr "type" "arith_media")
15789 (set_attr "highpart" "depend")])
15790
15791 (define_insn "ashrv4hi3"
15792 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15793 (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
15794 (match_operand:DI 2 "arith_reg_operand" "r")))]
15795 "TARGET_SHMEDIA"
15796 "mshard.w %1, %2, %0"
15797 [(set_attr "type" "arith_media")
15798 (set_attr "highpart" "depend")])
15799
15800 (define_insn "mshards_q"
15801 [(set (match_operand:HI 0 "arith_reg_dest" "=r")
15802 (ss_truncate:HI
15803 (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r")
15804 (match_operand:DI 2 "arith_reg_or_0_operand" "rZ"))))]
15805 "TARGET_SHMEDIA"
15806 "mshards.q %1, %N2, %0"
15807 [(set_attr "type" "mcmp_media")])
15808
15809 (define_expand "mshfhi_b"
15810 [(match_operand:V8QI 0 "arith_reg_dest" "")
15811 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15812 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
15813 "TARGET_SHMEDIA"
15814 {
15815 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b)
15816 (operands[0], operands[1], operands[2]));
15817 DONE;
15818 })
15819
15820 (define_expand "mshflo_b"
15821 [(match_operand:V8QI 0 "arith_reg_dest" "")
15822 (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15823 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ")]
15824 "TARGET_SHMEDIA"
15825 {
15826 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b)
15827 (operands[0], operands[1], operands[2]));
15828 DONE;
15829 })
15830
15831 (define_insn "mshf4_b"
15832 [(set
15833 (match_operand:V8QI 0 "arith_reg_dest" "=r")
15834 (vec_select:V8QI
15835 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15836 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
15837 (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
15838 (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
15839 "TARGET_SHMEDIA"
15840 {
15841 return (TARGET_LITTLE_ENDIAN
15842 ? "mshfhi.b %N1, %N2, %0"
15843 : "mshflo.b %N1, %N2, %0");
15844 }
15845 [(set_attr "type" "arith_media")
15846 (set (attr "highpart")
15847 (cond [(eq_attr "endian" "big") (const_string "ignore")]
15848 (const_string "user")))])
15849
15850 (define_insn "mshf0_b"
15851 [(set
15852 (match_operand:V8QI 0 "arith_reg_dest" "=r")
15853 (vec_select:V8QI
15854 (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
15855 (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))
15856 (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
15857 (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
15858 "TARGET_SHMEDIA"
15859 {
15860 return (TARGET_LITTLE_ENDIAN
15861 ? "mshflo.b %N1, %N2, %0"
15862 : "mshfhi.b %N1, %N2, %0");
15863 }
15864 [(set_attr "type" "arith_media")
15865 (set (attr "highpart")
15866 (cond [(eq_attr "endian" "little") (const_string "ignore")]
15867 (const_string "user")))])
15868
15869 (define_expand "mshfhi_l"
15870 [(match_operand:V2SI 0 "arith_reg_dest" "")
15871 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15872 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
15873 "TARGET_SHMEDIA"
15874 {
15875 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l)
15876 (operands[0], operands[1], operands[2]));
15877 DONE;
15878 })
15879
15880 (define_expand "mshflo_l"
15881 [(match_operand:V2SI 0 "arith_reg_dest" "")
15882 (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15883 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ")]
15884 "TARGET_SHMEDIA"
15885 {
15886 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l)
15887 (operands[0], operands[1], operands[2]));
15888 DONE;
15889 })
15890
15891 (define_insn "mshf4_l"
15892 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15893 (vec_select:V2SI
15894 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15895 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
15896 (parallel [(const_int 1) (const_int 3)])))]
15897 "TARGET_SHMEDIA"
15898 {
15899 return (TARGET_LITTLE_ENDIAN
15900 ? "mshfhi.l %N1, %N2, %0"
15901 : "mshflo.l %N1, %N2, %0");
15902 }
15903 [(set_attr "type" "arith_media")
15904 (set (attr "highpart")
15905 (cond [(eq_attr "endian" "big") (const_string "ignore")]
15906 (const_string "user")))])
15907
15908 (define_insn "mshf0_l"
15909 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
15910 (vec_select:V2SI
15911 (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
15912 (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))
15913 (parallel [(const_int 0) (const_int 2)])))]
15914 "TARGET_SHMEDIA"
15915 {
15916 return (TARGET_LITTLE_ENDIAN
15917 ? "mshflo.l %N1, %N2, %0"
15918 : "mshfhi.l %N1, %N2, %0");
15919 }
15920 [(set_attr "type" "arith_media")
15921 (set (attr "highpart")
15922 (cond [(eq_attr "endian" "little") (const_string "ignore")]
15923 (const_string "user")))])
15924
15925 (define_expand "mshfhi_w"
15926 [(match_operand:V4HI 0 "arith_reg_dest" "")
15927 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15928 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
15929 "TARGET_SHMEDIA"
15930 {
15931 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w)
15932 (operands[0], operands[1], operands[2]));
15933 DONE;
15934 })
15935
15936 (define_expand "mshflo_w"
15937 [(match_operand:V4HI 0 "arith_reg_dest" "")
15938 (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15939 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ")]
15940 "TARGET_SHMEDIA"
15941 {
15942 emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w)
15943 (operands[0], operands[1], operands[2]));
15944 DONE;
15945 })
15946
15947 (define_insn "mshf4_w"
15948 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15949 (vec_select:V4HI
15950 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15951 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
15952 (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
15953 "TARGET_SHMEDIA"
15954 {
15955 return (TARGET_LITTLE_ENDIAN
15956 ? "mshfhi.w %N1, %N2, %0"
15957 : "mshflo.w %N1, %N2, %0");
15958 }
15959 [(set_attr "type" "arith_media")
15960 (set (attr "highpart")
15961 (cond [(eq_attr "endian" "big") (const_string "ignore")]
15962 (const_string "user")))])
15963
15964 (define_insn "mshf0_w"
15965 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15966 (vec_select:V4HI
15967 (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
15968 (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))
15969 (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
15970 "TARGET_SHMEDIA"
15971 {
15972 return (TARGET_LITTLE_ENDIAN
15973 ? "mshflo.w %N1, %N2, %0"
15974 : "mshfhi.w %N1, %N2, %0");
15975 }
15976 [(set_attr "type" "arith_media")
15977 (set (attr "highpart")
15978 (cond [(eq_attr "endian" "little") (const_string "ignore")]
15979 (const_string "user")))])
15980
15981 (define_insn "mshflo_w_x"
15982 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
15983 (vec_select:V4HI
15984 (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rZ")
15985 (match_operand:V2HI 2 "extend_reg_or_0_operand" "rZ"))
15986 (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))]
15987 "TARGET_SHMEDIA"
15988 "mshflo.w %N1, %N2, %0"
15989 [(set_attr "type" "arith_media")
15990 (set_attr "highpart" "ignore")])
15991
15992 ;; These are useful to expand ANDs and as combiner patterns.
15993 (define_insn_and_split "mshfhi_l_di"
15994 [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
15995 (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
15996 (const_int 32))
15997 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ,?f")
15998 (const_int -4294967296))))]
15999 "TARGET_SHMEDIA"
16000 "@
16001 mshfhi.l %N1, %N2, %0
16002 #"
16003 "TARGET_SHMEDIA && reload_completed
16004 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
16005 [(set (match_dup 3) (match_dup 4))
16006 (set (match_dup 5) (match_dup 6))]
16007 {
16008 operands[3] = gen_lowpart (SImode, operands[0]);
16009 operands[4] = gen_highpart (SImode, operands[1]);
16010 operands[5] = gen_highpart (SImode, operands[0]);
16011 operands[6] = gen_highpart (SImode, operands[2]);
16012 }
16013 [(set_attr "type" "arith_media")])
16014
16015 (define_insn "*mshfhi_l_di_rev"
16016 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16017 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16018 (const_int -4294967296))
16019 (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16020 (const_int 32))))]
16021 "TARGET_SHMEDIA"
16022 "mshfhi.l %N2, %N1, %0"
16023 [(set_attr "type" "arith_media")])
16024
16025 (define_split
16026 [(set (match_operand:DI 0 "arith_reg_dest" "")
16027 (ior:DI (zero_extend:DI (match_operand:SI 1
16028 "extend_reg_or_0_operand" ""))
16029 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "")
16030 (const_int -4294967296))))
16031 (clobber (match_operand:DI 3 "arith_reg_dest" ""))]
16032 "TARGET_SHMEDIA"
16033 [(const_int 0)]
16034 {
16035 emit_insn (gen_ashldi3_media (operands[3],
16036 simplify_gen_subreg (DImode, operands[1],
16037 SImode, 0),
16038 GEN_INT (32)));
16039 emit_insn (gen_mshfhi_l_di (operands[0], operands[3], operands[2]));
16040 DONE;
16041 })
16042
16043 (define_insn "mshflo_l_di"
16044 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16045 (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16046 (const_int 4294967295))
16047 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16048 (const_int 32))))]
16049
16050 "TARGET_SHMEDIA"
16051 "mshflo.l %N1, %N2, %0"
16052 [(set_attr "type" "arith_media")
16053 (set_attr "highpart" "ignore")])
16054
16055 (define_insn "*mshflo_l_di_rev"
16056 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16057 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16058 (const_int 32))
16059 (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16060 (const_int 4294967295))))]
16061
16062 "TARGET_SHMEDIA"
16063 "mshflo.l %N2, %N1, %0"
16064 [(set_attr "type" "arith_media")
16065 (set_attr "highpart" "ignore")])
16066
16067 ;; Combiner pattern for trampoline initialization.
16068 (define_insn_and_split "*double_shori"
16069 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16070 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
16071 (const_int 32))
16072 (match_operand:DI 2 "const_int_operand" "n")))]
16073 "TARGET_SHMEDIA
16074 && ! (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xffffffffUL)"
16075 "#"
16076 "rtx_equal_p (operands[0], operands[1])"
16077 [(const_int 0)]
16078 {
16079 HOST_WIDE_INT v = INTVAL (operands[2]);
16080
16081 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v >> 16)));
16082 emit_insn (gen_shori_media (operands[0], operands[0], GEN_INT (v & 65535)));
16083 DONE;
16084 }
16085 [(set_attr "highpart" "ignore")])
16086
16087 (define_insn "*mshflo_l_di_x"
16088 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16089 (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
16090 "rZ"))
16091 (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rZ")
16092 (const_int 32))))]
16093 "TARGET_SHMEDIA"
16094 "mshflo.l %N1, %N2, %0"
16095 [(set_attr "type" "arith_media")
16096 (set_attr "highpart" "ignore")])
16097
16098 (define_insn_and_split "concat_v2sf"
16099 [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
16100 ;; (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,0,f")
16101 (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rZ,f,f")
16102 (match_operand:SF 2 "register_operand" "rZ,f,f")))]
16103 "TARGET_SHMEDIA"
16104 "@
16105 mshflo.l %N1, %N2, %0
16106 #
16107 #"
16108 "TARGET_SHMEDIA && reload_completed
16109 && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
16110 [(set (match_dup 3) (match_dup 1))
16111 (set (match_dup 4) (match_dup 2))]
16112 {
16113 operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
16114 operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
16115 }
16116 [(set_attr "type" "arith_media")
16117 (set_attr "highpart" "ignore")])
16118
16119 (define_insn "*mshflo_l_di_x_rev"
16120 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16121 (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ")
16122 (const_int 32))
16123 (zero_extend:DI
16124 (match_operand:SI 2 "extend_reg_or_0_operand" "rZ"))))]
16125 "TARGET_SHMEDIA"
16126 "mshflo.l %N2, %N1, %0"
16127 [(set_attr "type" "arith_media")
16128 (set_attr "highpart" "ignore")])
16129
16130 (define_insn "ashlv2si3"
16131 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16132 (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
16133 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16134 "TARGET_SHMEDIA"
16135 "mshlld.l %1, %2, %0"
16136 [(set_attr "type" "arith_media")
16137 (set_attr "highpart" "depend")])
16138
16139 (define_split
16140 [(set (match_operand 0 "any_register_operand" "")
16141 (match_operator 3 "shift_operator"
16142 [(match_operand 1 "any_register_operand" "")
16143 (match_operand 2 "shift_count_reg_operand" "")]))]
16144 "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)"
16145 [(set (match_dup 0) (match_dup 3))]
16146 {
16147 rtx count = operands[2];
16148 machine_mode outer_mode = GET_MODE (operands[2]), inner_mode;
16149
16150 while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND
16151 || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0)
16152 || GET_CODE (count) == TRUNCATE)
16153 count = XEXP (count, 0);
16154 inner_mode = GET_MODE (count);
16155 count = simplify_gen_subreg (outer_mode, count, inner_mode,
16156 subreg_lowpart_offset (outer_mode, inner_mode));
16157 operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
16158 operands[1], count);
16159 })
16160
16161 (define_insn "ashlv4hi3"
16162 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16163 (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
16164 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16165 "TARGET_SHMEDIA"
16166 "mshlld.w %1, %2, %0"
16167 [(set_attr "type" "arith_media")
16168 (set_attr "highpart" "depend")])
16169
16170 (define_insn "lshrv2si3"
16171 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16172 (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")
16173 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16174 "TARGET_SHMEDIA"
16175 "mshlrd.l %1, %2, %0"
16176 [(set_attr "type" "arith_media")
16177 (set_attr "highpart" "depend")])
16178
16179 (define_insn "lshrv4hi3"
16180 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16181 (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")
16182 (match_operand:DI 2 "shift_count_reg_operand" "r")))]
16183 "TARGET_SHMEDIA"
16184 "mshlrd.w %1, %2, %0"
16185 [(set_attr "type" "arith_media")
16186 (set_attr "highpart" "depend")])
16187
16188 (define_insn "subv2si3"
16189 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16190 (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16191 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
16192 "TARGET_SHMEDIA"
16193 "msub.l %N1, %2, %0"
16194 [(set_attr "type" "arith_media")
16195 (set_attr "highpart" "depend")])
16196
16197 (define_insn "subv4hi3"
16198 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16199 (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16200 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
16201 "TARGET_SHMEDIA"
16202 "msub.w %N1, %2, %0"
16203 [(set_attr "type" "arith_media")
16204 (set_attr "highpart" "depend")])
16205
16206 (define_insn_and_split "subv2hi3"
16207 [(set (match_operand:V2HI 0 "arith_reg_dest" "=r")
16208 (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ")
16209 (match_operand:V2HI 2 "arith_reg_operand" "r")))]
16210 "TARGET_SHMEDIA"
16211 "#"
16212 "TARGET_SHMEDIA"
16213 [(const_int 0)]
16214 {
16215 rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0);
16216 rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0);
16217 rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0);
16218 rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0);
16219 rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0);
16220
16221 emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1));
16222 emit_insn (gen_truncdisi2 (si_dst, di_dst));
16223 DONE;
16224 }
16225 [(set_attr "highpart" "must_split")])
16226
16227 (define_insn "sssubv2si3"
16228 [(set (match_operand:V2SI 0 "arith_reg_dest" "=r")
16229 (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rZ")
16230 (match_operand:V2SI 2 "arith_reg_operand" "r")))]
16231 "TARGET_SHMEDIA"
16232 "msubs.l %N1, %2, %0"
16233 [(set_attr "type" "mcmp_media")
16234 (set_attr "highpart" "depend")])
16235
16236 (define_insn "ussubv8qi3"
16237 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
16238 (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ")
16239 (match_operand:V8QI 2 "arith_reg_operand" "r")))]
16240 "TARGET_SHMEDIA"
16241 "msubs.ub %N1, %2, %0"
16242 [(set_attr "type" "mcmp_media")
16243 (set_attr "highpart" "depend")])
16244
16245 (define_insn "sssubv4hi3"
16246 [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
16247 (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rZ")
16248 (match_operand:V4HI 2 "arith_reg_operand" "r")))]
16249 "TARGET_SHMEDIA"
16250 "msubs.w %N1, %2, %0"
16251 [(set_attr "type" "mcmp_media")
16252 (set_attr "highpart" "depend")])
16253
16254 ;; -------------------------------------------------------------------------
16255 ;; Floating Point Intrinsics
16256 ;; -------------------------------------------------------------------------
16257
16258 (define_insn "fcosa_s"
16259 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16260 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
16261 UNSPEC_FCOSA))]
16262 "TARGET_SHMEDIA"
16263 "fcosa.s %1, %0"
16264 [(set_attr "type" "atrans_media")])
16265
16266 (define_insn "fsina_s"
16267 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16268 (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")]
16269 UNSPEC_FSINA))]
16270 "TARGET_SHMEDIA"
16271 "fsina.s %1, %0"
16272 [(set_attr "type" "atrans_media")])
16273
16274 (define_insn "fipr"
16275 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16276 (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1
16277 "fp_arith_reg_operand" "f")
16278 (match_operand:V4SF 2
16279 "fp_arith_reg_operand" "f"))
16280 (parallel [(const_int 0)]))
16281 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
16282 (parallel [(const_int 1)])))
16283 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
16284 (parallel [(const_int 2)]))
16285 (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
16286 (parallel [(const_int 3)])))))]
16287 "TARGET_SHMEDIA"
16288 "fipr.s %1, %2, %0"
16289 [(set_attr "type" "fparith_media")])
16290
16291 (define_insn "fsrra_s"
16292 [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
16293 (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")]
16294 UNSPEC_FSRRA))]
16295 "TARGET_SHMEDIA"
16296 "fsrra.s %1, %0"
16297 [(set_attr "type" "atrans_media")])
16298
16299 (define_insn "ftrv"
16300 [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f")
16301 (plus:V4SF
16302 (plus:V4SF
16303 (mult:V4SF
16304 (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
16305 (parallel [(const_int 0) (const_int 5)
16306 (const_int 10) (const_int 15)]))
16307 (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
16308 (mult:V4SF
16309 (vec_select:V4SF (match_dup 1)
16310 (parallel [(const_int 4) (const_int 9)
16311 (const_int 14) (const_int 3)]))
16312 (vec_select:V4SF (match_dup 2)
16313 (parallel [(const_int 1) (const_int 2)
16314 (const_int 3) (const_int 0)]))))
16315 (plus:V4SF
16316 (mult:V4SF
16317 (vec_select:V4SF (match_dup 1)
16318 (parallel [(const_int 8) (const_int 13)
16319 (const_int 2) (const_int 7)]))
16320 (vec_select:V4SF (match_dup 2)
16321 (parallel [(const_int 2) (const_int 3)
16322 (const_int 0) (const_int 1)])))
16323 (mult:V4SF
16324 (vec_select:V4SF (match_dup 1)
16325 (parallel [(const_int 12) (const_int 1)
16326 (const_int 6) (const_int 11)]))
16327 (vec_select:V4SF (match_dup 2)
16328 (parallel [(const_int 3) (const_int 0)
16329 (const_int 1) (const_int 2)]))))))]
16330 "TARGET_SHMEDIA"
16331 "ftrv.s %1, %2, %0"
16332 [(set_attr "type" "fparith_media")])
16333
16334 (define_insn "ldhi_l"
16335 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16336 (zero_extract:SI
16337 (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
16338 (const_int 3))
16339 (const_int -3)))
16340 (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1))
16341 (const_int 0)))]
16342 "TARGET_SHMEDIA32"
16343 "ldhi.l %U1, %0"
16344 [(set_attr "type" "load_media")])
16345
16346 (define_insn "ldhi_q"
16347 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16348 (zero_extract:DI
16349 (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p")
16350 (const_int 7))
16351 (const_int -7)))
16352 (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1))
16353 (const_int 0)))]
16354 "TARGET_SHMEDIA32"
16355 "ldhi.q %U1, %0"
16356 [(set_attr "type" "load_media")])
16357
16358 (define_insn_and_split "*ldhi_q_comb0"
16359 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16360 (zero_extract:DI
16361 (mem:DI (plus:SI (ior:SI (plus:SI
16362 (match_operand:SI 1 "register_operand" "r")
16363 (match_operand:SI 2 "ua_offset" "I06"))
16364 (const_int 7))
16365 (const_int -7)))
16366 (plus:SI (and:SI (match_dup 1) (const_int 7))
16367 (const_int 1))
16368 (const_int 0)))]
16369 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
16370 "#"
16371 ""
16372 [(pc)]
16373 {
16374 emit_insn (gen_ldhi_q (operands[0],
16375 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16376 DONE;
16377 })
16378
16379 (define_insn_and_split "*ldhi_q_comb1"
16380 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16381 (zero_extract:DI
16382 (mem:DI (plus:SI (ior:SI (plus:SI
16383 (match_operand:SI 1 "register_operand" "r")
16384 (match_operand:SI 2 "ua_offset" "I06"))
16385 (const_int 7))
16386 (const_int -7)))
16387 (plus:SI (and:SI (plus:SI (match_dup 1)
16388 (match_operand:SI 3 "ua_offset" "I06"))
16389 (const_int 7))
16390 (const_int 1))
16391 (const_int 0)))]
16392 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
16393 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
16394 "#"
16395 ""
16396 [(pc)]
16397 {
16398 emit_insn (gen_ldhi_q (operands[0],
16399 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16400 DONE;
16401 })
16402
16403 (define_insn "ldlo_l"
16404 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16405 (zero_extract:SI
16406 (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
16407 (const_int -4)))
16408 (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3)))
16409 (and:SI (match_dup 1) (const_int 3))))]
16410 "TARGET_SHMEDIA32"
16411 "ldlo.l %U1, %0"
16412 [(set_attr "type" "load_media")])
16413
16414 (define_insn "ldlo_q"
16415 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16416 (zero_extract:DI
16417 (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p")
16418 (const_int -8)))
16419 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
16420 (and:SI (match_dup 1) (const_int 7))))]
16421 "TARGET_SHMEDIA32"
16422 "ldlo.q %U1, %0"
16423 [(set_attr "type" "load_media")])
16424
16425 (define_insn_and_split "*ldlo_q_comb0"
16426 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16427 (zero_extract:DI
16428 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
16429 (match_operand:SI 2 "ua_offset" "I06"))
16430 (const_int -8)))
16431 (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7)))
16432 (and:SI (match_dup 1) (const_int 7))))]
16433 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0"
16434 "#"
16435 ""
16436 [(pc)]
16437 {
16438 emit_insn (gen_ldlo_q (operands[0],
16439 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16440 DONE;
16441 })
16442
16443 (define_insn_and_split "*ldlo_q_comb1"
16444 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16445 (zero_extract:DI
16446 (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
16447 (match_operand:SI 2 "ua_offset" "I06"))
16448 (const_int -8)))
16449 (minus:SI (const_int 8)
16450 (and:SI (plus:SI (match_dup 1)
16451 (match_operand:SI 3 "ua_offset" "I06"))
16452 (const_int 7)))
16453 (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))]
16454 "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8)
16455 && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])"
16456 "#"
16457 ""
16458 [(pc)]
16459 {
16460 emit_insn (gen_ldlo_q (operands[0],
16461 gen_rtx_PLUS (SImode, operands[1], operands[2])));
16462 DONE;
16463 })
16464
16465 (define_insn "sthi_l"
16466 [(set (zero_extract:SI
16467 (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
16468 (const_int 3))
16469 (const_int -3)))
16470 (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1))
16471 (const_int 0))
16472 (match_operand:SI 1 "arith_reg_operand" "r"))]
16473 "TARGET_SHMEDIA32"
16474 "sthi.l %U0, %1"
16475 [(set_attr "type" "ustore_media")])
16476
16477 ;; All unaligned stores are considered to be 'narrow' because they typically
16478 ;; operate on less that a quadword, and when they operate on a full quadword,
16479 ;; the vanilla store high / store low sequence will cause a stall if not
16480 ;; scheduled apart.
16481 (define_insn "sthi_q"
16482 [(set (zero_extract:DI
16483 (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p")
16484 (const_int 7))
16485 (const_int -7)))
16486 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
16487 (const_int 0))
16488 (match_operand:DI 1 "arith_reg_operand" "r"))]
16489 "TARGET_SHMEDIA32"
16490 "sthi.q %U0, %1"
16491 [(set_attr "type" "ustore_media")])
16492
16493 (define_insn_and_split "*sthi_q_comb0"
16494 [(set (zero_extract:DI
16495 (mem:DI (plus:SI (ior:SI (plus:SI
16496 (match_operand:SI 0 "register_operand" "r")
16497 (match_operand:SI 1 "ua_offset" "I06"))
16498 (const_int 7))
16499 (const_int -7)))
16500 (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1))
16501 (const_int 0))
16502 (match_operand:DI 2 "arith_reg_operand" "r"))]
16503 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
16504 "#"
16505 ""
16506 [(pc)]
16507 {
16508 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16509 operands[2]));
16510 DONE;
16511 })
16512
16513 (define_insn_and_split "*sthi_q_comb1"
16514 [(set (zero_extract:DI
16515 (mem:DI (plus:SI (ior:SI (plus:SI
16516 (match_operand:SI 0 "register_operand" "r")
16517 (match_operand:SI 1 "ua_offset" "I06"))
16518 (const_int 7))
16519 (const_int -7)))
16520 (plus:SI (and:SI (plus:SI (match_dup 0)
16521 (match_operand:SI 2 "ua_offset" "I06"))
16522 (const_int 7))
16523 (const_int 1))
16524 (const_int 0))
16525 (match_operand:DI 3 "arith_reg_operand" "r"))]
16526 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8)
16527 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
16528 "#"
16529 ""
16530 [(pc)]
16531 {
16532 emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16533 operands[3]));
16534 DONE;
16535 })
16536
16537 ;; This is highpart user because the address is used as full 64 bit.
16538 (define_insn "stlo_l"
16539 [(set (zero_extract:SI
16540 (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
16541 (const_int -4)))
16542 (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3)))
16543 (and:SI (match_dup 0) (const_int 3)))
16544 (match_operand:SI 1 "arith_reg_operand" "r"))]
16545 "TARGET_SHMEDIA32"
16546 "stlo.l %U0, %1"
16547 [(set_attr "type" "ustore_media")])
16548
16549 (define_insn "stlo_q"
16550 [(set (zero_extract:DI
16551 (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p")
16552 (const_int -8)))
16553 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
16554 (and:SI (match_dup 0) (const_int 7)))
16555 (match_operand:DI 1 "arith_reg_operand" "r"))]
16556 "TARGET_SHMEDIA32"
16557 "stlo.q %U0, %1"
16558 [(set_attr "type" "ustore_media")])
16559
16560 (define_insn_and_split "*stlo_q_comb0"
16561 [(set (zero_extract:DI
16562 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
16563 (match_operand:SI 1 "ua_offset" "I06"))
16564 (const_int -8)))
16565 (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7)))
16566 (and:SI (match_dup 0) (const_int 7)))
16567 (match_operand:DI 2 "arith_reg_operand" "r"))]
16568 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0"
16569 "#"
16570 ""
16571 [(pc)]
16572 {
16573 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16574 operands[2]));
16575 DONE;
16576 })
16577
16578 (define_insn_and_split "*stlo_q_comb1"
16579 [(set (zero_extract:DI
16580 (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
16581 (match_operand:SI 1 "ua_offset" "I06"))
16582 (const_int -8)))
16583 (minus:SI (const_int 8)
16584 (and:SI (plus:SI (match_dup 0)
16585 (match_operand:SI 2 "ua_offset" "I06"))
16586 (const_int 7)))
16587 (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7)))
16588 (match_operand:DI 3 "arith_reg_operand" "r"))]
16589 "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])"
16590 "#"
16591 ""
16592 [(pc)]
16593 {
16594 emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]),
16595 operands[3]));
16596 DONE;
16597 })
16598
16599 (define_insn "ldhi_l64"
16600 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16601 (zero_extract:SI
16602 (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
16603 (const_int 3))
16604 (const_int -3)))
16605 (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1))
16606 (const_int 0)))]
16607 "TARGET_SHMEDIA64"
16608 "ldhi.l %U1, %0"
16609 [(set_attr "type" "load_media")])
16610
16611 (define_insn "ldhi_q64"
16612 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16613 (zero_extract:DI
16614 (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p")
16615 (const_int 7))
16616 (const_int -7)))
16617 (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1))
16618 (const_int 0)))]
16619 "TARGET_SHMEDIA64"
16620 "ldhi.q %U1, %0"
16621 [(set_attr "type" "load_media")])
16622
16623 (define_insn "ldlo_l64"
16624 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16625 (zero_extract:SI
16626 (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
16627 (const_int -4)))
16628 (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3)))
16629 (and:DI (match_dup 1) (const_int 3))))]
16630 "TARGET_SHMEDIA64"
16631 "ldlo.l %U1, %0"
16632 [(set_attr "type" "load_media")])
16633
16634 (define_insn "ldlo_q64"
16635 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16636 (zero_extract:DI
16637 (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p")
16638 (const_int -8)))
16639 (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7)))
16640 (and:DI (match_dup 1) (const_int 7))))]
16641 "TARGET_SHMEDIA64"
16642 "ldlo.q %U1, %0"
16643 [(set_attr "type" "load_media")])
16644
16645 (define_insn "sthi_l64"
16646 [(set (zero_extract:SI
16647 (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
16648 (const_int 3))
16649 (const_int -3)))
16650 (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1))
16651 (const_int 0))
16652 (match_operand:SI 1 "arith_reg_operand" "r"))]
16653 "TARGET_SHMEDIA64"
16654 "sthi.l %U0, %1"
16655 [(set_attr "type" "ustore_media")])
16656
16657 (define_insn "sthi_q64"
16658 [(set (zero_extract:DI
16659 (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p")
16660 (const_int 7))
16661 (const_int -7)))
16662 (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1))
16663 (const_int 0))
16664 (match_operand:DI 1 "arith_reg_operand" "r"))]
16665 "TARGET_SHMEDIA64"
16666 "sthi.q %U0, %1"
16667 [(set_attr "type" "ustore_media")])
16668
16669 (define_insn "stlo_l64"
16670 [(set (zero_extract:SI
16671 (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
16672 (const_int -4)))
16673 (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3)))
16674 (and:DI (match_dup 0) (const_int 3)))
16675 (match_operand:SI 1 "arith_reg_operand" "r"))]
16676 "TARGET_SHMEDIA64"
16677 "stlo.l %U0, %1"
16678 [(set_attr "type" "ustore_media")])
16679
16680 (define_insn "stlo_q64"
16681 [(set (zero_extract:DI
16682 (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p")
16683 (const_int -8)))
16684 (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7)))
16685 (and:DI (match_dup 0) (const_int 7)))
16686 (match_operand:DI 1 "arith_reg_operand" "r"))]
16687 "TARGET_SHMEDIA64"
16688 "stlo.q %U0, %1"
16689 [(set_attr "type" "ustore_media")])
16690
16691 (define_insn "nsb"
16692 [(set (match_operand:QI 0 "arith_reg_dest" "=r")
16693 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
16694 UNSPEC_NSB))]
16695 "TARGET_SHMEDIA"
16696 "nsb %1, %0"
16697 [(set_attr "type" "arith_media")])
16698
16699 (define_insn "nsbsi"
16700 [(set (match_operand:SI 0 "arith_reg_dest" "=r")
16701 (zero_extend:SI
16702 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
16703 UNSPEC_NSB)))]
16704 "TARGET_SHMEDIA"
16705 "nsb %1, %0"
16706 [(set_attr "type" "arith_media")])
16707
16708 (define_insn "nsbdi"
16709 [(set (match_operand:DI 0 "arith_reg_dest" "=r")
16710 (zero_extend:DI
16711 (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")]
16712 UNSPEC_NSB)))]
16713 "TARGET_SHMEDIA"
16714 "nsb %1, %0"
16715 [(set_attr "type" "arith_media")])
16716
16717 (define_expand "ffsdi2"
16718 [(set (match_operand:DI 0 "arith_reg_dest" "")
16719 (ffs:DI (match_operand:DI 1 "arith_reg_operand" "")))]
16720 "TARGET_SHMEDIA"
16721 {
16722 rtx scratch = gen_reg_rtx (DImode);
16723 rtx last;
16724
16725 emit_insn (gen_adddi3 (scratch, operands[1], constm1_rtx));
16726 emit_insn (gen_xordi3 (scratch, operands[1], scratch));
16727 emit_insn (gen_lshrdi3_media (scratch, scratch, const1_rtx));
16728 emit_insn (gen_nsbdi (scratch, scratch));
16729 emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
16730 emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
16731 last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
16732 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
16733
16734 DONE;
16735 })
16736
16737 (define_expand "ffssi2"
16738 [(set (match_operand:SI 0 "arith_reg_dest" "")
16739 (ffs:SI (match_operand:SI 1 "arith_reg_operand" "")))]
16740 "TARGET_SHMEDIA"
16741 {
16742 rtx scratch = gen_reg_rtx (SImode);
16743 rtx discratch = gen_reg_rtx (DImode);
16744 rtx last;
16745
16746 emit_insn (gen_adddi3 (discratch,
16747 simplify_gen_subreg (DImode, operands[1], SImode, 0),
16748 constm1_rtx));
16749 emit_insn (gen_andcdi3 (discratch,
16750 simplify_gen_subreg (DImode, operands[1], SImode, 0),
16751 discratch));
16752 emit_insn (gen_nsbsi (scratch, discratch));
16753 last = emit_insn (gen_subsi3 (operands[0],
16754 force_reg (SImode, GEN_INT (63)), scratch));
16755 set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
16756
16757 DONE;
16758 })
16759
16760 (define_insn "byterev"
16761 [(set (match_operand:V8QI 0 "arith_reg_dest" "=r")
16762 (vec_select:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r")
16763 (parallel [(const_int 7) (const_int 6) (const_int 5)
16764 (const_int 4) (const_int 3) (const_int 2)
16765 (const_int 1) (const_int 0)])))]
16766 "TARGET_SHMEDIA"
16767 "byterev %1, %0"
16768 [(set_attr "type" "arith_media")])
16769
16770 ;; In user mode, the "pref" instruction will raise a RADDERR exception
16771 ;; for accesses to [0x80000000,0xffffffff]. This makes it an unsuitable
16772 ;; implementation of __builtin_prefetch for VxWorks RTPs.
16773 (define_expand "prefetch"
16774 [(prefetch (match_operand 0 "address_operand" "")
16775 (match_operand:SI 1 "const_int_operand" "")
16776 (match_operand:SI 2 "const_int_operand" ""))]
16777 "(TARGET_SH2A || TARGET_SH3 || TARGET_SH5)
16778 && (TARGET_SHMEDIA || ! TARGET_VXWORKS_RTP)")
16779
16780 (define_insn "*prefetch"
16781 [(prefetch (match_operand:SI 0 "register_operand" "r")
16782 (match_operand:SI 1 "const_int_operand" "n")
16783 (match_operand:SI 2 "const_int_operand" "n"))]
16784 "(TARGET_SH2A || TARGET_SH3 || TARGET_SHCOMPACT) && ! TARGET_VXWORKS_RTP"
16785 "pref @%0"
16786 [(set_attr "type" "other")])
16787
16788 (define_insn "*prefetch_media"
16789 [(prefetch (match_operand:QI 0 "address_operand" "p")
16790 (match_operand:SI 1 "const_int_operand" "n")
16791 (match_operand:SI 2 "const_int_operand" "n"))]
16792 "TARGET_SHMEDIA"
16793 {
16794 operands[0] = gen_rtx_MEM (QImode, operands[0]);
16795 output_asm_insn ("ld%M0.b %m0,r63", operands);
16796 return "";
16797 }
16798 [(set_attr "type" "other")])
16799
16800 (define_insn "alloco_i"
16801 [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
16802 (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]
16803 "TARGET_SHMEDIA32"
16804 {
16805 rtx xops[2];
16806
16807 if (GET_CODE (operands[0]) == PLUS)
16808 {
16809 xops[0] = XEXP (operands[0], 0);
16810 xops[1] = XEXP (operands[0], 1);
16811 }
16812 else
16813 {
16814 xops[0] = operands[0];
16815 xops[1] = const0_rtx;
16816 }
16817 output_asm_insn ("alloco %0, %1", xops);
16818 return "";
16819 }
16820 [(set_attr "type" "other")])
16821
16822 (define_split
16823 [(set (match_operand 0 "any_register_operand" "")
16824 (match_operand 1 "" ""))]
16825 "TARGET_SHMEDIA && reload_completed"
16826 [(set (match_dup 0) (match_dup 1))]
16827 {
16828 if (!shmedia_cleanup_truncate (operands[1]))
16829 FAIL;
16830 })
16831
16832 ;; -------------------------------------------------------------------------
16833 ;; Stack Protector Patterns
16834 ;; -------------------------------------------------------------------------
16835
16836 (define_expand "stack_protect_set"
16837 [(set (match_operand 0 "memory_operand" "")
16838 (match_operand 1 "memory_operand" ""))]
16839 ""
16840 {
16841 if (TARGET_SHMEDIA)
16842 {
16843 if (TARGET_SHMEDIA64)
16844 emit_insn (gen_stack_protect_set_di_media (operands[0], operands[1]));
16845 else
16846 emit_insn (gen_stack_protect_set_si_media (operands[0], operands[1]));
16847 }
16848 else
16849 emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
16850
16851 DONE;
16852 })
16853
16854 (define_insn "stack_protect_set_si"
16855 [(set (match_operand:SI 0 "memory_operand" "=m")
16856 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
16857 (set (match_scratch:SI 2 "=&r") (const_int 0))]
16858 "!TARGET_SHMEDIA"
16859 {
16860 return "mov.l %1,%2" "\n"
16861 " mov.l %2,%0" "\n"
16862 " mov #0,%2";
16863 }
16864 [(set_attr "type" "other")
16865 (set_attr "length" "6")])
16866
16867 (define_insn "stack_protect_set_si_media"
16868 [(set (match_operand:SI 0 "memory_operand" "=m")
16869 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
16870 (set (match_scratch:SI 2 "=&r") (const_int 0))]
16871 "TARGET_SHMEDIA"
16872 {
16873 return "ld%M1.l %m1,%2" "\n"
16874 " st%M0.l %m0,%2" "\n"
16875 " movi 0,%2";
16876 }
16877 [(set_attr "type" "other")
16878 (set_attr "length" "12")])
16879
16880 (define_insn "stack_protect_set_di_media"
16881 [(set (match_operand:DI 0 "memory_operand" "=m")
16882 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
16883 (set (match_scratch:DI 2 "=&r") (const_int 0))]
16884 "TARGET_SHMEDIA64"
16885 {
16886 return "ld%M1.q %m1,%2" "\n"
16887 " st%M0.q %m0,%2" "\n"
16888 " movi 0,%2";
16889 }
16890 [(set_attr "type" "other")
16891 (set_attr "length" "12")])
16892
16893 (define_expand "stack_protect_test"
16894 [(match_operand 0 "memory_operand" "")
16895 (match_operand 1 "memory_operand" "")
16896 (match_operand 2 "" "")]
16897 ""
16898 {
16899 if (TARGET_SHMEDIA)
16900 {
16901 rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
16902 rtx test;
16903
16904 test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
16905 if (TARGET_SHMEDIA64)
16906 {
16907 emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
16908 operands[1]));
16909 emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
16910 }
16911 else
16912 {
16913 emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
16914 operands[1]));
16915 emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
16916 }
16917 }
16918 else
16919 {
16920 emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
16921 emit_jump_insn (gen_branch_true (operands[2]));
16922 }
16923
16924 DONE;
16925 })
16926
16927 (define_insn "stack_protect_test_si"
16928 [(set (reg:SI T_REG)
16929 (unspec:SI [(match_operand:SI 0 "memory_operand" "m")
16930 (match_operand:SI 1 "memory_operand" "m")]
16931 UNSPEC_SP_TEST))
16932 (set (match_scratch:SI 2 "=&r") (const_int 0))
16933 (set (match_scratch:SI 3 "=&r") (const_int 0))]
16934 "!TARGET_SHMEDIA"
16935 {
16936 return "mov.l %0,%2" "\n"
16937 " mov.l %1,%3" "\n"
16938 " cmp/eq %2,%3" "\n"
16939 " mov #0,%2" "\n"
16940 " mov #0,%3";
16941 }
16942 [(set_attr "type" "other")
16943 (set_attr "length" "10")])
16944
16945 (define_insn "stack_protect_test_si_media"
16946 [(set (match_operand:SI 0 "register_operand" "=&r")
16947 (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
16948 (match_operand:SI 2 "memory_operand" "m")]
16949 UNSPEC_SP_TEST))
16950 (set (match_scratch:SI 3 "=&r") (const_int 0))]
16951 "TARGET_SHMEDIA"
16952 {
16953 return "ld%M1.l %m1,%0" "\n"
16954 " ld%M2.l %m2,%3" "\n"
16955 " cmpeq %0,%3,%0" "\n"
16956 " movi 0,%3";
16957 }
16958 [(set_attr "type" "other")
16959 (set_attr "length" "16")])
16960
16961 (define_insn "stack_protect_test_di_media"
16962 [(set (match_operand:DI 0 "register_operand" "=&r")
16963 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
16964 (match_operand:DI 2 "memory_operand" "m")]
16965 UNSPEC_SP_TEST))
16966 (set (match_scratch:DI 3 "=&r") (const_int 0))]
16967 "TARGET_SHMEDIA64"
16968 {
16969 return "ld%M1.q %m1,%0" "\n"
16970 " ld%M2.q %m2,%3" "\n"
16971 " cmpeq %0,%3,%0" "\n"
16972 " movi 0,%3";
16973 }
16974 [(set_attr "type" "other")
16975 (set_attr "length" "16")])
16976
16977 ;; -------------------------------------------------------------------------
16978 ;; Atomic operations
16979 ;; -------------------------------------------------------------------------
16980
16981 (include "sync.md")